Merge changes from topic "st_regulator" into integration

* changes:
  feat(st-sdmmc2): manage cards power cycle
  feat(stm32mp1): register fixed regulator
  feat(st-drivers): introduce fixed regulator driver
  refactor(st): update CPU and VDD voltage get
  refactor(stm32mp1-fdts): update regulator description
  refactor(st-pmic): use regulator framework for DDR init
  feat(st-pmic): register the PMIC to regulator framework
  refactor(st-pmic): split initialize_pmic()
  feat(stm32mp1): add regulator framework compilation
  feat(regulator): add a regulator framework
  feat(stpmic1): add new services
  feat(stpmic1): add USB OTG regulators
  refactor(st-pmic): improve driver usage
  refactor(stpmic1): set stpmic1_is_regulator_enabled() as boolean
  refactor(stm32mp1): re-order drivers init
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index 9db97d4..1a8bd5b 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -8,10 +8,6 @@
 #include <errno.h>
 #include <string.h>
 
-#include <libfdt.h>
-
-#include <platform_def.h>
-
 #include <arch.h>
 #include <arch_helpers.h>
 #include <common/debug.h>
@@ -23,8 +19,11 @@
 #include <drivers/st/stm32mp_reset.h>
 #include <lib/mmio.h>
 #include <lib/utils.h>
+#include <libfdt.h>
 #include <plat/common/platform.h>
 
+#include <platform_def.h>
+
 /* Registers offsets */
 #define SDMMC_POWER			0x00U
 #define SDMMC_CLKCR			0x04U
@@ -51,6 +50,7 @@
 
 /* SDMMC power control register */
 #define SDMMC_POWER_PWRCTRL		GENMASK(1, 0)
+#define SDMMC_POWER_PWRCTRL_PWR_CYCLE	BIT(1)
 #define SDMMC_POWER_DIRPOL		BIT(4)
 
 /* SDMMC clock control register */
@@ -118,6 +118,13 @@
 #define TIMEOUT_US_10_MS		10000U
 #define TIMEOUT_US_1_S			1000000U
 
+/* Power cycle delays in ms */
+#define VCC_POWER_OFF_DELAY		2
+#define VCC_POWER_ON_DELAY		2
+#define POWER_CYCLE_DELAY		2
+#define POWER_OFF_DELAY			2
+#define POWER_ON_DELAY			1
+
 #define DT_SDMMC2_COMPAT		"st,stm32-sdmmc2"
 
 static void stm32_sdmmc2_init(void);
@@ -155,6 +162,25 @@
 		freq = MIN(sdmmc2_params.max_freq, freq);
 	}
 
+	if (sdmmc2_params.vmmc_regu != NULL) {
+		regulator_disable(sdmmc2_params.vmmc_regu);
+	}
+
+	mdelay(VCC_POWER_OFF_DELAY);
+
+	mmio_write_32(base + SDMMC_POWER,
+		      SDMMC_POWER_PWRCTRL_PWR_CYCLE | sdmmc2_params.dirpol);
+	mdelay(POWER_CYCLE_DELAY);
+
+	if (sdmmc2_params.vmmc_regu != NULL) {
+		regulator_enable(sdmmc2_params.vmmc_regu);
+	}
+
+	mdelay(VCC_POWER_ON_DELAY);
+
+	mmio_write_32(base + SDMMC_POWER, sdmmc2_params.dirpol);
+	mdelay(POWER_OFF_DELAY);
+
 	clock_div = div_round_up(sdmmc2_params.clk_rate, freq * 2U);
 
 	mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div |
@@ -164,7 +190,7 @@
 	mmio_write_32(base + SDMMC_POWER,
 		      SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol);
 
-	mdelay(1);
+	mdelay(POWER_ON_DELAY);
 }
 
 static int stm32_sdmmc2_stop_transfer(void)
@@ -690,6 +716,8 @@
 		sdmmc2_params.max_freq = fdt32_to_cpu(*cuint);
 	}
 
+	sdmmc2_params.vmmc_regu = regulator_get_by_supply_name(fdt, sdmmc_node, "vmmc");
+
 	return 0;
 }
 
@@ -710,6 +738,8 @@
 
 	memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params));
 
+	sdmmc2_params.vmmc_regu = NULL;
+
 	if (stm32_sdmmc2_dt_get_config() != 0) {
 		ERROR("%s: DT error\n", __func__);
 		return -ENOMEM;
diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
index be410a1..6a30dce 100644
--- a/drivers/st/pmic/stm32mp_pmic.c
+++ b/drivers/st/pmic/stm32mp_pmic.c
@@ -4,54 +4,63 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
 #include <errno.h>
 
-#include <libfdt.h>
-
-#include <platform_def.h>
-
 #include <common/debug.h>
 #include <drivers/delay_timer.h>
+#include <drivers/st/regulator.h>
 #include <drivers/st/stm32_i2c.h>
 #include <drivers/st/stm32mp_pmic.h>
 #include <drivers/st/stpmic1.h>
 #include <lib/mmio.h>
 #include <lib/utils_def.h>
-
-#define STPMIC1_LDO12356_OUTPUT_MASK	(uint8_t)(GENMASK(6, 2))
-#define STPMIC1_LDO12356_OUTPUT_SHIFT	2
-#define STPMIC1_LDO3_MODE		(uint8_t)(BIT(7))
-#define STPMIC1_LDO3_DDR_SEL		31U
-#define STPMIC1_LDO3_1800000		(9U << STPMIC1_LDO12356_OUTPUT_SHIFT)
+#include <libfdt.h>
 
-#define STPMIC1_BUCK_OUTPUT_SHIFT	2
-#define STPMIC1_BUCK3_1V8		(39U << STPMIC1_BUCK_OUTPUT_SHIFT)
+#include <platform_def.h>
 
-#define STPMIC1_DEFAULT_START_UP_DELAY_MS	1
+#define PMIC_NODE_NOT_FOUND	1
 
 static struct i2c_handle_s i2c_handle;
 static uint32_t pmic_i2c_addr;
 
+static int register_pmic(void);
+
 static int dt_get_pmic_node(void *fdt)
 {
-	return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
+	static int node = -FDT_ERR_BADOFFSET;
+
+	if (node == -FDT_ERR_BADOFFSET) {
+		node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
+	}
+
+	return node;
 }
 
 int dt_pmic_status(void)
 {
+	static int status = -FDT_ERR_BADVALUE;
 	int node;
 	void *fdt;
 
+	if (status != -FDT_ERR_BADVALUE) {
+		return status;
+	}
+
 	if (fdt_get_address(&fdt) == 0) {
 		return -ENOENT;
 	}
 
 	node = dt_get_pmic_node(fdt);
 	if (node <= 0) {
-		return -FDT_ERR_NOTFOUND;
+		status = -FDT_ERR_NOTFOUND;
+
+		return status;
 	}
 
-	return fdt_get_status(node);
+	status = (int)fdt_get_status(node);
+
+	return status;
 }
 
 static bool dt_pmic_is_secure(void)
@@ -65,125 +74,49 @@
 
 /*
  * Get PMIC and its I2C bus configuration from the device tree.
- * Return 0 on success, negative on error, 1 if no PMIC node is found.
+ * Return 0 on success, negative on error, 1 if no PMIC node is defined.
  */
 static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
 			      struct stm32_i2c_init_s *init)
 {
-	int pmic_node, i2c_node;
+	static int i2c_node = -FDT_ERR_NOTFOUND;
 	void *fdt;
-	const fdt32_t *cuint;
 
 	if (fdt_get_address(&fdt) == 0) {
-		return -ENOENT;
-	}
-
-	pmic_node = dt_get_pmic_node(fdt);
-	if (pmic_node < 0) {
-		return 1;
-	}
-
-	cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
-	if (cuint == NULL) {
 		return -FDT_ERR_NOTFOUND;
 	}
 
-	pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
-	if (pmic_i2c_addr > UINT16_MAX) {
-		return -EINVAL;
-	}
-
-	i2c_node = fdt_parent_offset(fdt, pmic_node);
-	if (i2c_node < 0) {
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	dt_fill_device_info(i2c_info, i2c_node);
-	if (i2c_info->base == 0U) {
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init);
-}
-
-int dt_pmic_configure_boot_on_regulators(void)
-{
-	int pmic_node, regulators_node, regulator_node;
-	void *fdt;
-
-	if (fdt_get_address(&fdt) == 0) {
-		return -ENOENT;
-	}
-
-	pmic_node = dt_get_pmic_node(fdt);
-	if (pmic_node < 0) {
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
-	if (regulators_node < 0) {
-		return -ENOENT;
-	}
-
-	fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
+	if (i2c_node == -FDT_ERR_NOTFOUND) {
+		int pmic_node;
 		const fdt32_t *cuint;
-		const char *node_name = fdt_get_name(fdt, regulator_node, NULL);
-		uint16_t voltage;
-		int status;
 
-#if defined(IMAGE_BL2)
-		if ((fdt_getprop(fdt, regulator_node, "regulator-boot-on",
-				 NULL) == NULL) &&
-		    (fdt_getprop(fdt, regulator_node, "regulator-always-on",
-				 NULL) == NULL)) {
-#else
-		if (fdt_getprop(fdt, regulator_node, "regulator-boot-on",
-				NULL) == NULL) {
-#endif
-			continue;
+		pmic_node = dt_get_pmic_node(fdt);
+		if (pmic_node < 0) {
+			return PMIC_NODE_NOT_FOUND;
 		}
 
-		if (fdt_getprop(fdt, regulator_node, "regulator-pull-down",
-				NULL) != NULL) {
-
-			status = stpmic1_regulator_pull_down_set(node_name);
-			if (status != 0) {
-				return status;
-			}
-		}
-
-		if (fdt_getprop(fdt, regulator_node, "st,mask-reset",
-				NULL) != NULL) {
-
-			status = stpmic1_regulator_mask_reset_set(node_name);
-			if (status != 0) {
-				return status;
-			}
-		}
-
-		cuint = fdt_getprop(fdt, regulator_node,
-				    "regulator-min-microvolt", NULL);
+		cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
 		if (cuint == NULL) {
-			continue;
+			return -FDT_ERR_NOTFOUND;
 		}
 
-		/* DT uses microvolts, whereas driver awaits millivolts */
-		voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
-
-		status = stpmic1_regulator_voltage_set(node_name, voltage);
-		if (status != 0) {
-			return status;
+		pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
+		if (pmic_i2c_addr > UINT16_MAX) {
+			return -FDT_ERR_BADVALUE;
 		}
 
-		if (stpmic1_is_regulator_enabled(node_name) == 0U) {
-			status = stpmic1_regulator_enable(node_name);
-			if (status != 0) {
-				return status;
-			}
+		i2c_node = fdt_parent_offset(fdt, pmic_node);
+		if (i2c_node < 0) {
+			return -FDT_ERR_NOTFOUND;
 		}
 	}
 
-	return 0;
+	dt_fill_device_info(i2c_info, i2c_node);
+	if (i2c_info->base == 0U) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init);
 }
 
 bool initialize_pmic_i2c(void)
@@ -251,8 +184,6 @@
 
 void initialize_pmic(void)
 {
-	unsigned long pmic_version;
-
 	if (!initialize_pmic_i2c()) {
 		VERBOSE("No PMIC\n");
 		return;
@@ -260,70 +191,77 @@
 
 	register_pmic_shared_peripherals();
 
+	if (register_pmic() < 0) {
+		panic();
+	}
+
+	if (stpmic1_powerctrl_on() < 0) {
+		panic();
+	}
+
+}
+
+#if DEBUG
+void print_pmic_info_and_debug(void)
+{
+	unsigned long pmic_version;
+
 	if (stpmic1_get_version(&pmic_version) != 0) {
 		ERROR("Failed to access PMIC\n");
 		panic();
 	}
 
 	INFO("PMIC version = 0x%02lx\n", pmic_version);
-	stpmic1_dump_regulators();
-
-#if defined(IMAGE_BL2)
-	if (dt_pmic_configure_boot_on_regulators() != 0) {
-		panic();
-	};
-#endif
 }
+#endif
 
 int pmic_ddr_power_init(enum ddr_type ddr_type)
 {
-	bool buck3_at_1v8 = false;
-	uint8_t read_val;
 	int status;
+	uint16_t buck3_min_mv;
+	struct rdev *buck2, *buck3, *ldo3, *vref;
 
-	switch (ddr_type) {
-	case STM32MP_DDR3:
-		/* Set LDO3 to sync mode */
-		status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
-		if (status != 0) {
-			return status;
-		}
+	buck2 = regulator_get_by_name("buck2");
+	if (buck2 == NULL) {
+		return -ENOENT;
+	}
 
-		read_val &= ~STPMIC1_LDO3_MODE;
-		read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
-		read_val |= STPMIC1_LDO3_DDR_SEL <<
-			    STPMIC1_LDO12356_OUTPUT_SHIFT;
+	ldo3 = regulator_get_by_name("ldo3");
+	if (ldo3 == NULL) {
+		return -ENOENT;
+	}
 
-		status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
+	vref = regulator_get_by_name("vref_ddr");
+	if (vref == NULL) {
+		return -ENOENT;
+	}
+
+	switch (ddr_type) {
+	case STM32MP_DDR3:
+		status = regulator_set_flag(ldo3, REGUL_SINK_SOURCE);
 		if (status != 0) {
 			return status;
 		}
 
-		status = stpmic1_regulator_voltage_set("buck2", 1350);
+		status = regulator_set_min_voltage(buck2);
 		if (status != 0) {
 			return status;
 		}
 
-		status = stpmic1_regulator_enable("buck2");
+		status = regulator_enable(buck2);
 		if (status != 0) {
 			return status;
 		}
 
-		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
-
-		status = stpmic1_regulator_enable("vref_ddr");
+		status = regulator_enable(vref);
 		if (status != 0) {
 			return status;
 		}
 
-		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
-
-		status = stpmic1_regulator_enable("ldo3");
+		status = regulator_enable(ldo3);
 		if (status != 0) {
 			return status;
 		}
-
-		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
 		break;
 
 	case STM32MP_LPDDR2:
@@ -333,62 +271,215 @@
 		 * Set LDO3 to bypass mode if BUCK3 = 1.8V
 		 * Set LDO3 to normal mode if BUCK3 != 1.8V
 		 */
-		status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val);
-		if (status != 0) {
-			return status;
+		buck3 = regulator_get_by_name("buck3");
+		if (buck3 == NULL) {
+			return -ENOENT;
 		}
 
-		if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) {
-			buck3_at_1v8 = true;
+		regulator_get_range(buck3, &buck3_min_mv, NULL);
+
+		if (buck3_min_mv != 1800) {
+			status = regulator_set_min_voltage(ldo3);
+			if (status != 0) {
+				return status;
+			}
+		} else {
+			status = regulator_set_flag(ldo3, REGUL_ENABLE_BYPASS);
+			if (status != 0) {
+				return status;
+			}
 		}
 
-		status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
+		status = regulator_set_min_voltage(buck2);
 		if (status != 0) {
 			return status;
 		}
 
-		read_val &= ~STPMIC1_LDO3_MODE;
-		read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
-		read_val |= STPMIC1_LDO3_1800000;
-		if (buck3_at_1v8) {
-			read_val |= STPMIC1_LDO3_MODE;
-		}
-
-		status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
+		status = regulator_enable(ldo3);
 		if (status != 0) {
 			return status;
 		}
 
-		status = stpmic1_regulator_voltage_set("buck2", 1200);
+		status = regulator_enable(buck2);
 		if (status != 0) {
 			return status;
 		}
 
-		status = stpmic1_regulator_enable("ldo3");
+		status = regulator_enable(vref);
 		if (status != 0) {
 			return status;
 		}
+		break;
 
-		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+	default:
+		break;
+	};
 
-		status = stpmic1_regulator_enable("buck2");
-		if (status != 0) {
-			return status;
-		}
+	return 0;
+}
 
-		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+enum {
+	STPMIC1_BUCK1 = 0,
+	STPMIC1_BUCK2,
+	STPMIC1_BUCK3,
+	STPMIC1_BUCK4,
+	STPMIC1_LDO1,
+	STPMIC1_LDO2,
+	STPMIC1_LDO3,
+	STPMIC1_LDO4,
+	STPMIC1_LDO5,
+	STPMIC1_LDO6,
+	STPMIC1_VREF_DDR,
+	STPMIC1_BOOST,
+	STPMIC1_VBUS_OTG,
+	STPMIC1_SW_OUT,
+};
 
-		status = stpmic1_regulator_enable("vref_ddr");
-		if (status != 0) {
-			return status;
-		}
+static int pmic_set_state(const struct regul_description *desc, bool enable)
+{
+	VERBOSE("%s: set state to %u\n", desc->node_name, enable);
 
-		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
-		break;
+	if (enable == STATE_ENABLE) {
+		return stpmic1_regulator_enable(desc->node_name);
+	} else {
+		return stpmic1_regulator_disable(desc->node_name);
+	}
+}
+
+static int pmic_get_state(const struct regul_description *desc)
+{
+	VERBOSE("%s: get state\n", desc->node_name);
+
+	return stpmic1_is_regulator_enabled(desc->node_name);
+}
+
+static int pmic_get_voltage(const struct regul_description *desc)
+{
+	VERBOSE("%s: get volt\n", desc->node_name);
+
+	return stpmic1_regulator_voltage_get(desc->node_name);
+}
+
+static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv)
+{
+	VERBOSE("%s: get volt\n", desc->node_name);
+
+	return stpmic1_regulator_voltage_set(desc->node_name, mv);
+}
+
+static int pmic_list_voltages(const struct regul_description *desc,
+			      const uint16_t **levels, size_t *count)
+{
+	VERBOSE("%s: list volt\n", desc->node_name);
+
+	return stpmic1_regulator_levels_mv(desc->node_name, levels, count);
+}
+
+static int pmic_set_flag(const struct regul_description *desc, uint16_t flag)
+{
+	VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag);
+
+	switch (flag) {
+	case REGUL_OCP:
+		return stpmic1_regulator_icc_set(desc->node_name);
+
+	case REGUL_ACTIVE_DISCHARGE:
+		return stpmic1_active_discharge_mode_set(desc->node_name);
+
+	case REGUL_PULL_DOWN:
+		return stpmic1_regulator_pull_down_set(desc->node_name);
+
+	case REGUL_MASK_RESET:
+		return stpmic1_regulator_mask_reset_set(desc->node_name);
+
+	case REGUL_SINK_SOURCE:
+		return stpmic1_regulator_sink_mode_set(desc->node_name);
+
+	case REGUL_ENABLE_BYPASS:
+		return stpmic1_regulator_bypass_mode_set(desc->node_name);
 
 	default:
-		break;
-	};
+		return -EINVAL;
+	}
+}
+
+struct regul_ops pmic_ops = {
+	.set_state = pmic_set_state,
+	.get_state = pmic_get_state,
+	.set_voltage = pmic_set_voltage,
+	.get_voltage = pmic_get_voltage,
+	.list_voltages = pmic_list_voltages,
+	.set_flag = pmic_set_flag,
+};
+
+#define DEFINE_REGU(name) { \
+	.node_name = name, \
+	.ops = &pmic_ops, \
+	.driver_data = NULL, \
+	.enable_ramp_delay = 1000, \
+}
+
+static const struct regul_description pmic_regs[] = {
+	[STPMIC1_BUCK1] = DEFINE_REGU("buck1"),
+	[STPMIC1_BUCK2] = DEFINE_REGU("buck2"),
+	[STPMIC1_BUCK3] = DEFINE_REGU("buck3"),
+	[STPMIC1_BUCK4] = DEFINE_REGU("buck4"),
+	[STPMIC1_LDO1] = DEFINE_REGU("ldo1"),
+	[STPMIC1_LDO2] = DEFINE_REGU("ldo2"),
+	[STPMIC1_LDO3] = DEFINE_REGU("ldo3"),
+	[STPMIC1_LDO4] = DEFINE_REGU("ldo4"),
+	[STPMIC1_LDO5] = DEFINE_REGU("ldo5"),
+	[STPMIC1_LDO6] = DEFINE_REGU("ldo6"),
+	[STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"),
+	[STPMIC1_BOOST] = DEFINE_REGU("boost"),
+	[STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"),
+	[STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"),
+};
+
+#define NB_REG ARRAY_SIZE(pmic_regs)
+
+static int register_pmic(void)
+{
+	void *fdt;
+	int pmic_node, regulators_node, subnode;
+
+	VERBOSE("Register pmic\n");
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	pmic_node = dt_get_pmic_node(fdt);
+	if (pmic_node < 0) {
+		return pmic_node;
+	}
+
+	regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
+	if (regulators_node < 0) {
+		return -ENOENT;
+	}
+
+	fdt_for_each_subnode(subnode, fdt, regulators_node) {
+		const char *reg_name = fdt_get_name(fdt, subnode, NULL);
+		const struct regul_description *desc;
+		unsigned int i;
+		int ret;
+
+		for (i = 0; i < NB_REG; i++) {
+			desc = &pmic_regs[i];
+			if (strcmp(desc->node_name, reg_name) == 0) {
+				break;
+			}
+		}
+		assert(i < NB_REG);
+
+		ret = regulator_register(desc, subnode);
+		if (ret != 0) {
+			WARN("%s:%d failed to register %s\n", __func__,
+			     __LINE__, reg_name);
+			return ret;
+		}
+	}
 
 	return 0;
 }
diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c
index 0a35df3..37eb50b 100644
--- a/drivers/st/pmic/stpmic1.c
+++ b/drivers/st/pmic/stpmic1.c
@@ -23,10 +23,17 @@
 	uint8_t pull_down;
 	uint8_t mask_reset_reg;
 	uint8_t mask_reset;
+	uint8_t icc_reg;
+	uint8_t icc_mask;
 };
 
 static struct i2c_handle_s *pmic_i2c_handle;
 static uint16_t pmic_i2c_addr;
+/*
+ * Special mode corresponds to LDO3 in sink source mode or in bypass mode.
+ * LDO3 doesn't switch back from special to normal mode.
+ */
+static bool ldo3_special_mode;
 
 /* Voltage tables in mV */
 static const uint16_t buck1_voltage_table[] = {
@@ -347,10 +354,13 @@
 	3300,
 	3300,
 	3300,
-	500,
-	0xFFFF, /* VREFDDR */
 };
 
+/* Special mode table is used for sink source OR bypass mode */
+static const uint16_t ldo3_special_mode_table[] = {
+	0,
+};
+
 static const uint16_t ldo5_voltage_table[] = {
 	1700,
 	1700,
@@ -421,6 +431,10 @@
 	3300,
 };
 
+static const uint16_t fixed_5v_voltage_table[] = {
+	5000,
+};
+
 /* Table of Regulators in PMIC SoC */
 static const struct regul_struct regulators_table[] = {
 	{
@@ -434,6 +448,8 @@
 		.pull_down	= BUCK1_PULL_DOWN_SHIFT,
 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
 		.mask_reset	= BUCK1_MASK_RESET,
+		.icc_reg	= BUCK_ICC_TURNOFF_REG,
+		.icc_mask	= BUCK1_ICC_SHIFT,
 	},
 	{
 		.dt_node_name	= "buck2",
@@ -446,6 +462,8 @@
 		.pull_down	= BUCK2_PULL_DOWN_SHIFT,
 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
 		.mask_reset	= BUCK2_MASK_RESET,
+		.icc_reg	= BUCK_ICC_TURNOFF_REG,
+		.icc_mask	= BUCK2_ICC_SHIFT,
 	},
 	{
 		.dt_node_name	= "buck3",
@@ -458,6 +476,8 @@
 		.pull_down	= BUCK3_PULL_DOWN_SHIFT,
 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
 		.mask_reset	= BUCK3_MASK_RESET,
+		.icc_reg	= BUCK_ICC_TURNOFF_REG,
+		.icc_mask	= BUCK3_ICC_SHIFT,
 	},
 	{
 		.dt_node_name	= "buck4",
@@ -470,6 +490,8 @@
 		.pull_down	= BUCK4_PULL_DOWN_SHIFT,
 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
 		.mask_reset	= BUCK4_MASK_RESET,
+		.icc_reg	= BUCK_ICC_TURNOFF_REG,
+		.icc_mask	= BUCK4_ICC_SHIFT,
 	},
 	{
 		.dt_node_name	= "ldo1",
@@ -480,6 +502,8 @@
 		.low_power_reg	= LDO1_PWRCTRL_REG,
 		.mask_reset_reg	= MASK_RESET_LDO_REG,
 		.mask_reset	= LDO1_MASK_RESET,
+		.icc_reg	= LDO_ICC_TURNOFF_REG,
+		.icc_mask	= LDO1_ICC_SHIFT,
 	},
 	{
 		.dt_node_name	= "ldo2",
@@ -490,6 +514,8 @@
 		.low_power_reg	= LDO2_PWRCTRL_REG,
 		.mask_reset_reg	= MASK_RESET_LDO_REG,
 		.mask_reset	= LDO2_MASK_RESET,
+		.icc_reg	= LDO_ICC_TURNOFF_REG,
+		.icc_mask	= LDO2_ICC_SHIFT,
 	},
 	{
 		.dt_node_name	= "ldo3",
@@ -500,6 +526,8 @@
 		.low_power_reg	= LDO3_PWRCTRL_REG,
 		.mask_reset_reg	= MASK_RESET_LDO_REG,
 		.mask_reset	= LDO3_MASK_RESET,
+		.icc_reg	= LDO_ICC_TURNOFF_REG,
+		.icc_mask	= LDO3_ICC_SHIFT,
 	},
 	{
 		.dt_node_name	= "ldo4",
@@ -510,6 +538,8 @@
 		.low_power_reg	= LDO4_PWRCTRL_REG,
 		.mask_reset_reg	= MASK_RESET_LDO_REG,
 		.mask_reset	= LDO4_MASK_RESET,
+		.icc_reg	= LDO_ICC_TURNOFF_REG,
+		.icc_mask	= LDO4_ICC_SHIFT,
 	},
 	{
 		.dt_node_name	= "ldo5",
@@ -520,6 +550,8 @@
 		.low_power_reg	= LDO5_PWRCTRL_REG,
 		.mask_reset_reg	= MASK_RESET_LDO_REG,
 		.mask_reset	= LDO5_MASK_RESET,
+		.icc_reg	= LDO_ICC_TURNOFF_REG,
+		.icc_mask	= LDO5_ICC_SHIFT,
 	},
 	{
 		.dt_node_name	= "ldo6",
@@ -530,6 +562,8 @@
 		.low_power_reg	= LDO6_PWRCTRL_REG,
 		.mask_reset_reg	= MASK_RESET_LDO_REG,
 		.mask_reset	= LDO6_MASK_RESET,
+		.icc_reg	= LDO_ICC_TURNOFF_REG,
+		.icc_mask	= LDO6_ICC_SHIFT,
 	},
 	{
 		.dt_node_name	= "vref_ddr",
@@ -541,6 +575,33 @@
 		.mask_reset_reg	= MASK_RESET_LDO_REG,
 		.mask_reset	= VREF_DDR_MASK_RESET,
 	},
+	{
+		.dt_node_name	= "boost",
+		.voltage_table	= fixed_5v_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
+		.control_reg	= USB_CONTROL_REG,
+		.enable_mask	= BOOST_ENABLED,
+		.icc_reg	= BUCK_ICC_TURNOFF_REG,
+		.icc_mask	= BOOST_ICC_SHIFT,
+	},
+	{
+		.dt_node_name	= "pwr_sw1",
+		.voltage_table	= fixed_5v_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
+		.control_reg	= USB_CONTROL_REG,
+		.enable_mask	= USBSW_OTG_SWITCH_ENABLED,
+		.icc_reg	= BUCK_ICC_TURNOFF_REG,
+		.icc_mask	= PWR_SW1_ICC_SHIFT,
+	},
+	{
+		.dt_node_name	= "pwr_sw2",
+		.voltage_table	= fixed_5v_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
+		.control_reg	= USB_CONTROL_REG,
+		.enable_mask	= SWIN_SWOUT_ENABLED,
+		.icc_reg	= BUCK_ICC_TURNOFF_REG,
+		.icc_mask	= PWR_SW2_ICC_SHIFT,
+	},
 };
 
 #define MAX_REGUL	ARRAY_SIZE(regulators_table)
@@ -606,7 +667,7 @@
 				       regul->enable_mask);
 }
 
-uint8_t stpmic1_is_regulator_enabled(const char *name)
+bool stpmic1_is_regulator_enabled(const char *name)
 {
 	uint8_t val;
 	const struct regul_struct *regul = get_regulator_data(name);
@@ -615,7 +676,7 @@
 		panic();
 	}
 
-	return (val & regul->enable_mask);
+	return (val & regul->enable_mask) == regul->enable_mask;
 }
 
 int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts)
@@ -624,11 +685,21 @@
 	const struct regul_struct *regul = get_regulator_data(name);
 	uint8_t mask;
 
+	if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) {
+		/*
+		 * when the LDO3 is in special mode, we do not change voltage,
+		 * because by setting voltage, the LDO would leaves sink-source
+		 * mode. There is obviously no reason to leave sink-source mode
+		 * at runtime.
+		 */
+		return 0;
+	}
+
 	/* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
 	if (strncmp(name, "buck", 4) == 0) {
 		mask = BUCK_VOLTAGE_MASK;
 	} else if ((strncmp(name, "ldo", 3) == 0) &&
-		   (strncmp(name, "ldo4", 4) != 0)) {
+		   (strncmp(name, "ldo4", 5) != 0)) {
 		mask = LDO_VOLTAGE_MASK;
 	} else {
 		return 0;
@@ -657,12 +728,90 @@
 {
 	const struct regul_struct *regul = get_regulator_data(name);
 
+	if (regul->mask_reset_reg == 0U) {
+		return -EPERM;
+	}
+
 	return stpmic1_register_update(regul->mask_reset_reg,
 				       BIT(regul->mask_reset),
 				       LDO_BUCK_RESET_MASK <<
 				       regul->mask_reset);
 }
 
+int stpmic1_regulator_icc_set(const char *name)
+{
+	const struct regul_struct *regul = get_regulator_data(name);
+
+	if (regul->mask_reset_reg == 0U) {
+		return -EPERM;
+	}
+
+	return stpmic1_register_update(regul->icc_reg,
+				       BIT(regul->icc_mask),
+				       BIT(regul->icc_mask));
+}
+
+int stpmic1_regulator_sink_mode_set(const char *name)
+{
+	if (strncmp(name, "ldo3", 5) != 0) {
+		return -EPERM;
+	}
+
+	ldo3_special_mode = true;
+
+	/* disable bypass mode, enable sink mode */
+	return stpmic1_register_update(LDO3_CONTROL_REG,
+				       LDO3_DDR_SEL << LDO_BUCK_VOLTAGE_SHIFT,
+				       LDO3_BYPASS | LDO_VOLTAGE_MASK);
+}
+
+int stpmic1_regulator_bypass_mode_set(const char *name)
+{
+	if (strncmp(name, "ldo3", 5) != 0) {
+		return -EPERM;
+	}
+
+	ldo3_special_mode = true;
+
+	/* enable bypass mode, disable sink mode */
+	return stpmic1_register_update(LDO3_CONTROL_REG,
+				       LDO3_BYPASS,
+				       LDO3_BYPASS | LDO_VOLTAGE_MASK);
+}
+
+int stpmic1_active_discharge_mode_set(const char *name)
+{
+	if (strncmp(name, "pwr_sw1", 8) == 0) {
+		return stpmic1_register_update(USB_CONTROL_REG,
+					       VBUS_OTG_DISCHARGE,
+					       VBUS_OTG_DISCHARGE);
+	}
+
+	if (strncmp(name, "pwr_sw2", 8) == 0) {
+		return stpmic1_register_update(USB_CONTROL_REG,
+					       SW_OUT_DISCHARGE,
+					       SW_OUT_DISCHARGE);
+	}
+
+	return -EPERM;
+}
+
+int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels,
+				size_t *levels_count)
+{
+	const struct regul_struct *regul = get_regulator_data(name);
+
+	if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) {
+		*levels_count = ARRAY_SIZE(ldo3_special_mode_table);
+		*levels = ldo3_special_mode_table;
+	} else {
+		*levels_count = regul->voltage_table_size;
+		*levels = regul->voltage_table;
+	}
+
+	return 0;
+}
+
 int stpmic1_regulator_voltage_get(const char *name)
 {
 	const struct regul_struct *regul = get_regulator_data(name);
@@ -670,11 +819,15 @@
 	uint8_t mask;
 	int status;
 
+	if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) {
+		return 0;
+	}
+
 	/* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
 	if (strncmp(name, "buck", 4) == 0) {
 		mask = BUCK_VOLTAGE_MASK;
 	} else if ((strncmp(name, "ldo", 3) == 0) &&
-		   (strncmp(name, "ldo4", 4) != 0)) {
+		   (strncmp(name, "ldo4", 5) != 0)) {
 		mask = LDO_VOLTAGE_MASK;
 	} else {
 		return 0;
diff --git a/drivers/st/regulator/regulator_core.c b/drivers/st/regulator/regulator_core.c
new file mode 100644
index 0000000..94b3cef
--- /dev/null
+++ b/drivers/st/regulator/regulator_core.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/regulator.h>
+#include <libfdt.h>
+
+#define MAX_PROPERTY_LEN 64
+
+static struct rdev rdev_array[PLAT_NB_RDEVS];
+
+#define for_each_rdev(rdev) \
+	for (rdev = rdev_array; rdev < (rdev_array + PLAT_NB_RDEVS); rdev++)
+
+#define for_each_registered_rdev(rdev) \
+	for (rdev = rdev_array; \
+	     (rdev < (rdev_array + PLAT_NB_RDEVS)) && (rdev->desc != NULL); rdev++)
+
+static void lock_driver(const struct rdev *rdev)
+{
+	if (rdev->desc->ops->lock != NULL) {
+		rdev->desc->ops->lock(rdev->desc);
+	}
+}
+
+static void unlock_driver(const struct rdev *rdev)
+{
+	if (rdev->desc->ops->unlock != NULL) {
+		rdev->desc->ops->unlock(rdev->desc);
+	}
+}
+
+static struct rdev *regulator_get_by_phandle(int32_t phandle)
+{
+	struct rdev *rdev;
+
+	for_each_registered_rdev(rdev) {
+		if (rdev->phandle == phandle) {
+			return rdev;
+		}
+	}
+
+	WARN("%s: phandle %d not found\n", __func__, phandle);
+	return NULL;
+}
+
+/*
+ * Get a regulator from its node name
+ *
+ * @fdt - pointer to device tree memory
+ * @node_name - name of the node "ldo1"
+ * Return pointer to rdev if succeed, NULL else.
+ */
+struct rdev *regulator_get_by_name(const char *node_name)
+{
+	struct rdev *rdev;
+
+	assert(node_name != NULL);
+	VERBOSE("get %s\n", node_name);
+
+	for_each_registered_rdev(rdev) {
+		if (strcmp(rdev->desc->node_name, node_name) == 0) {
+			return rdev;
+		}
+	}
+
+	WARN("%s: %s not found\n", __func__, node_name);
+	return NULL;
+}
+
+static int32_t get_supply_phandle(const void *fdt, int node, const char *name)
+{
+	const fdt32_t *cuint;
+	int len __unused;
+	int supply_phandle = -FDT_ERR_NOTFOUND;
+	char prop_name[MAX_PROPERTY_LEN];
+
+	len = snprintf(prop_name, MAX_PROPERTY_LEN - 1, "%s-supply", name);
+	assert((len >= 0) && (len < MAX_PROPERTY_LEN - 1));
+
+	cuint = fdt_getprop(fdt, node, prop_name, NULL);
+	if (cuint != NULL) {
+		supply_phandle = fdt32_to_cpu(*cuint);
+		VERBOSE("%s: supplied by %d\n", name, supply_phandle);
+	}
+
+	return supply_phandle;
+}
+
+/*
+ * Get a regulator from a supply name
+ *
+ * @fdt - pointer to device tree memory
+ * @node - offset of the node that contains the supply description
+ * @name - name of the supply "vdd" for "vdd-supply'
+ * Return pointer to rdev if succeed, NULL else.
+ */
+struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name)
+{
+	const int p = get_supply_phandle(fdt, node, name);
+
+	if (p < 0) {
+		return NULL;
+	}
+
+	return regulator_get_by_phandle(p);
+}
+
+static int __regulator_set_state(struct rdev *rdev, bool state)
+{
+	if (rdev->desc->ops->set_state == NULL) {
+		return -ENODEV;
+	}
+
+	return rdev->desc->ops->set_state(rdev->desc, state);
+}
+
+/*
+ * Enable regulator
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_enable(struct rdev *rdev)
+{
+	int ret;
+
+	assert(rdev != NULL);
+
+	ret = __regulator_set_state(rdev, STATE_ENABLE);
+
+	udelay(rdev->enable_ramp_delay);
+
+	return ret;
+}
+
+/*
+ * Disable regulator
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_disable(struct rdev *rdev)
+{
+	int ret;
+
+	assert(rdev != NULL);
+
+	ret = __regulator_set_state(rdev, STATE_DISABLE);
+
+	udelay(rdev->enable_ramp_delay);
+
+	return ret;
+}
+
+/*
+ * Regulator enabled query
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if disabled, 1 if enabled, <0 else.
+ */
+int regulator_is_enabled(const struct rdev *rdev)
+{
+	int ret;
+
+	assert(rdev != NULL);
+
+	VERBOSE("%s: is en\n", rdev->desc->node_name);
+
+	if (rdev->desc->ops->get_state == NULL) {
+		return -ENODEV;
+	}
+
+	lock_driver(rdev);
+
+	ret = rdev->desc->ops->get_state(rdev->desc);
+	if (ret < 0) {
+		ERROR("regul %s get state failed: err:%d\n",
+		      rdev->desc->node_name, ret);
+	}
+
+	unlock_driver(rdev);
+
+	return ret;
+}
+
+/*
+ * Set regulator voltage
+ *
+ * @rdev - pointer to rdev struct
+ * @mvolt - Target voltage level in millivolt
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_set_voltage(struct rdev *rdev, uint16_t mvolt)
+{
+	int ret;
+
+	assert(rdev != NULL);
+
+	VERBOSE("%s: set mvolt\n", rdev->desc->node_name);
+
+	if (rdev->desc->ops->set_voltage == NULL) {
+		return -ENODEV;
+	}
+
+	if ((mvolt < rdev->min_mv) || (mvolt > rdev->max_mv)) {
+		return -EPERM;
+	}
+
+	lock_driver(rdev);
+
+	ret = rdev->desc->ops->set_voltage(rdev->desc, mvolt);
+	if (ret < 0) {
+		ERROR("regul %s set volt failed: err:%d\n",
+		      rdev->desc->node_name, ret);
+	}
+
+	unlock_driver(rdev);
+
+	return ret;
+}
+
+/*
+ * Set regulator min voltage
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_set_min_voltage(struct rdev *rdev)
+{
+	return regulator_set_voltage(rdev, rdev->min_mv);
+}
+
+/*
+ * Get regulator voltage
+ *
+ * @rdev - pointer to rdev struct
+ * Return milli volts if succeed, <0 else.
+ */
+int regulator_get_voltage(const struct rdev *rdev)
+{
+	int ret;
+
+	assert(rdev != NULL);
+
+	VERBOSE("%s: get volt\n", rdev->desc->node_name);
+
+	if (rdev->desc->ops->get_voltage == NULL) {
+		return rdev->min_mv;
+	}
+
+	lock_driver(rdev);
+
+	ret = rdev->desc->ops->get_voltage(rdev->desc);
+	if (ret < 0) {
+		ERROR("regul %s get voltage failed: err:%d\n",
+		      rdev->desc->node_name, ret);
+	}
+
+	unlock_driver(rdev);
+
+	return ret;
+}
+
+/*
+ * List regulator voltages
+ *
+ * @rdev - pointer to rdev struct
+ * @levels - out: array of supported millitvolt levels from min to max value
+ * @count - out: number of possible millivolt values
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count)
+{
+	int ret;
+	size_t n;
+
+	assert(rdev != NULL);
+	assert(levels != NULL);
+	assert(count != NULL);
+
+	VERBOSE("%s: list volt\n", rdev->desc->node_name);
+
+	if (rdev->desc->ops->list_voltages == NULL) {
+		return -ENODEV;
+	}
+
+	lock_driver(rdev);
+
+	ret = rdev->desc->ops->list_voltages(rdev->desc, levels, count);
+
+	unlock_driver(rdev);
+
+	if (ret < 0) {
+		ERROR("regul %s list_voltages failed: err: %d\n",
+		      rdev->desc->node_name, ret);
+		return ret;
+	}
+
+	/*
+	 * Reduce the possible values depending on min and max from device-tree
+	 */
+	n = *count;
+	while ((n > 1U) && ((*levels)[n - 1U] > rdev->max_mv)) {
+		n--;
+	}
+
+	/* Verify that max val is a valid value */
+	if (rdev->max_mv != (*levels)[n - 1]) {
+		ERROR("regul %s: max value %u is invalid\n",
+		      rdev->desc->node_name, rdev->max_mv);
+		return -EINVAL;
+	}
+
+	while ((n > 1U) && ((*levels[0U]) < rdev->min_mv)) {
+		(*levels)++;
+		n--;
+	}
+
+	/* Verify that min is not too high */
+	if (n == 0U) {
+		ERROR("regul %s set min voltage is too high\n",
+		      rdev->desc->node_name);
+		return -EINVAL;
+	}
+
+	/* Verify that min val is a valid vlue */
+	if (rdev->min_mv != (*levels)[0U]) {
+		ERROR("regul %s: min value %u is invalid\n",
+		      rdev->desc->node_name, rdev->min_mv);
+		return -EINVAL;
+	}
+
+	*count = n;
+
+	VERBOSE("rdev->min_mv=%u rdev->max_mv=%u\n", rdev->min_mv, rdev->max_mv);
+
+	return 0;
+}
+
+/*
+ * Get regulator voltages range
+ *
+ * @rdev - pointer to rdev struct
+ * @min_mv - out: min possible millivolt value
+ * @max_mv - out: max possible millivolt value
+ * Return 0 if succeed, non 0 else.
+ */
+void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv)
+{
+	assert(rdev != NULL);
+
+	if (min_mv != NULL) {
+		*min_mv = rdev->min_mv;
+	}
+	if (max_mv != NULL) {
+		*max_mv = rdev->max_mv;
+	}
+}
+
+/*
+ * Set regulator flag
+ *
+ * @rdev - pointer to rdev struct
+ * @flag - flag value to set (eg: REGUL_OCP)
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_set_flag(struct rdev *rdev, uint16_t flag)
+{
+	int ret;
+
+	/* check that only one bit is set on flag */
+	if (__builtin_popcount(flag) != 1) {
+		return -EINVAL;
+	}
+
+	/* REGUL_ALWAYS_ON and REGUL_BOOT_ON are internal properties of the core */
+	if ((flag == REGUL_ALWAYS_ON) || (flag == REGUL_BOOT_ON)) {
+		rdev->flags |= flag;
+		return 0;
+	}
+
+	if (rdev->desc->ops->set_flag == NULL) {
+		ERROR("%s can not set any flag\n", rdev->desc->node_name);
+		return -ENODEV;
+	}
+
+	lock_driver(rdev);
+
+	ret = rdev->desc->ops->set_flag(rdev->desc, flag);
+
+	unlock_driver(rdev);
+
+	if (ret != 0) {
+		ERROR("%s: could not set flag %d ret=%d\n",
+		      rdev->desc->node_name, flag, ret);
+		return ret;
+	}
+
+	rdev->flags |= flag;
+
+	return 0;
+}
+
+/*
+ * Parse the device-tree for a regulator
+ *
+ * Read min/max voltage from dt and check its validity
+ * Read the properties, and call the driver to set flags
+ * Read power supply phandle
+ * Read and store low power mode states
+ *
+ * @rdev - pointer to rdev struct
+ * @node - device-tree node offset of the regulator
+ * Return 0 if disabled, 1 if enabled, <0 else.
+ */
+static int parse_dt(struct rdev *rdev, int node)
+{
+	void *fdt;
+	const fdt32_t *cuint;
+	const uint16_t *levels;
+	size_t size;
+	int ret;
+
+	VERBOSE("%s: parse dt\n", rdev->desc->node_name);
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -ENOENT;
+	}
+
+	rdev->phandle = fdt_get_phandle(fdt, node);
+
+	cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
+	if (cuint != NULL) {
+		uint16_t min_mv;
+
+		min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
+		VERBOSE("%s: min_mv=%d\n", rdev->desc->node_name, (int)min_mv);
+		if (min_mv <= rdev->max_mv) {
+			rdev->min_mv = min_mv;
+		} else {
+			ERROR("%s: min_mv=%d is too high\n",
+			      rdev->desc->node_name, (int)min_mv);
+			return -EINVAL;
+		}
+	}
+
+	cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
+	if (cuint != NULL) {
+		uint16_t max_mv;
+
+		max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
+		VERBOSE("%s: max_mv=%d\n", rdev->desc->node_name, (int)max_mv);
+		if (max_mv >= rdev->min_mv) {
+			rdev->max_mv = max_mv;
+		} else {
+			ERROR("%s: max_mv=%d is too low\n",
+			      rdev->desc->node_name, (int)max_mv);
+			return -EINVAL;
+		}
+	}
+
+	/* validate that min and max values can be used */
+	ret = regulator_list_voltages(rdev, &levels, &size);
+	if ((ret != 0) && (ret != -ENODEV)) {
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Register a regulator driver in regulator framework.
+ * Initialize voltage range from driver description
+ *
+ * @desc - pointer to the regulator description
+ * @node - device-tree node offset of the regulator
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_register(const struct regul_description *desc, int node)
+{
+	struct rdev *rdev;
+
+	assert(desc != NULL);
+
+	VERBOSE("register %s\n", desc->node_name);
+
+	for_each_rdev(rdev) {
+		if (rdev->desc == NULL) {
+			break;
+		}
+	}
+
+	if (rdev == rdev_array + PLAT_NB_RDEVS) {
+		WARN("Not enough place for regulators, PLAT_NB_RDEVS should be increased.\n");
+		return -ENOMEM;
+	}
+
+	rdev->desc = desc;
+	rdev->enable_ramp_delay = rdev->desc->enable_ramp_delay;
+
+	if (rdev->desc->ops->list_voltages != NULL) {
+		int ret;
+		const uint16_t *levels;
+		size_t count;
+
+		lock_driver(rdev);
+
+		ret = rdev->desc->ops->list_voltages(rdev->desc, &levels, &count);
+
+		unlock_driver(rdev);
+
+		if (ret < 0) {
+			ERROR("regul %s set state failed: err:%d\n",
+			      rdev->desc->node_name, ret);
+			return ret;
+		}
+
+		rdev->min_mv = levels[0];
+		rdev->max_mv = levels[count - 1U];
+	} else {
+		rdev->max_mv = UINT16_MAX;
+	}
+
+	return parse_dt(rdev, node);
+}
diff --git a/drivers/st/regulator/regulator_fixed.c b/drivers/st/regulator/regulator_fixed.c
new file mode 100644
index 0000000..f1c224e
--- /dev/null
+++ b/drivers/st/regulator/regulator_fixed.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/st/regulator.h>
+#include <drivers/st/regulator_fixed.h>
+#include <libfdt.h>
+
+#ifndef PLAT_NB_FIXED_REGS
+#error "Missing PLAT_NB_FIXED_REGS"
+#endif
+
+#define FIXED_NAME_LEN 32
+
+struct fixed_data {
+	char name[FIXED_NAME_LEN];
+	uint16_t volt;
+	struct regul_description desc;
+};
+
+static struct fixed_data data[PLAT_NB_FIXED_REGS];
+
+static int fixed_set_state(const struct regul_description *desc, bool state)
+{
+	return 0;
+}
+
+static int fixed_get_state(const struct regul_description *desc)
+{
+	return 1;
+}
+
+static struct regul_ops fixed_ops = {
+	.set_state = fixed_set_state,
+	.get_state = fixed_get_state,
+};
+
+int fixed_regulator_register(void)
+{
+	uint32_t count = 0;
+	void *fdt;
+	int node;
+
+	VERBOSE("fixed reg init!\n");
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	fdt_for_each_compatible_node(fdt, node, "regulator-fixed") {
+		int len __unused;
+		int ret;
+		struct fixed_data *d = &data[count];
+		const char *reg_name;
+
+		reg_name = fdt_get_name(fdt, node, NULL);
+
+		VERBOSE("register fixed reg %s!\n", reg_name);
+
+		len = snprintf(d->name, FIXED_NAME_LEN - 1, "%s", reg_name);
+		assert((len > 0) && (len < (FIXED_NAME_LEN - 1)));
+
+		d->desc.node_name = d->name;
+		d->desc.driver_data = d;
+		d->desc.ops = &fixed_ops;
+
+		ret = regulator_register(&d->desc, node);
+		if (ret != 0) {
+			WARN("%s:%d failed to register %s\n", __func__,
+			     __LINE__, reg_name);
+			return ret;
+		}
+
+		count++;
+		assert(count <= PLAT_NB_FIXED_REGS);
+
+	}
+
+	return 0;
+}
diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts
index 11e0a61..5c9818f 100644
--- a/fdts/stm32mp157c-ed1.dts
+++ b/fdts/stm32mp157c-ed1.dts
@@ -135,14 +135,15 @@
 
 			vtt_ddr: ldo3 {
 				regulator-name = "vtt_ddr";
-				regulator-min-microvolt = <500000>;
-				regulator-max-microvolt = <750000>;
 				regulator-always-on;
 				regulator-over-current-protection;
+				st,regulator-sink-source;
 			};
 
 			vdd_usb: ldo4 {
 				regulator-name = "vdd_usb";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
 			};
 
 			vdd_sd: ldo5 {
diff --git a/fdts/stm32mp15xx-dkx.dtsi b/fdts/stm32mp15xx-dkx.dtsi
index 9cc5368..975d749 100644
--- a/fdts/stm32mp15xx-dkx.dtsi
+++ b/fdts/stm32mp15xx-dkx.dtsi
@@ -131,10 +131,9 @@
 
 			vtt_ddr: ldo3 {
 				regulator-name = "vtt_ddr";
-				regulator-min-microvolt = <500000>;
-				regulator-max-microvolt = <750000>;
 				regulator-always-on;
 				regulator-over-current-protection;
+				st,regulator-sink-source;
 			};
 
 			vdd_usb: ldo4 {
@@ -160,7 +159,6 @@
 			vref_ddr: vref_ddr {
 				regulator-name = "vref_ddr";
 				regulator-always-on;
-				regulator-over-current-protection;
 			};
 
 			bst_out: boost {
diff --git a/include/drivers/st/regulator.h b/include/drivers/st/regulator.h
new file mode 100644
index 0000000..bf583e2
--- /dev/null
+++ b/include/drivers/st/regulator.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef REGULATOR_H
+#define REGULATOR_H
+
+#include <platform_def.h>
+
+#ifndef PLAT_NB_RDEVS
+#error "Missing PLAT_NB_RDEVS"
+#endif
+
+/*
+ * Consumer interface
+ */
+
+/* regulator-always-on : regulator should never be disabled */
+#define REGUL_ALWAYS_ON		BIT(0)
+/*
+ * regulator-boot-on:
+ * It's expected that this regulator was left on by the bootloader.
+ * The core shouldn't prevent it from being turned off later.
+ * The regulator is needed to exit from suspend so it is turned on during suspend entry.
+ */
+#define REGUL_BOOT_ON		BIT(1)
+/* regulator-over-current-protection: Enable over current protection. */
+#define REGUL_OCP		BIT(2)
+/* regulator-active-discharge: enable active discharge. */
+#define REGUL_ACTIVE_DISCHARGE	BIT(3)
+/* regulator-pull-down: Enable pull down resistor when the regulator is disabled. */
+#define REGUL_PULL_DOWN		BIT(4)
+/*
+ * st,mask-reset: set mask reset for the regulator, meaning that the regulator
+ * setting is maintained during pmic reset.
+ */
+#define REGUL_MASK_RESET	BIT(5)
+/* st,regulator-sink-source: set the regulator in sink source mode */
+#define REGUL_SINK_SOURCE	BIT(6)
+/* st,regulator-bypass: set the regulator in bypass mode */
+#define REGUL_ENABLE_BYPASS	BIT(7)
+
+struct rdev *regulator_get_by_name(const char *node_name);
+
+struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name);
+
+int regulator_enable(struct rdev *rdev);
+int regulator_disable(struct rdev *rdev);
+int regulator_is_enabled(const struct rdev *rdev);
+
+int regulator_set_voltage(struct rdev *rdev, uint16_t volt);
+int regulator_set_min_voltage(struct rdev *rdev);
+int regulator_get_voltage(const struct rdev *rdev);
+
+int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count);
+void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv);
+int regulator_set_flag(struct rdev *rdev, uint16_t flag);
+
+/*
+ * Driver Interface
+ */
+
+/* set_state() arguments */
+#define STATE_DISABLE		false
+#define STATE_ENABLE		true
+
+struct regul_description {
+	const char *node_name;
+	const struct regul_ops *ops;
+	const void *driver_data;
+	const char *supply_name;
+	const uint32_t enable_ramp_delay;
+};
+
+struct regul_ops {
+	int (*set_state)(const struct regul_description *desc, bool state);
+	int (*get_state)(const struct regul_description *desc);
+	int (*set_voltage)(const struct regul_description *desc, uint16_t mv);
+	int (*get_voltage)(const struct regul_description *desc);
+	int (*list_voltages)(const struct regul_description *desc,
+			     const uint16_t **levels, size_t *count);
+	int (*set_flag)(const struct regul_description *desc, uint16_t flag);
+	void (*lock)(const struct regul_description *desc);
+	void (*unlock)(const struct regul_description *desc);
+};
+
+int regulator_register(const struct regul_description *desc, int node);
+
+/*
+ * Internal regulator structure
+ * The structure is internal to the core, and the content should not be used
+ * by a consumer nor a driver.
+ */
+struct rdev {
+	const struct regul_description *desc;
+
+	int32_t phandle;
+
+	uint16_t min_mv;
+	uint16_t max_mv;
+
+	uint16_t flags;
+
+	uint32_t enable_ramp_delay;
+};
+
+#endif /* REGULATOR_H */
diff --git a/include/drivers/st/regulator_fixed.h b/include/drivers/st/regulator_fixed.h
new file mode 100644
index 0000000..b981262
--- /dev/null
+++ b/include/drivers/st/regulator_fixed.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef REGULATOR_FIXED_H
+#define REGULATOR_FIXED_H
+
+int fixed_regulator_register(void);
+
+#endif /* REGULATOR_FIXED_H */
diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h
index 4853208..c83f625 100644
--- a/include/drivers/st/stm32_sdmmc2.h
+++ b/include/drivers/st/stm32_sdmmc2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,7 @@
 #include <stdbool.h>
 
 #include <drivers/mmc.h>
+#include <drivers/st/regulator.h>
 
 struct stm32_sdmmc2_params {
 	uintptr_t		reg_base;
@@ -24,6 +25,7 @@
 	unsigned int		reset_id;
 	unsigned int		max_freq;
 	bool			use_dma;
+	struct rdev		*vmmc_regu;
 };
 
 unsigned long long stm32_sdmmc2_mmc_get_device_size(void);
diff --git a/include/drivers/st/stm32mp_pmic.h b/include/drivers/st/stm32mp_pmic.h
index 984cd60..4dfb038 100644
--- a/include/drivers/st/stm32mp_pmic.h
+++ b/include/drivers/st/stm32mp_pmic.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,14 +20,6 @@
 int dt_pmic_status(void);
 
 /*
- * dt_pmic_configure_boot_on_regulators - Configure boot-on and always-on
- * regulators from device tree configuration
- *
- * Returns 0 on success, and negative values on errors
- */
-int dt_pmic_configure_boot_on_regulators(void);
-
-/*
  * initialize_pmic_i2c - Initialize I2C for the PMIC control
  *
  * Returns true if PMIC is available, false if not found, panics on errors
@@ -41,6 +33,14 @@
  */
 void initialize_pmic(void);
 
+#if DEBUG
+void print_pmic_info_and_debug(void);
+#else
+static inline void print_pmic_info_and_debug(void)
+{
+}
+#endif
+
 /*
  * pmic_ddr_power_init - Initialize regulators required for DDR
  *
diff --git a/include/drivers/st/stpmic1.h b/include/drivers/st/stpmic1.h
index dc096cd..2dfc7f8 100644
--- a/include/drivers/st/stpmic1.h
+++ b/include/drivers/st/stpmic1.h
@@ -103,6 +103,22 @@
 #define BUCK4_PULL_DOWN_SHIFT		6
 #define VREF_DDR_PULL_DOWN_SHIFT	4
 
+/* ICC register */
+#define BUCK1_ICC_SHIFT			0
+#define BUCK2_ICC_SHIFT			1
+#define BUCK3_ICC_SHIFT			2
+#define BUCK4_ICC_SHIFT			3
+#define PWR_SW1_ICC_SHIFT		4
+#define PWR_SW2_ICC_SHIFT		5
+#define BOOST_ICC_SHIFT			6
+
+#define LDO1_ICC_SHIFT			0
+#define LDO2_ICC_SHIFT			1
+#define LDO3_ICC_SHIFT			2
+#define LDO4_ICC_SHIFT			3
+#define LDO5_ICC_SHIFT			4
+#define LDO6_ICC_SHIFT			5
+
 /* Buck Mask reset register */
 #define BUCK1_MASK_RESET		0
 #define BUCK2_MASK_RESET		1
@@ -118,6 +134,10 @@
 #define LDO6_MASK_RESET			5
 #define VREF_DDR_MASK_RESET		6
 
+/* LDO3 Special modes */
+#define LDO3_BYPASS                     BIT(7)
+#define LDO3_DDR_SEL                    31U
+
 /* Main PMIC Control Register (MAIN_CONTROL_REG) */
 #define ICC_EVENT_ENABLED		BIT(4)
 #define PWRCTRL_POLARITY_HIGH		BIT(3)
@@ -145,9 +165,12 @@
 /* USB Control Register */
 #define BOOST_OVP_DISABLED		BIT(7)
 #define VBUS_OTG_DETECTION_DISABLED	BIT(6)
+#define SW_OUT_DISCHARGE		BIT(5)
+#define VBUS_OTG_DISCHARGE		BIT(4)
 #define OCP_LIMIT_HIGH			BIT(3)
 #define SWIN_SWOUT_ENABLED		BIT(2)
 #define USBSW_OTG_SWITCH_ENABLED	BIT(1)
+#define BOOST_ENABLED			BIT(0)
 
 int stpmic1_powerctrl_on(void);
 int stpmic1_switch_off(void);
@@ -156,11 +179,17 @@
 int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask);
 int stpmic1_regulator_enable(const char *name);
 int stpmic1_regulator_disable(const char *name);
-uint8_t stpmic1_is_regulator_enabled(const char *name);
+bool stpmic1_is_regulator_enabled(const char *name);
 int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts);
+int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels,
+				size_t *levels_count);
 int stpmic1_regulator_voltage_get(const char *name);
 int stpmic1_regulator_pull_down_set(const char *name);
 int stpmic1_regulator_mask_reset_set(const char *name);
+int stpmic1_regulator_icc_set(const char *name);
+int stpmic1_regulator_sink_mode_set(const char *name);
+int stpmic1_regulator_bypass_mode_set(const char *name);
+int stpmic1_active_discharge_mode_set(const char *name);
 void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr);
 
 int stpmic1_get_version(unsigned long *version);
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h
index f7201c0..a87f941 100644
--- a/plat/st/common/include/stm32mp_dt.h
+++ b/plat/st/common/include/stm32mp_dt.h
@@ -37,6 +37,8 @@
 int dt_match_instance_by_compatible(const char *compatible, uintptr_t address);
 uint32_t dt_get_ddr_size(void);
 uint32_t dt_get_pwr_vdd_voltage(void);
+struct rdev *dt_get_vdd_regulator(void);
+struct rdev *dt_get_cpu_regulator(void);
 const char *dt_get_board_model(void);
 int fdt_get_gpio_bank_pin_count(unsigned int bank);
 
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
index 4dc9908..863a90f 100644
--- a/plat/st/common/stm32mp_dt.c
+++ b/plat/st/common/stm32mp_dt.c
@@ -7,16 +7,15 @@
 #include <assert.h>
 #include <errno.h>
 
-#include <libfdt.h>
-
-#include <platform_def.h>
-
 #include <common/debug.h>
 #include <common/fdt_wrappers.h>
+#include <drivers/st/regulator.h>
 #include <drivers/st/stm32_gpio.h>
 #include <drivers/st/stm32mp1_ddr.h>
 #include <drivers/st/stm32mp1_ram.h>
+#include <libfdt.h>
 
+#include <platform_def.h>
 #include <stm32mp_dt.h>
 
 static void *fdt;
@@ -262,37 +261,46 @@
  ******************************************************************************/
 uint32_t dt_get_pwr_vdd_voltage(void)
 {
-	int node, pwr_regulators_node;
-	const fdt32_t *cuint;
+	struct rdev *regul = dt_get_vdd_regulator();
+	uint16_t min;
 
-	node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
-	if (node < 0) {
-		INFO("%s: Cannot read PWR node in DT\n", __func__);
+	if (regul == NULL) {
 		return 0;
 	}
 
-	pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators");
-	if (pwr_regulators_node < 0) {
-		INFO("%s: Cannot read pwr-regulators node in DT\n", __func__);
-		return 0;
-	}
+	regulator_get_range(regul, &min, NULL);
 
-	cuint = fdt_getprop(fdt, pwr_regulators_node, "vdd-supply", NULL);
-	if (cuint == NULL) {
-		return 0;
-	}
+	return (uint32_t)min * 1000U;
+}
 
-	node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+/*******************************************************************************
+ * This function retrieves VDD supply regulator from DT.
+ * Returns an rdev taken from supply node, NULL otherwise.
+ ******************************************************************************/
+struct rdev *dt_get_vdd_regulator(void)
+{
+	int node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
+
 	if (node < 0) {
-		return 0;
+		return NULL;
 	}
 
-	cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
-	if (cuint == NULL) {
-		return 0;
+	return regulator_get_by_supply_name(fdt, node, "vdd");
+}
+
+/*******************************************************************************
+ * This function retrieves CPU supply regulator from DT.
+ * Returns an rdev taken from supply node, NULL otherwise.
+ ******************************************************************************/
+struct rdev *dt_get_cpu_regulator(void)
+{
+	int node = fdt_path_offset(fdt, "/cpus/cpu@0");
+
+	if (node < 0) {
+		return NULL;
 	}
 
-	return fdt32_to_cpu(*cuint);
+	return regulator_get_by_supply_name(fdt, node, "cpu");
 }
 
 /*******************************************************************************
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 512afa8..bac77bb 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -15,6 +15,7 @@
 #include <drivers/generic_delay_timer.h>
 #include <drivers/mmc.h>
 #include <drivers/st/bsec.h>
+#include <drivers/st/regulator_fixed.h>
 #include <drivers/st/stm32_iwdg.h>
 #include <drivers/st/stm32_uart.h>
 #include <drivers/st/stm32mp1_clk.h>
@@ -130,10 +131,6 @@
 {
 	int ret;
 
-	if (dt_pmic_status() > 0) {
-		initialize_pmic();
-	}
-
 	ret = stm32mp1_ddr_probe();
 	if (ret < 0) {
 		ERROR("Invalid DDR init: error %d\n", ret);
@@ -247,8 +244,6 @@
 		panic();
 	}
 
-	stm32mp1_syscfg_init();
-
 	stm32_save_boot_interface(boot_context->boot_interface_selected,
 				  boot_context->boot_interface_instance);
 
@@ -277,6 +272,17 @@
 	}
 
 skip_console_init:
+	if (fixed_regulator_register() != 0) {
+		panic();
+	}
+
+	if (dt_pmic_status() > 0) {
+		initialize_pmic();
+		print_pmic_info_and_debug();
+	}
+
+	stm32mp1_syscfg_init();
+
 	if (stm32_iwdg_init() < 0) {
 		panic();
 	}
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index aa91646..cc1e0d9 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -201,6 +201,8 @@
 				drivers/st/iwdg/stm32_iwdg.c				\
 				drivers/st/pmic/stm32mp_pmic.c				\
 				drivers/st/pmic/stpmic1.c				\
+				drivers/st/regulator/regulator_core.c			\
+				drivers/st/regulator/regulator_fixed.c			\
 				drivers/st/reset/stm32mp1_reset.c			\
 				plat/st/common/stm32mp_dt.c				\
 				plat/st/stm32mp1/stm32mp1_dbgmcu.c			\
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index f5d4b2f..b43245f 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -461,6 +461,14 @@
 #define SYSCFG_BASE			U(0x50020000)
 
 /*******************************************************************************
+ * REGULATORS
+ ******************************************************************************/
+/* 3 PWR + 1 VREFBUF + 14 PMIC regulators + 1 FIXED */
+#define PLAT_NB_RDEVS			U(19)
+/* 1 FIXED */
+#define PLAT_NB_FIXED_REGS		U(1)
+
+/*******************************************************************************
  * Device Tree defines
  ******************************************************************************/
 #define DT_BSEC_COMPAT			"st,stm32mp15-bsec"