Merge pull request #1466 from Yann-lms/stm32mp1

Add STMicroelectronics STM32MP1 platform support
diff --git a/.gitignore b/.gitignore
index 7f8642e..78da669 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,9 @@
 tools/cert_create/cert_create
 tools/cert_create/cert_create.exe
 tools/doimage/doimage
+tools/stm32image/*.o
+tools/stm32image/stm32image
+tools/stm32image/stm32image.exe
 
 # GNU GLOBAL files
 GPATH
diff --git a/acknowledgements.rst b/acknowledgements.rst
index 5686a58..4d527f4 100644
--- a/acknowledgements.rst
+++ b/acknowledgements.rst
@@ -16,5 +16,7 @@
 
 Marvell International Ltd.
 
+STMicroelectronics
+
 Individuals
 -----------
diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst
new file mode 100644
index 0000000..9e731a4
--- /dev/null
+++ b/docs/plat/stm32mp1.rst
@@ -0,0 +1,82 @@
+Trusted Firmware-A for STM32MP1
+===============================
+
+STM32MP1 is a microprocessor designed by STMicroelectronics
+based on a dual Arm Cortex-A7.
+It is an Armv7-A platform, using dedicated code from TF-A.
+
+
+Design
+------
+The STM32MP1 resets in the ROM code of the Cortex-A7.
+The primary boot core (core 0) executes the boot sequence while
+secondary boot core (core 1) is kept in a holding pen loop.
+The ROM code boot sequence loads the TF-A binary image from boot device
+to embedded SRAM.
+
+The TF-A image must be properly formatted with a STM32 header structure
+for ROM code is able to load this image.
+Tool stm32image can be used to prepend this header to the generated TF-A binary.
+
+At compilation step, BL2, BL32 and DTB file are linked together in a single
+binary. The stm32image tool is also generated and the header is added to TF-A
+binary. This binary file with header is named tf-a-stm32mp157c-ev1.stm32.
+It can then be copied in the first partition of the boot device.
+
+
+Memory mapping
+~~~~~~~~~~~~~~
+
+::
+
+    0x00000000 +-----------------+
+               |                 |   ROM
+    0x00020000 +-----------------+
+               |                 |
+               |       ...       |
+               |                 |
+    0x2FFC0000 +-----------------+ \
+               |                 | |
+               |       ...       | |
+               |                 | |
+    0x2FFD8000 +-----------------+ |
+               |    TF-A DTB     | | Embedded SRAM
+    0x2FFDC000 +-----------------+ |
+               |       BL2       | |
+    0x2FFEF000 +-----------------+ |
+               |       BL32      | |
+    0x30000000 +-----------------+ /
+               |                 |
+               |       ...       |
+               |                 |
+    0x40000000 +-----------------+
+               |                 |
+               |                 |   Devices
+               |                 |
+    0xC0000000 +-----------------+ \
+               |                 | |
+    0xC0100000 +-----------------+ |
+               |       BL33      | | Non-secure RAM (DDR)
+               |       ...       | |
+               |                 | |
+    0xFFFFFFFF +-----------------+ /
+
+
+Boot sequence
+~~~~~~~~~~~~~
+
+ROM code -> BL2 (compiled with BL2_AT_EL3) -> BL32 (SP_min) -> BL33 (U-Boot)
+
+
+Build Instructions
+------------------
+
+To build:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min
+
+The following build options are supported:
+
+- ``ENABLE_STACK_PROTECTOR``: To enable the stack protection.
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/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c
new file mode 100644
index 0000000..eed1d76
--- /dev/null
+++ b/drivers/st/ddr/stm32mp1_ddr.c
@@ -0,0 +1,895 @@
+/*
+ * 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 <debug.h>
+#include <delay_timer.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stddef.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_ddr.h>
+#include <stm32mp1_ddr_regs.h>
+#include <stm32mp1_dt.h>
+#include <stm32mp1_pmic.h>
+#include <stm32mp1_pwr.h>
+#include <stm32mp1_ram.h>
+#include <stm32mp1_rcc.h>
+
+struct reg_desc {
+	const char *name;
+	uint16_t offset;	/* Offset for base address */
+	uint8_t par_offset;	/* Offset for parameter array */
+};
+
+#define INVALID_OFFSET	0xFFU
+
+#define TIMESLOT_1US	(plat_get_syscnt_freq2() / 1000000U)
+
+#define DDRCTL_REG(x, y)					\
+	{							\
+		.name = #x,					\
+		.offset = offsetof(struct stm32mp1_ddrctl, x),	\
+		.par_offset = offsetof(struct y, x)		\
+	}
+
+#define DDRPHY_REG(x, y)					\
+	{							\
+		.name = #x,					\
+		.offset = offsetof(struct stm32mp1_ddrphy, x),	\
+		.par_offset = offsetof(struct y, x)		\
+	}
+
+#define DDRCTL_REG_REG(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_reg)
+static const struct reg_desc ddr_reg[] = {
+	DDRCTL_REG_REG(mstr),
+	DDRCTL_REG_REG(mrctrl0),
+	DDRCTL_REG_REG(mrctrl1),
+	DDRCTL_REG_REG(derateen),
+	DDRCTL_REG_REG(derateint),
+	DDRCTL_REG_REG(pwrctl),
+	DDRCTL_REG_REG(pwrtmg),
+	DDRCTL_REG_REG(hwlpctl),
+	DDRCTL_REG_REG(rfshctl0),
+	DDRCTL_REG_REG(rfshctl3),
+	DDRCTL_REG_REG(crcparctl0),
+	DDRCTL_REG_REG(zqctl0),
+	DDRCTL_REG_REG(dfitmg0),
+	DDRCTL_REG_REG(dfitmg1),
+	DDRCTL_REG_REG(dfilpcfg0),
+	DDRCTL_REG_REG(dfiupd0),
+	DDRCTL_REG_REG(dfiupd1),
+	DDRCTL_REG_REG(dfiupd2),
+	DDRCTL_REG_REG(dfiphymstr),
+	DDRCTL_REG_REG(odtmap),
+	DDRCTL_REG_REG(dbg0),
+	DDRCTL_REG_REG(dbg1),
+	DDRCTL_REG_REG(dbgcmd),
+	DDRCTL_REG_REG(poisoncfg),
+	DDRCTL_REG_REG(pccfg),
+};
+
+#define DDRCTL_REG_TIMING(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_timing)
+static const struct reg_desc ddr_timing[] = {
+	DDRCTL_REG_TIMING(rfshtmg),
+	DDRCTL_REG_TIMING(dramtmg0),
+	DDRCTL_REG_TIMING(dramtmg1),
+	DDRCTL_REG_TIMING(dramtmg2),
+	DDRCTL_REG_TIMING(dramtmg3),
+	DDRCTL_REG_TIMING(dramtmg4),
+	DDRCTL_REG_TIMING(dramtmg5),
+	DDRCTL_REG_TIMING(dramtmg6),
+	DDRCTL_REG_TIMING(dramtmg7),
+	DDRCTL_REG_TIMING(dramtmg8),
+	DDRCTL_REG_TIMING(dramtmg14),
+	DDRCTL_REG_TIMING(odtcfg),
+};
+
+#define DDRCTL_REG_MAP(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_map)
+static const struct reg_desc ddr_map[] = {
+	DDRCTL_REG_MAP(addrmap1),
+	DDRCTL_REG_MAP(addrmap2),
+	DDRCTL_REG_MAP(addrmap3),
+	DDRCTL_REG_MAP(addrmap4),
+	DDRCTL_REG_MAP(addrmap5),
+	DDRCTL_REG_MAP(addrmap6),
+	DDRCTL_REG_MAP(addrmap9),
+	DDRCTL_REG_MAP(addrmap10),
+	DDRCTL_REG_MAP(addrmap11),
+};
+
+#define DDRCTL_REG_PERF(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_perf)
+static const struct reg_desc ddr_perf[] = {
+	DDRCTL_REG_PERF(sched),
+	DDRCTL_REG_PERF(sched1),
+	DDRCTL_REG_PERF(perfhpr1),
+	DDRCTL_REG_PERF(perflpr1),
+	DDRCTL_REG_PERF(perfwr1),
+	DDRCTL_REG_PERF(pcfgr_0),
+	DDRCTL_REG_PERF(pcfgw_0),
+	DDRCTL_REG_PERF(pcfgqos0_0),
+	DDRCTL_REG_PERF(pcfgqos1_0),
+	DDRCTL_REG_PERF(pcfgwqos0_0),
+	DDRCTL_REG_PERF(pcfgwqos1_0),
+	DDRCTL_REG_PERF(pcfgr_1),
+	DDRCTL_REG_PERF(pcfgw_1),
+	DDRCTL_REG_PERF(pcfgqos0_1),
+	DDRCTL_REG_PERF(pcfgqos1_1),
+	DDRCTL_REG_PERF(pcfgwqos0_1),
+	DDRCTL_REG_PERF(pcfgwqos1_1),
+};
+
+#define DDRPHY_REG_REG(x)	DDRPHY_REG(x, stm32mp1_ddrphy_reg)
+static const struct reg_desc ddrphy_reg[] = {
+	DDRPHY_REG_REG(pgcr),
+	DDRPHY_REG_REG(aciocr),
+	DDRPHY_REG_REG(dxccr),
+	DDRPHY_REG_REG(dsgcr),
+	DDRPHY_REG_REG(dcr),
+	DDRPHY_REG_REG(odtcr),
+	DDRPHY_REG_REG(zq0cr1),
+	DDRPHY_REG_REG(dx0gcr),
+	DDRPHY_REG_REG(dx1gcr),
+	DDRPHY_REG_REG(dx2gcr),
+	DDRPHY_REG_REG(dx3gcr),
+};
+
+#define DDRPHY_REG_TIMING(x)	DDRPHY_REG(x, stm32mp1_ddrphy_timing)
+static const struct reg_desc ddrphy_timing[] = {
+	DDRPHY_REG_TIMING(ptr0),
+	DDRPHY_REG_TIMING(ptr1),
+	DDRPHY_REG_TIMING(ptr2),
+	DDRPHY_REG_TIMING(dtpr0),
+	DDRPHY_REG_TIMING(dtpr1),
+	DDRPHY_REG_TIMING(dtpr2),
+	DDRPHY_REG_TIMING(mr0),
+	DDRPHY_REG_TIMING(mr1),
+	DDRPHY_REG_TIMING(mr2),
+	DDRPHY_REG_TIMING(mr3),
+};
+
+#define DDRPHY_REG_CAL(x)	DDRPHY_REG(x, stm32mp1_ddrphy_cal)
+static const struct reg_desc ddrphy_cal[] = {
+	DDRPHY_REG_CAL(dx0dllcr),
+	DDRPHY_REG_CAL(dx0dqtr),
+	DDRPHY_REG_CAL(dx0dqstr),
+	DDRPHY_REG_CAL(dx1dllcr),
+	DDRPHY_REG_CAL(dx1dqtr),
+	DDRPHY_REG_CAL(dx1dqstr),
+	DDRPHY_REG_CAL(dx2dllcr),
+	DDRPHY_REG_CAL(dx2dqtr),
+	DDRPHY_REG_CAL(dx2dqstr),
+	DDRPHY_REG_CAL(dx3dllcr),
+	DDRPHY_REG_CAL(dx3dqtr),
+	DDRPHY_REG_CAL(dx3dqstr),
+};
+
+#define DDR_REG_DYN(x)						\
+	{							\
+		.name = #x,					\
+		.offset = offsetof(struct stm32mp1_ddrctl, x),	\
+		.par_offset = INVALID_OFFSET \
+	}
+
+static const struct reg_desc ddr_dyn[] = {
+	DDR_REG_DYN(stat),
+	DDR_REG_DYN(init0),
+	DDR_REG_DYN(dfimisc),
+	DDR_REG_DYN(dfistat),
+	DDR_REG_DYN(swctl),
+	DDR_REG_DYN(swstat),
+	DDR_REG_DYN(pctrl_0),
+	DDR_REG_DYN(pctrl_1),
+};
+
+#define DDRPHY_REG_DYN(x)					\
+	{							\
+		.name = #x,					\
+		.offset = offsetof(struct stm32mp1_ddrphy, x),	\
+		.par_offset = INVALID_OFFSET			\
+	}
+
+static const struct reg_desc ddrphy_dyn[] = {
+	DDRPHY_REG_DYN(pir),
+	DDRPHY_REG_DYN(pgsr),
+};
+
+enum reg_type {
+	REG_REG,
+	REG_TIMING,
+	REG_PERF,
+	REG_MAP,
+	REGPHY_REG,
+	REGPHY_TIMING,
+	REGPHY_CAL,
+/*
+ * Dynamic registers => managed in driver or not changed,
+ * can be dumped in interactive mode.
+ */
+	REG_DYN,
+	REGPHY_DYN,
+	REG_TYPE_NB
+};
+
+enum base_type {
+	DDR_BASE,
+	DDRPHY_BASE,
+	NONE_BASE
+};
+
+struct ddr_reg_info {
+	const char *name;
+	const struct reg_desc *desc;
+	uint8_t size;
+	enum base_type base;
+};
+
+static const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = {
+	[REG_REG] = {
+		"static", ddr_reg, ARRAY_SIZE(ddr_reg), DDR_BASE
+	},
+	[REG_TIMING] = {
+		"timing", ddr_timing, ARRAY_SIZE(ddr_timing), DDR_BASE
+	},
+	[REG_PERF] = {
+		"perf", ddr_perf, ARRAY_SIZE(ddr_perf), DDR_BASE
+	},
+	[REG_MAP] = {
+		"map", ddr_map, ARRAY_SIZE(ddr_map), DDR_BASE
+	},
+	[REGPHY_REG] = {
+		"static", ddrphy_reg, ARRAY_SIZE(ddrphy_reg), DDRPHY_BASE
+	},
+	[REGPHY_TIMING] = {
+		"timing", ddrphy_timing, ARRAY_SIZE(ddrphy_timing), DDRPHY_BASE
+	},
+	[REGPHY_CAL] = {
+		"cal", ddrphy_cal, ARRAY_SIZE(ddrphy_cal), DDRPHY_BASE
+	},
+	[REG_DYN] = {
+		"dyn", ddr_dyn, ARRAY_SIZE(ddr_dyn), DDR_BASE
+	},
+	[REGPHY_DYN] = {
+		"dyn", ddrphy_dyn, ARRAY_SIZE(ddrphy_dyn), DDRPHY_BASE
+	},
+};
+
+static uint32_t get_base_addr(const struct ddr_info *priv, enum base_type base)
+{
+	if (base == DDRPHY_BASE) {
+		return (uint32_t)priv->phy;
+	} else {
+		return (uint32_t)priv->ctl;
+	}
+}
+
+static void set_reg(const struct ddr_info *priv,
+		    enum reg_type type,
+		    const void *param)
+{
+	unsigned int i;
+	unsigned int *ptr, value;
+	enum base_type base = ddr_registers[type].base;
+	uint32_t base_addr = get_base_addr(priv, base);
+	const struct reg_desc *desc = ddr_registers[type].desc;
+
+	VERBOSE("init %s\n", ddr_registers[type].name);
+	for (i = 0; i < ddr_registers[type].size; i++) {
+		ptr = (unsigned int *)(base_addr + desc[i].offset);
+		if (desc[i].par_offset == INVALID_OFFSET) {
+			ERROR("invalid parameter offset for %s", desc[i].name);
+			panic();
+		} else {
+			value = *((uint32_t *)((uint32_t)param +
+					       desc[i].par_offset));
+			mmio_write_32((uint32_t)ptr, value);
+		}
+	}
+}
+
+static void stm32mp1_ddrphy_idone_wait(struct stm32mp1_ddrphy *phy)
+{
+	uint32_t pgsr;
+	int error = 0;
+	unsigned long start;
+	unsigned long time0, time;
+
+	start = get_timer(0);
+	time0 = start;
+
+	do {
+		pgsr = mmio_read_32((uint32_t)&phy->pgsr);
+		time = get_timer(start);
+		if (time != time0) {
+			VERBOSE("  > [0x%x] pgsr = 0x%x &\n",
+				(uint32_t)&phy->pgsr, pgsr);
+			VERBOSE("    [0x%x] pir = 0x%x (time=%x)\n",
+				(uint32_t)&phy->pir,
+				mmio_read_32((uint32_t)&phy->pir),
+				(uint32_t)time);
+		}
+
+		time0 = time;
+		if (time > plat_get_syscnt_freq2()) {
+			panic();
+		}
+		if ((pgsr & DDRPHYC_PGSR_DTERR) != 0U) {
+			VERBOSE("DQS Gate Trainig Error\n");
+			error++;
+		}
+		if ((pgsr & DDRPHYC_PGSR_DTIERR) != 0U) {
+			VERBOSE("DQS Gate Trainig Intermittent Error\n");
+			error++;
+		}
+		if ((pgsr & DDRPHYC_PGSR_DFTERR) != 0U) {
+			VERBOSE("DQS Drift Error\n");
+			error++;
+		}
+		if ((pgsr & DDRPHYC_PGSR_RVERR) != 0U) {
+			VERBOSE("Read Valid Training Error\n");
+			error++;
+		}
+		if ((pgsr & DDRPHYC_PGSR_RVEIRR) != 0U) {
+			VERBOSE("Read Valid Training Intermittent Error\n");
+			error++;
+		}
+	} while ((pgsr & DDRPHYC_PGSR_IDONE) == 0U && error == 0);
+	VERBOSE("\n[0x%x] pgsr = 0x%x\n",
+		(uint32_t)&phy->pgsr, pgsr);
+}
+
+static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir)
+{
+	uint32_t pir_init = pir | DDRPHYC_PIR_INIT;
+
+	mmio_write_32((uint32_t)&phy->pir, pir_init);
+	VERBOSE("[0x%x] pir = 0x%x -> 0x%x\n",
+		(uint32_t)&phy->pir, pir_init,
+		mmio_read_32((uint32_t)&phy->pir));
+
+	/* Need to wait 10 configuration clock before start polling */
+	udelay(10);
+
+	/* Wait DRAM initialization and Gate Training Evaluation complete */
+	stm32mp1_ddrphy_idone_wait(phy);
+}
+
+/* Start quasi dynamic register update */
+static void stm32mp1_start_sw_done(struct stm32mp1_ddrctl *ctl)
+{
+	mmio_clrbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
+	VERBOSE("[0x%x] swctl = 0x%x\n",
+		(uint32_t)&ctl->swctl,  mmio_read_32((uint32_t)&ctl->swctl));
+}
+
+/* Wait quasi dynamic register update */
+static void stm32mp1_wait_sw_done_ack(struct stm32mp1_ddrctl *ctl)
+{
+	unsigned long start;
+	uint32_t swstat;
+
+	mmio_setbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
+	VERBOSE("[0x%x] swctl = 0x%x\n",
+		(uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl));
+
+	start = get_timer(0);
+	do {
+		swstat = mmio_read_32((uint32_t)&ctl->swstat);
+		VERBOSE("[0x%x] swstat = 0x%x ",
+			(uint32_t)&ctl->swstat, swstat);
+		VERBOSE("timer in ms 0x%x = start 0x%lx\r",
+			get_timer(0), start);
+		if (get_timer(start) > plat_get_syscnt_freq2()) {
+			panic();
+		}
+	} while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U);
+
+	VERBOSE("[0x%x] swstat = 0x%x\n",
+		(uint32_t)&ctl->swstat, swstat);
+}
+
+/* Wait quasi dynamic register update */
+static void stm32mp1_wait_operating_mode(struct ddr_info *priv, uint32_t mode)
+{
+	unsigned long start;
+	uint32_t stat;
+	uint32_t operating_mode;
+	uint32_t selref_type;
+	int break_loop = 0;
+
+	start = get_timer(0);
+	for ( ; ; ) {
+		stat = mmio_read_32((uint32_t)&priv->ctl->stat);
+		operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK;
+		selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK;
+		VERBOSE("[0x%x] stat = 0x%x\n",
+			(uint32_t)&priv->ctl->stat, stat);
+		VERBOSE("timer in ms 0x%x = start 0x%lx\r",
+			get_timer(0), start);
+		if (get_timer(start) > plat_get_syscnt_freq2()) {
+			panic();
+		}
+
+		if (mode == DDRCTRL_STAT_OPERATING_MODE_SR) {
+			/*
+			 * Self-refresh due to software
+			 * => checking also STAT.selfref_type.
+			 */
+			if ((operating_mode ==
+			     DDRCTRL_STAT_OPERATING_MODE_SR) &&
+			    (selref_type == DDRCTRL_STAT_SELFREF_TYPE_SR)) {
+				break_loop = 1;
+			}
+		} else if (operating_mode == mode) {
+			break_loop = 1;
+		} else if ((mode == DDRCTRL_STAT_OPERATING_MODE_NORMAL) &&
+			   (operating_mode == DDRCTRL_STAT_OPERATING_MODE_SR) &&
+			   (selref_type == DDRCTRL_STAT_SELFREF_TYPE_ASR)) {
+			/* Normal mode: handle also automatic self refresh */
+			break_loop = 1;
+		}
+
+		if (break_loop == 1) {
+			break;
+		}
+	}
+
+	VERBOSE("[0x%x] stat = 0x%x\n",
+		(uint32_t)&priv->ctl->stat, stat);
+}
+
+/* Mode Register Writes (MRW or MRS) */
+static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr,
+					 uint32_t data)
+{
+	uint32_t mrctrl0;
+
+	VERBOSE("MRS: %d = %x\n", addr, data);
+
+	/*
+	 * 1. Poll MRSTAT.mr_wr_busy until it is '0'.
+	 *    This checks that there is no outstanding MR transaction.
+	 *    No write should be performed to MRCTRL0 and MRCTRL1
+	 *    if MRSTAT.mr_wr_busy = 1.
+	 */
+	while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) &
+		DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) {
+		;
+	}
+
+	/*
+	 * 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr, MRCTRL0.mr_rank
+	 *    and (for MRWs) MRCTRL1.mr_data to define the MR transaction.
+	 */
+	mrctrl0 = DDRCTRL_MRCTRL0_MR_TYPE_WRITE |
+		  DDRCTRL_MRCTRL0_MR_RANK_ALL |
+		  (((uint32_t)addr << DDRCTRL_MRCTRL0_MR_ADDR_SHIFT) &
+		   DDRCTRL_MRCTRL0_MR_ADDR_MASK);
+	mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0);
+	VERBOSE("[0x%x] mrctrl0 = 0x%x (0x%x)\n",
+		(uint32_t)&priv->ctl->mrctrl0,
+		mmio_read_32((uint32_t)&priv->ctl->mrctrl0), mrctrl0);
+	mmio_write_32((uint32_t)&priv->ctl->mrctrl1, data);
+	VERBOSE("[0x%x] mrctrl1 = 0x%x\n",
+		(uint32_t)&priv->ctl->mrctrl1,
+		mmio_read_32((uint32_t)&priv->ctl->mrctrl1));
+
+	/*
+	 * 3. In a separate APB transaction, write the MRCTRL0.mr_wr to 1. This
+	 *    bit is self-clearing, and triggers the MR transaction.
+	 *    The uMCTL2 then asserts the MRSTAT.mr_wr_busy while it performs
+	 *    the MR transaction to SDRAM, and no further access can be
+	 *    initiated until it is deasserted.
+	 */
+	mrctrl0 |= DDRCTRL_MRCTRL0_MR_WR;
+	mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0);
+
+	while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) &
+	       DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) {
+		;
+	}
+
+	VERBOSE("[0x%x] mrctrl0 = 0x%x\n",
+		(uint32_t)&priv->ctl->mrctrl0, mrctrl0);
+}
+
+/* Switch DDR3 from DLL-on to DLL-off */
+static void stm32mp1_ddr3_dll_off(struct ddr_info *priv)
+{
+	uint32_t mr1 = mmio_read_32((uint32_t)&priv->phy->mr1);
+	uint32_t mr2 = mmio_read_32((uint32_t)&priv->phy->mr2);
+	uint32_t dbgcam;
+
+	VERBOSE("mr1: 0x%x\n", mr1);
+	VERBOSE("mr2: 0x%x\n", mr2);
+
+	/*
+	 * 1. Set the DBG1.dis_hif = 1.
+	 *    This prevents further reads/writes being received on the HIF.
+	 */
+	mmio_setbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF);
+	VERBOSE("[0x%x] dbg1 = 0x%x\n",
+		(uint32_t)&priv->ctl->dbg1,
+		mmio_read_32((uint32_t)&priv->ctl->dbg1));
+
+	/*
+	 * 2. Ensure all commands have been flushed from the uMCTL2 by polling
+	 *    DBGCAM.wr_data_pipeline_empty = 1,
+	 *    DBGCAM.rd_data_pipeline_empty = 1,
+	 *    DBGCAM.dbg_wr_q_depth = 0 ,
+	 *    DBGCAM.dbg_lpr_q_depth = 0, and
+	 *    DBGCAM.dbg_hpr_q_depth = 0.
+	 */
+	do {
+		dbgcam = mmio_read_32((uint32_t)&priv->ctl->dbgcam);
+		VERBOSE("[0x%x] dbgcam = 0x%x\n",
+			(uint32_t)&priv->ctl->dbgcam, dbgcam);
+	} while ((((dbgcam & DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY) ==
+		   DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY)) &&
+		 ((dbgcam & DDRCTRL_DBGCAM_DBG_Q_DEPTH) == 0U));
+
+	/*
+	 * 3. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers)
+	 *    to disable RTT_NOM:
+	 *    a. DDR3: Write to MR1[9], MR1[6] and MR1[2]
+	 *    b. DDR4: Write to MR1[10:8]
+	 */
+	mr1 &= ~(BIT(9) | BIT(6) | BIT(2));
+	stm32mp1_mode_register_write(priv, 1, mr1);
+
+	/*
+	 * 4. For DDR4 only: Perform an MRS command
+	 *    (using MRCTRL0 and MRCTRL1 registers) to write to MR5[8:6]
+	 *    to disable RTT_PARK
+	 */
+
+	/*
+	 * 5. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers)
+	 *    to write to MR2[10:9], to disable RTT_WR
+	 *    (and therefore disable dynamic ODT).
+	 *    This applies for both DDR3 and DDR4.
+	 */
+	mr2 &= ~GENMASK(10, 9);
+	stm32mp1_mode_register_write(priv, 2, mr2);
+
+	/*
+	 * 6. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers)
+	 *    to disable the DLL. The timing of this MRS is automatically
+	 *    handled by the uMCTL2.
+	 *    a. DDR3: Write to MR1[0]
+	 *    b. DDR4: Write to MR1[0]
+	 */
+	mr1 |= BIT(0);
+	stm32mp1_mode_register_write(priv, 1, mr1);
+
+	/*
+	 * 7. Put the SDRAM into self-refresh mode by setting
+	 *    PWRCTL.selfref_sw = 1, and polling STAT.operating_mode to ensure
+	 *    the DDRC has entered self-refresh.
+	 */
+	mmio_setbits_32((uint32_t)&priv->ctl->pwrctl,
+			DDRCTRL_PWRCTL_SELFREF_SW);
+	VERBOSE("[0x%x] pwrctl = 0x%x\n",
+		(uint32_t)&priv->ctl->pwrctl,
+		mmio_read_32((uint32_t)&priv->ctl->pwrctl));
+
+	/*
+	 * 8. Wait until STAT.operating_mode[1:0]==11 indicating that the
+	 *    DWC_ddr_umctl2 core is in self-refresh mode.
+	 *    Ensure transition to self-refresh was due to software
+	 *    by checking that STAT.selfref_type[1:0]=2.
+	 */
+	stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_SR);
+
+	/*
+	 * 9. Set the MSTR.dll_off_mode = 1.
+	 *    warning: MSTR.dll_off_mode is a quasi-dynamic type 2 field
+	 */
+	stm32mp1_start_sw_done(priv->ctl);
+
+	mmio_setbits_32((uint32_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE);
+	VERBOSE("[0x%x] mstr = 0x%x\n",
+		(uint32_t)&priv->ctl->mstr,
+		mmio_read_32((uint32_t)&priv->ctl->mstr));
+
+	stm32mp1_wait_sw_done_ack(priv->ctl);
+
+	/* 10. Change the clock frequency to the desired value. */
+
+	/*
+	 * 11. Update any registers which may be required to change for the new
+	 *     frequency. This includes static and dynamic registers.
+	 *     This includes both uMCTL2 registers and PHY registers.
+	 */
+
+	/* Change Bypass Mode Frequency Range */
+	if (stm32mp1_clk_get_rate(DDRPHYC) < 100000000U) {
+		mmio_clrbits_32((uint32_t)&priv->phy->dllgcr,
+				DDRPHYC_DLLGCR_BPS200);
+	} else {
+		mmio_setbits_32((uint32_t)&priv->phy->dllgcr,
+				DDRPHYC_DLLGCR_BPS200);
+	}
+
+	mmio_setbits_32((uint32_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS);
+
+	mmio_setbits_32((uint32_t)&priv->phy->dx0dllcr,
+			DDRPHYC_DXNDLLCR_DLLDIS);
+	mmio_setbits_32((uint32_t)&priv->phy->dx1dllcr,
+			DDRPHYC_DXNDLLCR_DLLDIS);
+	mmio_setbits_32((uint32_t)&priv->phy->dx2dllcr,
+			DDRPHYC_DXNDLLCR_DLLDIS);
+	mmio_setbits_32((uint32_t)&priv->phy->dx3dllcr,
+			DDRPHYC_DXNDLLCR_DLLDIS);
+
+	/* 12. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */
+	mmio_clrbits_32((uint32_t)&priv->ctl->pwrctl,
+			DDRCTRL_PWRCTL_SELFREF_SW);
+	stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL);
+
+	/*
+	 * 13. If ZQCTL0.dis_srx_zqcl = 0, the uMCTL2 performs a ZQCL command
+	 *     at this point.
+	 */
+
+	/*
+	 * 14. Perform MRS commands as required to re-program timing registers
+	 *     in the SDRAM for the new frequency
+	 *     (in particular, CL, CWL and WR may need to be changed).
+	 */
+
+	/* 15. Write DBG1.dis_hif = 0 to re-enable reads and writes. */
+	mmio_clrbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF);
+	VERBOSE("[0x%x] dbg1 = 0x%x\n",
+		(uint32_t)&priv->ctl->dbg1,
+		mmio_read_32((uint32_t)&priv->ctl->dbg1));
+}
+
+static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl)
+{
+	stm32mp1_start_sw_done(ctl);
+	/* Quasi-dynamic register update*/
+	mmio_setbits_32((uint32_t)&ctl->rfshctl3,
+			DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
+	mmio_clrbits_32((uint32_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
+	mmio_clrbits_32((uint32_t)&ctl->dfimisc,
+			DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
+	stm32mp1_wait_sw_done_ack(ctl);
+}
+
+static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl,
+				     uint32_t rfshctl3, uint32_t pwrctl)
+{
+	stm32mp1_start_sw_done(ctl);
+	if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) {
+		mmio_clrbits_32((uint32_t)&ctl->rfshctl3,
+				DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
+	}
+	if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) {
+		mmio_setbits_32((uint32_t)&ctl->pwrctl,
+				DDRCTRL_PWRCTL_POWERDOWN_EN);
+	}
+	mmio_setbits_32((uint32_t)&ctl->dfimisc,
+			DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
+	stm32mp1_wait_sw_done_ack(ctl);
+}
+
+static int board_ddr_power_init(enum ddr_type ddr_type)
+{
+	if (dt_check_pmic()) {
+		return pmic_ddr_power_init(ddr_type);
+	}
+
+	return 0;
+}
+
+void stm32mp1_ddr_init(struct ddr_info *priv,
+		       struct stm32mp1_ddr_config *config)
+{
+	uint32_t pir;
+	int ret;
+
+	if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) {
+		ret = board_ddr_power_init(STM32MP_DDR3);
+	} else {
+		ret = board_ddr_power_init(STM32MP_LPDDR2);
+	}
+
+	if (ret != 0) {
+		panic();
+	}
+
+	VERBOSE("name = %s\n", config->info.name);
+	VERBOSE("speed = %d MHz\n", config->info.speed);
+	VERBOSE("size  = 0x%x\n", config->info.size);
+
+	/* DDR INIT SEQUENCE */
+
+	/*
+	 * 1. Program the DWC_ddr_umctl2 registers
+	 *     nota: check DFIMISC.dfi_init_complete = 0
+	 */
+
+	/* 1.1 RESETS: presetn, core_ddrc_rstn, aresetn */
+	mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST);
+	mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST);
+	mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST);
+	mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST);
+	mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST);
+	mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST);
+
+	/* 1.2. start CLOCK */
+	if (stm32mp1_ddr_clk_enable(priv, config->info.speed) != 0) {
+		panic();
+	}
+
+	/* 1.3. deassert reset */
+	/* De-assert PHY rstn and ctl_rstn via DPHYRST and DPHYCTLRST. */
+	mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST);
+	mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST);
+	/*
+	 * De-assert presetn once the clocks are active
+	 * and stable via DDRCAPBRST bit.
+	 */
+	mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST);
+
+	/* 1.4. wait 128 cycles to permit initialization of end logic */
+	udelay(2);
+	/* For PCLK = 133MHz => 1 us is enough, 2 to allow lower frequency */
+
+	/* 1.5. initialize registers ddr_umctl2 */
+	/* Stop uMCTL2 before PHY is ready */
+	mmio_clrbits_32((uint32_t)&priv->ctl->dfimisc,
+			DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
+	VERBOSE("[0x%x] dfimisc = 0x%x\n",
+		(uint32_t)&priv->ctl->dfimisc,
+		mmio_read_32((uint32_t)&priv->ctl->dfimisc));
+
+	set_reg(priv, REG_REG, &config->c_reg);
+
+	/* DDR3 = don't set DLLOFF for init mode */
+	if ((config->c_reg.mstr &
+	     (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE))
+	    == (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) {
+		VERBOSE("deactivate DLL OFF in mstr\n");
+		mmio_clrbits_32((uint32_t)&priv->ctl->mstr,
+				DDRCTRL_MSTR_DLL_OFF_MODE);
+		VERBOSE("[0x%x] mstr = 0x%x\n",
+			(uint32_t)&priv->ctl->mstr,
+			mmio_read_32((uint32_t)&priv->ctl->mstr));
+	}
+
+	set_reg(priv, REG_TIMING, &config->c_timing);
+	set_reg(priv, REG_MAP, &config->c_map);
+
+	/* Skip CTRL init, SDRAM init is done by PHY PUBL */
+	mmio_clrsetbits_32((uint32_t)&priv->ctl->init0,
+			   DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK,
+			   DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL);
+	VERBOSE("[0x%x] init0 = 0x%x\n",
+		(uint32_t)&priv->ctl->init0,
+		mmio_read_32((uint32_t)&priv->ctl->init0));
+
+	set_reg(priv, REG_PERF, &config->c_perf);
+
+	/*  2. deassert reset signal core_ddrc_rstn, aresetn and presetn */
+	mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST);
+	mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST);
+	mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST);
+
+	/*
+	 * 3. start PHY init by accessing relevant PUBL registers
+	 *    (DXGCR, DCR, PTR*, MR*, DTPR*)
+	 */
+	set_reg(priv, REGPHY_REG, &config->p_reg);
+	set_reg(priv, REGPHY_TIMING, &config->p_timing);
+	set_reg(priv, REGPHY_CAL, &config->p_cal);
+
+	/* DDR3 = don't set DLLOFF for init mode */
+	if ((config->c_reg.mstr &
+	     (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE))
+	    == (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) {
+		VERBOSE("deactivate DLL OFF in mr1\n");
+		mmio_clrbits_32((uint32_t)&priv->phy->mr1, BIT(0));
+		VERBOSE("[0x%x] mr1 = 0x%x\n",
+			(uint32_t)&priv->phy->mr1,
+			mmio_read_32((uint32_t)&priv->phy->mr1));
+	}
+
+	/*
+	 *  4. Monitor PHY init status by polling PUBL register PGSR.IDONE
+	 *     Perform DDR PHY DRAM initialization and Gate Training Evaluation
+	 */
+	stm32mp1_ddrphy_idone_wait(priv->phy);
+
+	/*
+	 *  5. Indicate to PUBL that controller performs SDRAM initialization
+	 *     by setting PIR.INIT and PIR CTLDINIT and pool PGSR.IDONE
+	 *     DRAM init is done by PHY, init0.skip_dram.init = 1
+	 */
+
+	pir = DDRPHYC_PIR_DLLSRST | DDRPHYC_PIR_DLLLOCK | DDRPHYC_PIR_ZCAL |
+	      DDRPHYC_PIR_ITMSRST | DDRPHYC_PIR_DRAMINIT | DDRPHYC_PIR_ICPC;
+
+	if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) {
+		pir |= DDRPHYC_PIR_DRAMRST; /* Only for DDR3 */
+	}
+
+	stm32mp1_ddrphy_init(priv->phy, pir);
+
+	/*
+	 *  6. SET DFIMISC.dfi_init_complete_en to 1
+	 *  Enable quasi-dynamic register programming.
+	 */
+	stm32mp1_start_sw_done(priv->ctl);
+
+	mmio_setbits_32((uint32_t)&priv->ctl->dfimisc,
+			DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
+	VERBOSE("[0x%x] dfimisc = 0x%x\n",
+		(uint32_t)&priv->ctl->dfimisc,
+		mmio_read_32((uint32_t)&priv->ctl->dfimisc));
+
+	stm32mp1_wait_sw_done_ack(priv->ctl);
+
+	/*
+	 *  7. Wait for DWC_ddr_umctl2 to move to normal operation mode
+	 *     by monitoring STAT.operating_mode signal
+	 */
+
+	/* Wait uMCTL2 ready */
+	stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL);
+
+	/* Switch to DLL OFF mode */
+	if ((config->c_reg.mstr & DDRCTRL_MSTR_DLL_OFF_MODE) != 0U) {
+		stm32mp1_ddr3_dll_off(priv);
+	}
+
+	VERBOSE("DDR DQS training : ");
+
+	/*
+	 *  8. Disable Auto refresh and power down by setting
+	 *    - RFSHCTL3.dis_au_refresh = 1
+	 *    - PWRCTL.powerdown_en = 0
+	 *    - DFIMISC.dfiinit_complete_en = 0
+	 */
+	stm32mp1_refresh_disable(priv->ctl);
+
+	/*
+	 *  9. Program PUBL PGCR to enable refresh during training
+	 *     and rank to train
+	 *     not done => keep the programed value in PGCR
+	 */
+
+	/*
+	 * 10. configure PUBL PIR register to specify which training step
+	 * to run
+	 * Warning : RVTRN  is not supported by this PUBL
+	 */
+	stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN);
+
+	/* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */
+	stm32mp1_ddrphy_idone_wait(priv->phy);
+
+	/*
+	 * 12. set back registers in step 8 to the orginal values if desidered
+	 */
+	stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3,
+				 config->c_reg.pwrctl);
+
+	/* Enable uMCTL2 AXI port 0 */
+	mmio_setbits_32((uint32_t)&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
+	VERBOSE("[0x%x] pctrl_0 = 0x%x\n",
+		(uint32_t)&priv->ctl->pctrl_0,
+		mmio_read_32((uint32_t)&priv->ctl->pctrl_0));
+
+	/* Enable uMCTL2 AXI port 1 */
+	mmio_setbits_32((uint32_t)&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
+	VERBOSE("[0x%x] pctrl_1 = 0x%x\n",
+		(uint32_t)&priv->ctl->pctrl_1,
+		mmio_read_32((uint32_t)&priv->ctl->pctrl_1));
+}
diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c
new file mode 100644
index 0000000..325c0b8
--- /dev/null
+++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mmio.h>
+#include <platform_def.h>
+#include <stm32mp1_ddr_helpers.h>
+#include <stm32mp1_rcc.h>
+
+void ddr_enable_clock(void)
+{
+	mmio_setbits_32(RCC_BASE + RCC_DDRITFCR,
+			RCC_DDRITFCR_DDRC1EN |
+			RCC_DDRITFCR_DDRC2EN |
+			RCC_DDRITFCR_DDRPHYCEN |
+			RCC_DDRITFCR_DDRPHYCAPBEN |
+			RCC_DDRITFCR_DDRCAPBEN);
+}
diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c
new file mode 100644
index 0000000..6d515ec
--- /dev/null
+++ b/drivers/st/ddr/stm32mp1_ram.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_ddr.h>
+#include <stm32mp1_ddr_helpers.h>
+#include <stm32mp1_dt.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_ram.h>
+#include <stm32mp1_rcc.h>
+
+#define DDR_PATTERN	0xAAAAAAAAU
+#define DDR_ANTIPATTERN	0x55555555U
+
+static struct ddr_info ddr_priv_data;
+
+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed)
+{
+	unsigned long ddrphy_clk, ddr_clk, mem_speed_hz;
+
+	ddr_enable_clock();
+
+	ddrphy_clk = stm32mp1_clk_get_rate(DDRPHYC);
+
+	VERBOSE("DDR: mem_speed (%d MHz), RCC %ld MHz\n",
+		mem_speed, ddrphy_clk / 1000U / 1000U);
+
+	mem_speed_hz = (uint32_t)mem_speed * 1000U * 1000U;
+
+	/* Max 10% frequency delta */
+	if (ddrphy_clk > mem_speed_hz) {
+		ddr_clk = ddrphy_clk - mem_speed_hz;
+	} else {
+		ddr_clk = mem_speed_hz - ddrphy_clk;
+	}
+	if (ddr_clk > mem_speed_hz) {
+		ERROR("DDR expected freq %d MHz, current is %ld MHz\n",
+		      mem_speed, ddrphy_clk / 1000U / 1000U);
+		return -1;
+	}
+	return 0;
+}
+
+/*******************************************************************************
+ * This function tests the DDR data bus wiring.
+ * This is inspired from the Data Bus Test algorithm written by Michael Barr
+ * in "Programming Embedded Systems in C and C++" book.
+ * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
+ * File: memtest.c - This source code belongs to Public Domain.
+ * Returns 0 if success, and address value else.
+ ******************************************************************************/
+static uint32_t ddr_test_data_bus(void)
+{
+	uint32_t pattern;
+
+	for (pattern = 1U; pattern != 0U; pattern <<= 1) {
+		mmio_write_32(STM32MP1_DDR_BASE, pattern);
+
+		if (mmio_read_32(STM32MP1_DDR_BASE) != pattern) {
+			return (uint32_t)STM32MP1_DDR_BASE;
+		}
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ * This function tests the DDR address bus wiring.
+ * This is inspired from the Data Bus Test algorithm written by Michael Barr
+ * in "Programming Embedded Systems in C and C++" book.
+ * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
+ * File: memtest.c - This source code belongs to Public Domain.
+ * Returns 0 if success, and address value else.
+ ******************************************************************************/
+static uint32_t ddr_test_addr_bus(void)
+{
+	uint64_t addressmask = (ddr_priv_data.info.size - 1U);
+	uint64_t offset;
+	uint64_t testoffset = 0;
+
+	/* Write the default pattern at each of the power-of-two offsets. */
+	for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
+	     offset <<= 1) {
+		mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)offset,
+			      DDR_PATTERN);
+	}
+
+	/* Check for address bits stuck high. */
+	mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset,
+		      DDR_ANTIPATTERN);
+
+	for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
+	     offset <<= 1) {
+		if (mmio_read_32(STM32MP1_DDR_BASE + (uint32_t)offset) !=
+		    DDR_PATTERN) {
+			return (uint32_t)(STM32MP1_DDR_BASE + offset);
+		}
+	}
+
+	mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN);
+
+	/* Check for address bits stuck low or shorted. */
+	for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U;
+	     testoffset <<= 1) {
+		mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset,
+			      DDR_ANTIPATTERN);
+
+		if (mmio_read_32(STM32MP1_DDR_BASE) != DDR_PATTERN) {
+			return STM32MP1_DDR_BASE;
+		}
+
+		for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
+		     offset <<= 1) {
+			if ((mmio_read_32(STM32MP1_DDR_BASE +
+					  (uint32_t)offset) != DDR_PATTERN) &&
+			    (offset != testoffset)) {
+				return (uint32_t)(STM32MP1_DDR_BASE + offset);
+			}
+		}
+
+		mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset,
+			      DDR_PATTERN);
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ * This function checks the DDR size. It has to be run with Data Cache off.
+ * This test is run before data have been put in DDR, and is only done for
+ * cold boot. The DDR data can then be overwritten, and it is not useful to
+ * restore its content.
+ * Returns DDR computed size.
+ ******************************************************************************/
+static uint32_t ddr_check_size(void)
+{
+	uint32_t offset = sizeof(uint32_t);
+
+	mmio_write_32(STM32MP1_DDR_BASE, DDR_PATTERN);
+
+	while (offset < STM32MP1_DDR_MAX_SIZE) {
+		mmio_write_32(STM32MP1_DDR_BASE + offset, DDR_ANTIPATTERN);
+		dsb();
+
+		if (mmio_read_32(STM32MP1_DDR_BASE) != DDR_PATTERN) {
+			break;
+		}
+
+		offset <<= 1;
+	}
+
+	INFO("Memory size = 0x%x (%d MB)\n", offset, offset / (1024U * 1024U));
+
+	return offset;
+}
+
+static int stm32mp1_ddr_setup(void)
+{
+	struct ddr_info *priv = &ddr_priv_data;
+	int ret;
+	struct stm32mp1_ddr_config config;
+	int node, len;
+	uint32_t tamp_clk_off = 0, uret, idx;
+	void *fdt;
+
+#define PARAM(x, y)							\
+	{								\
+		.name = x,						\
+		.offset = offsetof(struct stm32mp1_ddr_config, y),	\
+		.size = sizeof(config.y) / sizeof(uint32_t)		\
+	}
+
+#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x)
+#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x)
+
+	const struct {
+		const char *name; /* Name in DT */
+		const uint32_t offset; /* Offset in config struct */
+		const uint32_t size;   /* Size of parameters */
+	} param[] = {
+		CTL_PARAM(reg),
+		CTL_PARAM(timing),
+		CTL_PARAM(map),
+		CTL_PARAM(perf),
+		PHY_PARAM(reg),
+		PHY_PARAM(timing),
+		PHY_PARAM(cal)
+	};
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -ENOENT;
+	}
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
+	if (node < 0) {
+		ERROR("%s: Cannot read DDR node in DT\n", __func__);
+		return -EINVAL;
+	}
+
+	config.info.speed =
+		(uint16_t)fdt_read_uint32_default(node, "st,mem-speed",
+						  STM32MP1_DDR_SPEED_DFLT);
+	config.info.size = fdt_read_uint32_default(node, "st,mem-size",
+						   STM32MP1_DDR_SIZE_DFLT);
+	config.info.name = fdt_getprop(fdt, node, "st,mem-name", &len);
+	if (config.info.name == NULL) {
+		VERBOSE("%s: no st,mem-name\n", __func__);
+		return -EINVAL;
+	}
+	INFO("RAM: %s\n", config.info.name);
+
+	for (idx = 0; idx < ARRAY_SIZE(param); idx++) {
+		ret = fdt_read_uint32_array(node, param[idx].name,
+					    (void *)((uint32_t)&config +
+						     param[idx].offset),
+					    param[idx].size);
+
+		VERBOSE("%s: %s[0x%x] = %d\n", __func__,
+			param[idx].name, param[idx].size, ret);
+		if (ret != 0) {
+			ERROR("%s: Cannot read %s\n",
+			      __func__, param[idx].name);
+			return -EINVAL;
+		}
+	}
+
+	if (!stm32mp1_clk_is_enabled(RTCAPB)) {
+		tamp_clk_off = 1;
+		if (stm32mp1_clk_enable(RTCAPB) != 0) {
+			return -EINVAL;
+		}
+	}
+
+	if (tamp_clk_off != 0U) {
+		if (stm32mp1_clk_disable(RTCAPB) != 0) {
+			return -EINVAL;
+		}
+	}
+
+	/* Disable axidcg clock gating during init */
+	mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
+
+	stm32mp1_ddr_init(priv, &config);
+
+	/* Enable axidcg clock gating */
+	mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
+
+	priv->info.size = config.info.size;
+
+	VERBOSE("%s : ram size(%x, %x)\n", __func__,
+		(uint32_t)priv->info.base, (uint32_t)priv->info.size);
+
+	dcsw_op_all(DC_OP_CISW);
+	write_sctlr(read_sctlr() & ~SCTLR_C_BIT);
+
+	uret = ddr_test_data_bus();
+	if (uret != 0U) {
+		ERROR("DDR data bus test: can't access memory @ 0x%x\n",
+		      uret);
+		panic();
+	}
+
+	uret = ddr_test_addr_bus();
+	if (uret != 0U) {
+		ERROR("DDR addr bus test: can't access memory @ 0x%x\n",
+		      uret);
+		panic();
+	}
+
+	uret = ddr_check_size();
+	if (uret < config.info.size) {
+		ERROR("DDR size: 0x%x does not match DT config: 0x%x\n",
+		      uret, config.info.size);
+		panic();
+	}
+
+	write_sctlr(read_sctlr() | SCTLR_C_BIT);
+
+	return 0;
+}
+
+int stm32mp1_ddr_probe(void)
+{
+	struct ddr_info *priv = &ddr_priv_data;
+
+	VERBOSE("STM32MP DDR probe\n");
+
+	priv->ctl = (struct stm32mp1_ddrctl *)DDRCTRL_BASE;
+	priv->phy = (struct stm32mp1_ddrphy *)DDRPHYC_BASE;
+	priv->pwr = PWR_BASE;
+	priv->rcc = RCC_BASE;
+
+	priv->info.base = STM32MP1_DDR_BASE;
+	priv->info.size = 0;
+
+	return stm32mp1_ddr_setup();
+}
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
new file mode 100644
index 0000000..200b473
--- /dev/null
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <debug.h>
+#include <mmio.h>
+#include <stdbool.h>
+#include <stm32_gpio.h>
+
+static bool check_gpio(uint32_t bank, uint32_t pin)
+{
+	if (pin > GPIO_PIN_MAX) {
+		ERROR("%s: wrong pin number (%d)\n", __func__, pin);
+		return false;
+	}
+
+	if ((bank > GPIO_BANK_K) && (bank != GPIO_BANK_Z)) {
+		ERROR("%s: wrong GPIO bank number (%d)\n", __func__, bank);
+		return false;
+	}
+
+	return true;
+}
+
+void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
+	      uint32_t pull, uint32_t alternate)
+{
+	volatile uint32_t bank_address;
+
+	if (!check_gpio(bank, pin)) {
+		return;
+	}
+
+	if (bank == GPIO_BANK_Z) {
+		bank_address = STM32_GPIOZ_BANK;
+	} else {
+		bank_address = STM32_GPIOA_BANK +
+			(bank * STM32_GPIO_BANK_OFFSET);
+	}
+
+	mmio_clrbits_32(bank_address + GPIO_MODE_OFFSET,
+			((uint32_t)GPIO_MODE_MASK << (pin << 1)));
+	mmio_setbits_32(bank_address + GPIO_MODE_OFFSET,
+			(mode & ~GPIO_OPEN_DRAIN) << (pin << 1));
+
+	if ((mode & GPIO_OPEN_DRAIN) != 0U) {
+		mmio_setbits_32(bank_address + GPIO_TYPE_OFFSET,
+				BIT(pin));
+	}
+
+	mmio_clrbits_32(bank_address + GPIO_SPEED_OFFSET,
+			((uint32_t)GPIO_SPEED_MASK << (pin << 1)));
+	mmio_setbits_32(bank_address + GPIO_SPEED_OFFSET, speed << (pin << 1));
+
+	mmio_clrbits_32(bank_address + GPIO_PUPD_OFFSET,
+			((uint32_t)GPIO_PULL_MASK << (pin << 1)));
+	mmio_setbits_32(bank_address + GPIO_PUPD_OFFSET, pull << (pin << 1));
+
+	if (pin < GPIO_ALT_LOWER_LIMIT) {
+		mmio_clrbits_32(bank_address + GPIO_AFRL_OFFSET,
+				((uint32_t)GPIO_ALTERNATE_MASK << (pin << 2)));
+		mmio_setbits_32(bank_address + GPIO_AFRL_OFFSET,
+				alternate << (pin << 2));
+	} else {
+		mmio_clrbits_32(bank_address + GPIO_AFRH_OFFSET,
+				((uint32_t)GPIO_ALTERNATE_MASK <<
+				 ((pin - GPIO_ALT_LOWER_LIMIT) << 2)));
+		mmio_setbits_32(bank_address + GPIO_AFRH_OFFSET,
+				alternate << ((pin - GPIO_ALT_LOWER_LIMIT) <<
+					      2));
+	}
+
+	VERBOSE("GPIO %u mode set to 0x%x\n", bank,
+		mmio_read_32(bank_address + GPIO_MODE_OFFSET));
+	VERBOSE("GPIO %u speed set to 0x%x\n", bank,
+		mmio_read_32(bank_address + GPIO_SPEED_OFFSET));
+	VERBOSE("GPIO %u mode pull to 0x%x\n", bank,
+		mmio_read_32(bank_address + GPIO_PUPD_OFFSET));
+	VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank,
+		mmio_read_32(bank_address + GPIO_AFRL_OFFSET));
+	VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank,
+		mmio_read_32(bank_address + GPIO_AFRH_OFFSET));
+}
diff --git a/drivers/st/pmic/stm32_i2c.c b/drivers/st/pmic/stm32_i2c.c
new file mode 100644
index 0000000..0980139
--- /dev/null
+++ b/drivers/st/pmic/stm32_i2c.c
@@ -0,0 +1,851 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <mmio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stm32_i2c.h>
+
+/* STM32 I2C registers offsets */
+#define I2C_CR1			0x00U
+#define I2C_CR2			0x04U
+#define I2C_OAR1		0x08U
+#define I2C_OAR2		0x0CU
+#define I2C_TIMINGR		0x10U
+#define I2C_TIMEOUTR		0x14U
+#define I2C_ISR			0x18U
+#define I2C_ICR			0x1CU
+#define I2C_PECR		0x20U
+#define I2C_RXDR		0x24U
+#define I2C_TXDR		0x28U
+
+#define MAX_DELAY		0xFFFFFFFFU
+
+/* I2C TIMING clear register Mask */
+#define TIMING_CLEAR_MASK	0xF0FFFFFFU
+/* Timeout 25 ms */
+#define I2C_TIMEOUT_BUSY	25U
+
+#define MAX_NBYTE_SIZE		255U
+
+static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
+				    uint16_t dev_addr, uint16_t mem_addr,
+				    uint16_t mem_add_size, uint32_t timeout,
+				    uint32_t tick_start);
+static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+				   uint16_t mem_addr, uint16_t mem_add_size,
+				   uint32_t timeout, uint32_t tick_start);
+
+/* Private functions to handle flags during polling transfer */
+static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
+			 uint8_t awaited_value, uint32_t timeout,
+			 uint32_t tick_start);
+static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint32_t timeout,
+			 uint32_t tick_start);
+static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout,
+			 uint32_t tick_start);
+static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout,
+			  uint32_t tick_start);
+
+/* Private function to flush TXDR register */
+static void i2c_flush_txdr(struct i2c_handle_s *hi2c);
+
+/* Private function to start, restart or stop a transfer */
+static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+				uint16_t size, uint32_t i2c_mode,
+				uint32_t request);
+
+/*
+ * @brief  Initialize the I2C device.
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2C.
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_init(struct i2c_handle_s *hi2c)
+{
+	if (hi2c == NULL) {
+		return -ENOENT;
+	}
+
+	if (hi2c->i2c_state == I2C_STATE_RESET) {
+		hi2c->lock = 0;
+	}
+
+	hi2c->i2c_state = I2C_STATE_BUSY;
+
+	/* Disable the selected I2C peripheral */
+	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
+
+	/* Configure I2Cx: Frequency range */
+	mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR,
+		      hi2c->i2c_init.timing & TIMING_CLEAR_MASK);
+
+	/* Disable Own Address1 before set the Own Address1 configuration */
+	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN);
+
+	/* Configure I2Cx: Own Address1 and ack own address1 mode */
+	if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
+		mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
+			      I2C_OAR1_OA1EN | hi2c->i2c_init.own_address1);
+	} else { /* I2C_ADDRESSINGMODE_10BIT */
+		mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
+			      I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE |
+			      hi2c->i2c_init.own_address1);
+	}
+
+	/* Configure I2Cx: Addressing Master mode */
+	if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_10BIT) {
+		mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10);
+	}
+
+	/*
+	 * Enable the AUTOEND by default, and enable NACK
+	 * (should be disable only during Slave process)
+	 */
+	mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
+			I2C_CR2_AUTOEND | I2C_CR2_NACK);
+
+	/* Disable Own Address2 before set the Own Address2 configuration */
+	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE);
+
+	/* Configure I2Cx: Dual mode and Own Address2 */
+	mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2,
+		      hi2c->i2c_init.dual_address_mode |
+		      hi2c->i2c_init.own_address2 |
+		      (hi2c->i2c_init.own_address2_masks << 8));
+
+	/* Configure I2Cx: Generalcall and NoStretch mode */
+	mmio_write_32(hi2c->i2c_base_addr + I2C_CR1,
+		      hi2c->i2c_init.general_call_mode |
+		      hi2c->i2c_init.no_stretch_mode);
+
+	/* Enable the selected I2C peripheral */
+	mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
+
+	hi2c->i2c_err = I2C_ERROR_NONE;
+	hi2c->i2c_state = I2C_STATE_READY;
+	hi2c->i2c_mode = I2C_MODE_NONE;
+
+	return 0;
+}
+
+/*
+ * @brief  Write an amount of data in blocking mode to a specific memory address
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2C.
+ * @param  dev_addr: Target device address
+ * @param  mem_addr: Internal memory address
+ * @param  mem_add_size: size of internal memory address
+ * @param  p_data: Pointer to data buffer
+ * @param  size: Amount of data to be sent
+ * @param  timeout: timeout duration
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+			uint16_t mem_addr, uint16_t mem_add_size,
+			uint8_t *p_data, uint16_t size, uint32_t timeout)
+{
+	uint32_t tickstart;
+
+	if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
+		return -EBUSY;
+	}
+
+	if ((p_data == NULL) || (size == 0U)) {
+		return -EINVAL;
+	}
+
+	hi2c->lock = 1;
+
+	tickstart = (uint32_t)read_cntpct_el0();
+
+	if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, I2C_TIMEOUT_BUSY,
+			  tickstart) != 0) {
+		return -EIO;
+	}
+
+	hi2c->i2c_state     = I2C_STATE_BUSY_TX;
+	hi2c->i2c_mode      = I2C_MODE_MEM;
+	hi2c->i2c_err = I2C_ERROR_NONE;
+
+	hi2c->p_buff  = p_data;
+	hi2c->xfer_count = size;
+
+	/* Send Slave Address and Memory Address */
+	if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, mem_add_size,
+				     timeout, tickstart) != 0) {
+		hi2c->lock = 0;
+		return -EIO;
+	}
+
+	/*
+	 * Set NBYTES to write and reload
+	 * if hi2c->xfer_count > MAX_NBYTE_SIZE
+	 */
+	if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
+		hi2c->xfer_size = MAX_NBYTE_SIZE;
+		i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
+				    I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+	} else {
+		hi2c->xfer_size = hi2c->xfer_count;
+		i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
+				    I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+	}
+
+	do {
+		if (i2c_wait_txis(hi2c, timeout, tickstart) != 0) {
+			return -EIO;
+		}
+
+		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *hi2c->p_buff);
+		hi2c->p_buff++;
+		hi2c->xfer_count--;
+		hi2c->xfer_size--;
+
+		if ((hi2c->xfer_count != 0U) && (hi2c->xfer_size == 0U)) {
+			/* Wait until TCR flag is set */
+			if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout,
+					  tickstart) != 0) {
+				return -EIO;
+		}
+
+			if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
+				hi2c->xfer_size = MAX_NBYTE_SIZE;
+				i2c_transfer_config(hi2c, dev_addr,
+						    hi2c->xfer_size,
+						    I2C_RELOAD_MODE,
+						    I2C_NO_STARTSTOP);
+			} else {
+				hi2c->xfer_size = hi2c->xfer_count;
+				i2c_transfer_config(hi2c, dev_addr,
+						    hi2c->xfer_size,
+						    I2C_AUTOEND_MODE,
+						    I2C_NO_STARTSTOP);
+			}
+		}
+
+	} while (hi2c->xfer_count > 0U);
+
+	/*
+	 * No need to Check TC flag, with AUTOEND mode the stop
+	 * is automatically generated.
+	 * Wait until STOPF flag is reset.
+	 */
+	if (i2c_wait_stop(hi2c, timeout, tickstart) != 0) {
+		return -EIO;
+	}
+
+	mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
+
+	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
+
+	hi2c->i2c_state = I2C_STATE_READY;
+	hi2c->i2c_mode  = I2C_MODE_NONE;
+
+	hi2c->lock = 0;
+
+	return 0;
+}
+
+/*
+ * @brief  Read an amount of data in blocking mode from a specific memory
+ *	   address
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2C.
+ * @param  dev_addr: Target device address
+ * @param  mem_addr: Internal memory address
+ * @param  mem_add_size: size of internal memory address
+ * @param  p_data: Pointer to data buffer
+ * @param  size: Amount of data to be sent
+ * @param  timeout: timeout duration
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+		       uint16_t mem_addr, uint16_t mem_add_size,
+		       uint8_t *p_data, uint16_t size, uint32_t timeout)
+{
+	uint32_t tickstart;
+
+	if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
+		return -EBUSY;
+	}
+
+	if ((p_data == NULL) || (size == 0U)) {
+		return  -EINVAL;
+	}
+
+	hi2c->lock = 1;
+
+	tickstart = (uint32_t)read_cntpct_el0();
+
+	if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, I2C_TIMEOUT_BUSY,
+			  tickstart) != 0) {
+		return -EIO;
+	}
+
+	hi2c->i2c_state     = I2C_STATE_BUSY_RX;
+	hi2c->i2c_mode      = I2C_MODE_MEM;
+	hi2c->i2c_err = I2C_ERROR_NONE;
+
+	hi2c->p_buff  = p_data;
+	hi2c->xfer_count = size;
+
+	/* Send Slave Address and Memory Address */
+	if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, mem_add_size,
+				    timeout, tickstart) != 0) {
+		hi2c->lock = 0;
+		return -EIO;
+	}
+
+	/*
+	 * Send Slave Address.
+	 * Set NBYTES to write and reload if hi2c->xfer_count > MAX_NBYTE_SIZE
+	 * and generate RESTART.
+	 */
+	if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
+		hi2c->xfer_size = MAX_NBYTE_SIZE;
+		i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
+				    I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
+	} else {
+		hi2c->xfer_size = hi2c->xfer_count;
+		i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
+				    I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
+	}
+
+	do {
+		if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout,
+				  tickstart) != 0) {
+			return -EIO;
+		}
+
+		*hi2c->p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR);
+		hi2c->p_buff++;
+		hi2c->xfer_size--;
+		hi2c->xfer_count--;
+
+		if ((hi2c->xfer_count != 0U) && (hi2c->xfer_size == 0U)) {
+			if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout,
+					  tickstart) != 0) {
+				return -EIO;
+			}
+
+			if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
+				hi2c->xfer_size = MAX_NBYTE_SIZE;
+				i2c_transfer_config(hi2c, dev_addr,
+						    hi2c->xfer_size,
+						    I2C_RELOAD_MODE,
+						    I2C_NO_STARTSTOP);
+			} else {
+				hi2c->xfer_size = hi2c->xfer_count;
+				i2c_transfer_config(hi2c, dev_addr,
+						    hi2c->xfer_size,
+						    I2C_AUTOEND_MODE,
+						    I2C_NO_STARTSTOP);
+			}
+		}
+	} while (hi2c->xfer_count > 0U);
+
+	/*
+	 * No need to Check TC flag, with AUTOEND mode the stop
+	 * is automatically generated
+	 * Wait until STOPF flag is reset
+	 */
+	if (i2c_wait_stop(hi2c, timeout, tickstart) != 0) {
+		return -EIO;
+	}
+
+	mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
+
+	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
+
+	hi2c->i2c_state = I2C_STATE_READY;
+	hi2c->i2c_mode  = I2C_MODE_NONE;
+
+	hi2c->lock = 0;
+
+	return 0;
+}
+
+/*
+ * @brief  Checks if target device is ready for communication.
+ * @note   This function is used with Memory devices
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2C.
+ * @param  dev_addr: Target device address
+ * @param  trials: Number of trials
+ * @param  timeout: timeout duration
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c,
+			      uint16_t dev_addr, uint32_t trials,
+			      uint32_t timeout)
+{
+	uint32_t i2c_trials = 0U;
+
+	if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
+		return -EBUSY;
+	}
+
+	if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) !=
+	    0U) {
+		return -EBUSY;
+	}
+
+	hi2c->lock = 1;
+
+	hi2c->i2c_state = I2C_STATE_BUSY;
+	hi2c->i2c_err = I2C_ERROR_NONE;
+
+	do {
+		uint32_t tickstart;
+
+		/* Generate Start */
+		if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
+			mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
+				      (((uint32_t)dev_addr & I2C_CR2_SADD) |
+				       I2C_CR2_START | I2C_CR2_AUTOEND) &
+				       ~I2C_CR2_RD_WRN);
+		} else {
+			mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
+				      (((uint32_t)dev_addr & I2C_CR2_SADD) |
+				       I2C_CR2_START | I2C_CR2_ADD10) &
+				      ~I2C_CR2_RD_WRN);
+		}
+
+		/*
+		 * No need to Check TC flag, with AUTOEND mode the stop
+		 * is automatically generated
+		 * Wait until STOPF flag is set or a NACK flag is set
+		 */
+		tickstart = (uint32_t)read_cntpct_el0();
+		while (((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+			 (I2C_FLAG_STOPF | I2C_FLAG_AF)) == 0U) &&
+		       (hi2c->i2c_state != I2C_STATE_TIMEOUT)) {
+			if (timeout != MAX_DELAY) {
+				if ((((uint32_t)read_cntpct_el0() - tickstart) >
+				     timeout) || (timeout == 0U)) {
+					hi2c->i2c_state = I2C_STATE_READY;
+
+					hi2c->i2c_err |=
+						I2C_ERROR_TIMEOUT;
+
+					hi2c->lock = 0;
+
+					return -EIO;
+				}
+			}
+		}
+
+		/* Check if the NACKF flag has not been set */
+		if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+		     I2C_FLAG_AF) == 0U) {
+			if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout,
+					  tickstart) != 0) {
+				return -EIO;
+			}
+
+			mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
+				      I2C_FLAG_STOPF);
+
+			hi2c->i2c_state = I2C_STATE_READY;
+
+			hi2c->lock = 0;
+
+			return 0;
+		}
+
+		if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout,
+				  tickstart) != 0) {
+			return -EIO;
+		}
+
+		mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
+
+		mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
+
+		if (i2c_trials == trials) {
+			mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
+					I2C_CR2_STOP);
+
+			if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout,
+					  tickstart) != 0) {
+				return -EIO;
+			}
+
+			mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
+				      I2C_FLAG_STOPF);
+		}
+
+		i2c_trials++;
+	} while (i2c_trials < trials);
+
+	hi2c->i2c_state = I2C_STATE_READY;
+
+	hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
+
+	hi2c->lock = 0;
+
+	return -EIO;
+}
+
+/*
+ * @brief  Master sends target device address followed by internal memory
+ *	   address for write request.
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2C.
+ * @param  dev_addr: Target device address
+ * @param  mem_addr: Internal memory address
+ * @param  mem_add_size: size of internal memory address
+ * @param  timeout: timeout duration
+ * @param  tick_start Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
+				    uint16_t dev_addr, uint16_t mem_addr,
+				    uint16_t mem_add_size, uint32_t timeout,
+				    uint32_t tick_start)
+{
+	i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE,
+			    I2C_GENERATE_START_WRITE);
+
+	if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
+		return -EIO;
+	}
+
+	if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
+		/* Send Memory Address */
+		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+			     (uint8_t)(mem_addr & 0x00FFU));
+	} else {
+		/* Send MSB of Memory Address */
+		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+			     (uint8_t)((mem_addr & 0xFF00U) >> 8));
+
+		/* Wait until TXIS flag is set */
+		if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
+			return -EIO;
+		}
+
+		/* Send LSB of Memory Address */
+		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+			     (uint8_t)(mem_addr & 0x00FFU));
+	}
+
+	if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout, tick_start) !=
+	    0) {
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * @brief  Master sends target device address followed by internal memory
+ *	   address for read request.
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2C.
+ * @param  dev_addr: Target device address
+ * @param  mem_addr: Internal memory address
+ * @param  mem_add_size: size of internal memory address
+ * @param  timeout: timeout duration
+ * @param  tick_start Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+				   uint16_t mem_addr, uint16_t mem_add_size,
+				   uint32_t timeout, uint32_t tick_start)
+{
+	i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE,
+			    I2C_GENERATE_START_WRITE);
+
+	if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
+		return -EIO;
+	}
+
+	if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
+		/* Send Memory Address */
+		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+			     (uint8_t)(mem_addr & 0x00FFU));
+	} else {
+		/* Send MSB of Memory Address */
+		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+			     (uint8_t)((mem_addr & 0xFF00U) >> 8));
+
+		/* Wait until TXIS flag is set */
+		if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
+			return -EIO;
+		}
+
+		/* Send LSB of Memory Address */
+		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+			     (uint8_t)(mem_addr & 0x00FFU));
+	}
+
+	if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout, tick_start) != 0) {
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * @brief  I2C Tx data register flush process.
+ * @param  hi2c: I2C handle.
+ * @retval None
+ */
+static void i2c_flush_txdr(struct i2c_handle_s *hi2c)
+{
+	/*
+	 * If a pending TXIS flag is set,
+	 * write a dummy data in TXDR to clear it.
+	 */
+	if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) !=
+	    0U) {
+		mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0);
+	}
+
+	/* Flush TX register if not empty */
+	if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) ==
+	    0U) {
+		mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR,
+				I2C_FLAG_TXE);
+	}
+}
+
+/*
+ * @brief  This function handles I2C Communication timeout.
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2C.
+ * @param  flag: Specifies the I2C flag to check.
+ * @param  awaited_value: The awaited bit value for the flag (0 or 1).
+ * @param  timeout: timeout duration
+ * @param  tick_start: Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
+			 uint8_t awaited_value, uint32_t timeout,
+			 uint32_t tick_start)
+{
+	uint8_t flag_check;
+
+	do {
+		flag_check = ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+			       flag) == flag) ? 1U : 0U;
+
+		if (timeout != MAX_DELAY) {
+			if ((((uint32_t)read_cntpct_el0() - tick_start) >
+			     timeout) || (timeout == 0U)) {
+				hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
+				hi2c->i2c_state = I2C_STATE_READY;
+				hi2c->i2c_mode = I2C_MODE_NONE;
+
+				hi2c->lock = 0;
+				return -EIO;
+			}
+		}
+	} while (flag_check == awaited_value);
+
+	return 0;
+}
+
+/*
+ * @brief  This function handles I2C Communication timeout for specific usage
+ *	   of TXIS flag.
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2C.
+ * @param  timeout: timeout duration
+ * @param  tick_start: Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint32_t timeout,
+			 uint32_t tick_start)
+{
+	while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+		I2C_FLAG_TXIS) == 0U) {
+		if (i2c_ack_failed(hi2c, timeout, tick_start) != 0) {
+			return -EIO;
+		}
+
+		if (timeout != MAX_DELAY) {
+			if ((((uint32_t)read_cntpct_el0() - tick_start) >
+			     timeout) || (timeout == 0U)) {
+				hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
+				hi2c->i2c_state = I2C_STATE_READY;
+				hi2c->i2c_mode = I2C_MODE_NONE;
+
+				hi2c->lock = 0;
+
+				return -EIO;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * @brief  This function handles I2C Communication timeout for specific
+ *	   usage of STOP flag.
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2C.
+ * @param  timeout: timeout duration
+ * @param  tick_start: Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout,
+			 uint32_t tick_start)
+{
+	while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+		 I2C_FLAG_STOPF) == 0U) {
+		if (i2c_ack_failed(hi2c, timeout, tick_start) != 0) {
+			return -EIO;
+		}
+
+		if ((((uint32_t)read_cntpct_el0() - tick_start) > timeout) ||
+		    (timeout == 0U)) {
+			hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
+			hi2c->i2c_state = I2C_STATE_READY;
+			hi2c->i2c_mode = I2C_MODE_NONE;
+
+			hi2c->lock = 0;
+
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * @brief  This function handles Acknowledge failed detection during
+ *	   an I2C Communication.
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2C.
+ * @param  timeout: timeout duration
+ * @param  tick_start: Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout,
+			  uint32_t tick_start)
+{
+	if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) {
+		return 0;
+	}
+
+	/*
+	 * Wait until STOP Flag is reset.
+	 * AutoEnd should be initiate after AF.
+	 */
+	while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+		I2C_FLAG_STOPF) == 0U) {
+		if (timeout != MAX_DELAY) {
+			if ((((uint32_t)read_cntpct_el0() - tick_start) >
+			     timeout) || (timeout == 0U)) {
+				hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
+				hi2c->i2c_state = I2C_STATE_READY;
+				hi2c->i2c_mode = I2C_MODE_NONE;
+
+				hi2c->lock = 0;
+
+				return -EIO;
+			}
+		}
+	}
+
+	mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
+
+	mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
+
+	i2c_flush_txdr(hi2c);
+
+	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
+
+	hi2c->i2c_err |= I2C_ERROR_AF;
+	hi2c->i2c_state = I2C_STATE_READY;
+	hi2c->i2c_mode = I2C_MODE_NONE;
+
+	hi2c->lock = 0;
+
+	return -EIO;
+}
+
+/*
+ * @brief  Handles I2Cx communication when starting transfer or during transfer
+ *	   (TC or TCR flag are set).
+ * @param  hi2c: I2C handle.
+ * @param  dev_addr: Specifies the slave address to be programmed.
+ * @param  size: Specifies the number of bytes to be programmed.
+ *   This parameter must be a value between 0 and 255.
+ * @param  i2c_mode: New state of the I2C START condition generation.
+ *   This parameter can be one of the following values:
+ *     @arg @ref I2C_RELOAD_MODE: Enable Reload mode .
+ *     @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode.
+ *     @arg @ref I2C_SOFTEND_MODE: Enable Software end mode.
+ * @param  request: New state of the I2C START condition generation.
+ *   This parameter can be one of the following values:
+ *     @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition.
+ *     @arg @ref I2C_GENERATE_STOP: Generate stop condition
+ *                                  (size should be set to 0).
+ *     @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request.
+ *     @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request.
+ * @retval None
+ */
+static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+				uint16_t size, uint32_t i2c_mode,
+				uint32_t request)
+{
+	uint32_t clr_value, set_value;
+
+	clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD |
+		     I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) |
+		(I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET)));
+
+	set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) |
+		(((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) |
+		i2c_mode | request;
+
+	mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value);
+}
+
+/*
+ * @brief  Configure I2C Analog noise filter.
+ * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
+ *               the configuration information for the specified I2Cx peripheral
+ * @param  analog_filter: New state of the Analog filter.
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c,
+				   uint32_t analog_filter)
+{
+	if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
+		return -EBUSY;
+	}
+
+	hi2c->lock = 1;
+
+	hi2c->i2c_state = I2C_STATE_BUSY;
+
+	/* Disable the selected I2C peripheral */
+	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
+
+	/* Reset I2Cx ANOFF bit */
+	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF);
+
+	/* Set analog filter bit*/
+	mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter);
+
+	/* Enable the selected I2C peripheral */
+	mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
+
+	hi2c->i2c_state = I2C_STATE_READY;
+
+	hi2c->lock = 0;
+
+	return 0;
+}
diff --git a/drivers/st/pmic/stm32mp1_pmic.c b/drivers/st/pmic/stm32mp1_pmic.c
new file mode 100644
index 0000000..958de08
--- /dev/null
+++ b/drivers/st/pmic/stm32mp1_pmic.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stdbool.h>
+#include <stm32_gpio.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_dt.h>
+#include <stm32mp1_pmic.h>
+#include <stpmu1.h>
+#include <utils_def.h>
+
+/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */
+#define I2C_TIMING			0x10D07DB5
+
+#define I2C_TIMEOUT			0xFFFFF
+
+#define MASK_RESET_BUCK3		BIT(2)
+
+#define STPMU1_LDO12356_OUTPUT_MASK	(uint8_t)(GENMASK(6, 2))
+#define STPMU1_LDO12356_OUTPUT_SHIFT	2
+#define STPMU1_LDO3_MODE		(uint8_t)(BIT(7))
+#define STPMU1_LDO3_DDR_SEL		31U
+#define STPMU1_LDO3_1800000		(9U << STPMU1_LDO12356_OUTPUT_SHIFT)
+
+#define STPMU1_BUCK_OUTPUT_SHIFT	2
+#define STPMU1_BUCK3_1V8		(39U << STPMU1_BUCK_OUTPUT_SHIFT)
+
+#define STPMU1_DEFAULT_START_UP_DELAY_MS	1
+
+static struct i2c_handle_s i2c_handle;
+static uint32_t pmic_i2c_addr;
+
+static int dt_get_pmic_node(void *fdt)
+{
+	return fdt_node_offset_by_compatible(fdt, -1, "st,stpmu1");
+}
+
+bool dt_check_pmic(void)
+{
+	int node;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return false;
+	}
+
+	node = dt_get_pmic_node(fdt);
+	if (node < 0) {
+		VERBOSE("%s: No PMIC node found in DT\n", __func__);
+		return false;
+	}
+
+	return fdt_check_status(node);
+}
+
+static int dt_pmic_i2c_config(struct dt_node_info *i2c_info)
+{
+	int pmic_node, i2c_node;
+	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 -FDT_ERR_NOTFOUND;
+	}
+
+	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 dt_set_pinctrl_config(i2c_node);
+}
+
+int dt_pmic_enable_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");
+
+	fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
+		const fdt32_t *cuint;
+		const char *node_name;
+		uint16_t voltage;
+
+		if (fdt_getprop(fdt, regulator_node, "regulator-boot-on",
+				NULL) == NULL) {
+			continue;
+		}
+
+		cuint = fdt_getprop(fdt, regulator_node,
+				    "regulator-min-microvolt", NULL);
+		if (cuint == NULL) {
+			continue;
+		}
+
+		/* DT uses microvolts, whereas driver awaits millivolts */
+		voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
+		node_name = fdt_get_name(fdt, regulator_node, NULL);
+
+		if (stpmu1_is_regulator_enabled(node_name) == 0U) {
+			int status;
+
+			status = stpmu1_regulator_voltage_set(node_name,
+							      voltage);
+			if (status != 0) {
+				return status;
+			}
+
+			status = stpmu1_regulator_enable(node_name);
+			if (status != 0) {
+				return status;
+			}
+		}
+	}
+
+	return 0;
+}
+
+void initialize_pmic_i2c(void)
+{
+	int ret;
+	struct dt_node_info i2c_info;
+
+	if (dt_pmic_i2c_config(&i2c_info) != 0) {
+		ERROR("I2C configuration failed\n");
+		panic();
+	}
+
+	if (stm32mp1_clk_enable((uint32_t)i2c_info.clock) < 0) {
+		ERROR("I2C clock enable failed\n");
+		panic();
+	}
+
+	/* Initialize PMIC I2C */
+	i2c_handle.i2c_base_addr		= i2c_info.base;
+	i2c_handle.i2c_init.timing		= I2C_TIMING;
+	i2c_handle.i2c_init.own_address1	= pmic_i2c_addr;
+	i2c_handle.i2c_init.addressing_mode	= I2C_ADDRESSINGMODE_7BIT;
+	i2c_handle.i2c_init.dual_address_mode	= I2C_DUALADDRESS_DISABLE;
+	i2c_handle.i2c_init.own_address2	= 0;
+	i2c_handle.i2c_init.own_address2_masks	= I2C_OAR2_OA2NOMASK;
+	i2c_handle.i2c_init.general_call_mode	= I2C_GENERALCALL_DISABLE;
+	i2c_handle.i2c_init.no_stretch_mode	= I2C_NOSTRETCH_DISABLE;
+
+	ret = stm32_i2c_init(&i2c_handle);
+	if (ret != 0) {
+		ERROR("Cannot initialize I2C %x (%d)\n",
+		      i2c_handle.i2c_base_addr, ret);
+		panic();
+	}
+
+	ret = stm32_i2c_config_analog_filter(&i2c_handle,
+					     I2C_ANALOGFILTER_ENABLE);
+	if (ret != 0) {
+		ERROR("Cannot initialize I2C analog filter (%d)\n", ret);
+		panic();
+	}
+
+	ret = stm32_i2c_is_device_ready(&i2c_handle, (uint16_t)pmic_i2c_addr, 1,
+					I2C_TIMEOUT);
+	if (ret != 0) {
+		ERROR("I2C device not ready (%d)\n", ret);
+		panic();
+	}
+
+	stpmu1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr);
+}
+
+void initialize_pmic(void)
+{
+	int status;
+	uint8_t read_val;
+
+	initialize_pmic_i2c();
+
+	status = stpmu1_register_read(VERSION_STATUS_REG, &read_val);
+	if (status != 0) {
+		panic();
+	}
+
+	INFO("PMIC version = 0x%x\n", read_val);
+
+	/* Keep VDD on during the reset cycle */
+	status = stpmu1_register_update(MASK_RESET_BUCK_REG,
+					MASK_RESET_BUCK3,
+					MASK_RESET_BUCK3);
+	if (status != 0) {
+		panic();
+	}
+}
+
+int pmic_ddr_power_init(enum ddr_type ddr_type)
+{
+	bool buck3_at_1v8 = false;
+	uint8_t read_val;
+	int status;
+
+	switch (ddr_type) {
+	case STM32MP_DDR3:
+		/* Set LDO3 to sync mode */
+		status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val);
+		if (status != 0) {
+			return status;
+		}
+
+		read_val &= ~STPMU1_LDO3_MODE;
+		read_val &= ~STPMU1_LDO12356_OUTPUT_MASK;
+		read_val |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT;
+
+		status = stpmu1_register_write(LDO3_CONTROL_REG, read_val);
+		if (status != 0) {
+			return status;
+		}
+
+		status = stpmu1_regulator_voltage_set("buck2", 1350);
+		if (status != 0) {
+			return status;
+		}
+
+		status = stpmu1_regulator_enable("buck2");
+		if (status != 0) {
+			return status;
+		}
+
+		mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+
+		status = stpmu1_regulator_enable("vref_ddr");
+		if (status != 0) {
+			return status;
+		}
+
+		mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+
+		status = stpmu1_regulator_enable("ldo3");
+		if (status != 0) {
+			return status;
+		}
+
+		mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+		break;
+
+	case STM32MP_LPDDR2:
+		/*
+		 * Set LDO3 to 1.8V
+		 * Set LDO3 to bypass mode if BUCK3 = 1.8V
+		 * Set LDO3 to normal mode if BUCK3 != 1.8V
+		 */
+		status = stpmu1_register_read(BUCK3_CONTROL_REG, &read_val);
+		if (status != 0) {
+			return status;
+		}
+
+		if ((read_val & STPMU1_BUCK3_1V8) == STPMU1_BUCK3_1V8) {
+			buck3_at_1v8 = true;
+		}
+
+		status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val);
+		if (status != 0) {
+			return status;
+		}
+
+		read_val &= ~STPMU1_LDO3_MODE;
+		read_val &= ~STPMU1_LDO12356_OUTPUT_MASK;
+		read_val |= STPMU1_LDO3_1800000;
+		if (buck3_at_1v8) {
+			read_val |= STPMU1_LDO3_MODE;
+		}
+
+		status = stpmu1_register_write(LDO3_CONTROL_REG, read_val);
+		if (status != 0) {
+			return status;
+		}
+
+		status = stpmu1_regulator_voltage_set("buck2", 1200);
+		if (status != 0) {
+			return status;
+		}
+
+		status = stpmu1_regulator_enable("ldo3");
+		if (status != 0) {
+			return status;
+		}
+
+		mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+
+		status = stpmu1_regulator_enable("buck2");
+		if (status != 0) {
+			return status;
+		}
+
+		mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+
+		status = stpmu1_regulator_enable("vref_ddr");
+		if (status != 0) {
+			return status;
+		}
+
+		mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+		break;
+
+	default:
+		break;
+	};
+
+	return 0;
+}
diff --git a/drivers/st/pmic/stpmu1.c b/drivers/st/pmic/stpmu1.c
new file mode 100644
index 0000000..5951899
--- /dev/null
+++ b/drivers/st/pmic/stpmu1.c
@@ -0,0 +1,600 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <platform.h>
+#include <stpmu1.h>
+#include <string.h>
+
+struct regul_struct {
+	const char *dt_node_name;
+	const uint16_t *voltage_table;
+	uint8_t voltage_table_size;
+	uint8_t control_reg;
+	uint8_t low_power_reg;
+};
+
+static struct i2c_handle_s *stpmu_i2c_handle;
+static uint16_t stpmu_i2c_addr;
+
+/* Voltage tables in mV */
+static const uint16_t buck1_voltage_table[] = {
+	600,
+	625,
+	650,
+	675,
+	700,
+	725,
+	750,
+	775,
+	800,
+	825,
+	850,
+	875,
+	900,
+	925,
+	950,
+	975,
+	1000,
+	1025,
+	1050,
+	1075,
+	1100,
+	1125,
+	1150,
+	1175,
+	1200,
+	1225,
+	1250,
+	1275,
+	1300,
+	1325,
+	1350,
+	1350,
+};
+
+static const uint16_t buck2_voltage_table[] = {
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1050,
+	1050,
+	1100,
+	1100,
+	1150,
+	1150,
+	1200,
+	1200,
+	1250,
+	1250,
+	1300,
+	1300,
+	1350,
+	1350,
+	1400,
+	1400,
+	1450,
+	1450,
+	1500,
+};
+
+static const uint16_t buck3_voltage_table[] = {
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1000,
+	1100,
+	1100,
+	1100,
+	1100,
+	1200,
+	1200,
+	1200,
+	1200,
+	1300,
+	1300,
+	1300,
+	1300,
+	1400,
+	1400,
+	1400,
+	1400,
+	1500,
+	1600,
+	1700,
+	1800,
+	1900,
+	2000,
+	2100,
+	2200,
+	2300,
+	2400,
+	2500,
+	2600,
+	2700,
+	2800,
+	2900,
+	3000,
+	3100,
+	3200,
+	3300,
+	3400,
+};
+
+static const uint16_t buck4_voltage_table[] = {
+	600,
+	625,
+	650,
+	675,
+	700,
+	725,
+	750,
+	775,
+	800,
+	825,
+	850,
+	875,
+	900,
+	925,
+	950,
+	975,
+	1000,
+	1025,
+	1050,
+	1075,
+	1100,
+	1125,
+	1150,
+	1175,
+	1200,
+	1225,
+	1250,
+	1275,
+	1300,
+	1300,
+	1350,
+	1350,
+	1400,
+	1400,
+	1450,
+	1450,
+	1500,
+	1600,
+	1700,
+	1800,
+	1900,
+	2000,
+	2100,
+	2200,
+	2300,
+	2400,
+	2500,
+	2600,
+	2700,
+	2800,
+	2900,
+	3000,
+	3100,
+	3200,
+	3300,
+	3400,
+	3500,
+	3600,
+	3700,
+	3800,
+	3900,
+};
+
+static const uint16_t ldo1_voltage_table[] = {
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1800,
+	1900,
+	2000,
+	2100,
+	2200,
+	2300,
+	2400,
+	2500,
+	2600,
+	2700,
+	2800,
+	2900,
+	3000,
+	3100,
+	3200,
+	3300,
+};
+
+static const uint16_t ldo2_voltage_table[] = {
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1800,
+	1900,
+	2000,
+	2100,
+	2200,
+	2300,
+	2400,
+	2500,
+	2600,
+	2700,
+	2800,
+	2900,
+	3000,
+	3100,
+	3200,
+	3300,
+};
+
+static const uint16_t ldo3_voltage_table[] = {
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1800,
+	1900,
+	2000,
+	2100,
+	2200,
+	2300,
+	2400,
+	2500,
+	2600,
+	2700,
+	2800,
+	2900,
+	3000,
+	3100,
+	3200,
+	3300,
+	3300,
+	3300,
+	3300,
+	3300,
+	3300,
+	3300,
+	0xFFFF, /* VREFDDR */
+};
+
+static const uint16_t ldo5_voltage_table[] = {
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1700,
+	1800,
+	1900,
+	2000,
+	2100,
+	2200,
+	2300,
+	2400,
+	2500,
+	2600,
+	2700,
+	2800,
+	2900,
+	3000,
+	3100,
+	3200,
+	3300,
+	3400,
+	3500,
+	3600,
+	3700,
+	3800,
+	3900,
+};
+
+static const uint16_t ldo6_voltage_table[] = {
+	900,
+	1000,
+	1100,
+	1200,
+	1300,
+	1400,
+	1500,
+	1600,
+	1700,
+	1800,
+	1900,
+	2000,
+	2100,
+	2200,
+	2300,
+	2400,
+	2500,
+	2600,
+	2700,
+	2800,
+	2900,
+	3000,
+	3100,
+	3200,
+	3300,
+};
+
+static const uint16_t ldo4_voltage_table[] = {
+	3300,
+};
+
+static const uint16_t vref_ddr_voltage_table[] = {
+	3300,
+};
+
+/* Table of Regulators in PMIC SoC */
+static const struct regul_struct regulators_table[] = {
+	{
+		.dt_node_name	= "buck1",
+		.voltage_table	= buck1_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(buck1_voltage_table),
+		.control_reg	= BUCK1_CONTROL_REG,
+		.low_power_reg	= BUCK1_PWRCTRL_REG,
+	},
+	{
+		.dt_node_name	= "buck2",
+		.voltage_table	= buck2_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(buck2_voltage_table),
+		.control_reg	= BUCK2_CONTROL_REG,
+		.low_power_reg	= BUCK2_PWRCTRL_REG,
+	},
+	{
+		.dt_node_name	= "buck3",
+		.voltage_table	= buck3_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(buck3_voltage_table),
+		.control_reg	= BUCK3_CONTROL_REG,
+		.low_power_reg	= BUCK3_PWRCTRL_REG,
+	},
+	{
+		.dt_node_name	= "buck4",
+		.voltage_table	= buck4_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(buck4_voltage_table),
+		.control_reg	= BUCK4_CONTROL_REG,
+		.low_power_reg	= BUCK4_PWRCTRL_REG,
+	},
+	{
+		.dt_node_name	= "ldo1",
+		.voltage_table	= ldo1_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(ldo1_voltage_table),
+		.control_reg	= LDO1_CONTROL_REG,
+		.low_power_reg	= LDO1_PWRCTRL_REG,
+	},
+	{
+		.dt_node_name	= "ldo2",
+		.voltage_table	= ldo2_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(ldo2_voltage_table),
+		.control_reg	= LDO2_CONTROL_REG,
+		.low_power_reg	= LDO2_PWRCTRL_REG,
+	},
+	{
+		.dt_node_name	= "ldo3",
+		.voltage_table	= ldo3_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(ldo3_voltage_table),
+		.control_reg	= LDO3_CONTROL_REG,
+		.low_power_reg	= LDO3_PWRCTRL_REG,
+	},
+	{
+		.dt_node_name	= "ldo4",
+		.voltage_table	= ldo4_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(ldo4_voltage_table),
+		.control_reg	= LDO4_CONTROL_REG,
+		.low_power_reg	= LDO4_PWRCTRL_REG,
+	},
+	{
+		.dt_node_name	= "ldo5",
+		.voltage_table	= ldo5_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(ldo5_voltage_table),
+		.control_reg	= LDO5_CONTROL_REG,
+		.low_power_reg	= LDO5_PWRCTRL_REG,
+	},
+	{
+		.dt_node_name	= "ldo6",
+		.voltage_table	= ldo6_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(ldo6_voltage_table),
+		.control_reg	= LDO6_CONTROL_REG,
+		.low_power_reg	= LDO6_PWRCTRL_REG,
+	},
+	{
+		.dt_node_name	= "vref_ddr",
+		.voltage_table	= vref_ddr_voltage_table,
+		.voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table),
+		.control_reg	= VREF_DDR_CONTROL_REG,
+		.low_power_reg	= VREF_DDR_PWRCTRL_REG,
+	},
+};
+
+#define MAX_REGUL  ARRAY_SIZE(regulators_table)
+
+static const struct regul_struct *stpmu1_get_regulator_data(const char *name)
+{
+	uint8_t i;
+
+	for (i = 0 ; i < MAX_REGUL ; i++) {
+		if (strncmp(name, regulators_table[i].dt_node_name,
+			    strlen(regulators_table[i].dt_node_name)) == 0) {
+			return &regulators_table[i];
+		}
+	}
+
+	/* Regulator not found */
+	panic();
+	return NULL;
+}
+
+static uint8_t stpmu1_voltage_find_index(const char *name,
+					 uint16_t millivolts)
+{
+	const struct regul_struct *regul = stpmu1_get_regulator_data(name);
+	uint8_t i;
+
+	for (i = 0 ; i < regul->voltage_table_size ; i++) {
+		if (regul->voltage_table[i] == millivolts) {
+			return i;
+		}
+	}
+
+	/* Voltage not found */
+	panic();
+
+	return 0;
+}
+
+int stpmu1_switch_off(void)
+{
+	return stpmu1_register_update(MAIN_CONTROL_REG, 1,
+				      SOFTWARE_SWITCH_OFF_ENABLED);
+}
+
+int stpmu1_regulator_enable(const char *name)
+{
+	const struct regul_struct *regul = stpmu1_get_regulator_data(name);
+
+	return stpmu1_register_update(regul->control_reg, BIT(0), BIT(0));
+}
+
+int stpmu1_regulator_disable(const char *name)
+{
+	const struct regul_struct *regul = stpmu1_get_regulator_data(name);
+
+	return stpmu1_register_update(regul->control_reg, 0, BIT(0));
+}
+
+uint8_t stpmu1_is_regulator_enabled(const char *name)
+{
+	uint8_t val;
+	const struct regul_struct *regul = stpmu1_get_regulator_data(name);
+
+	if (stpmu1_register_read(regul->control_reg, &val) != 0) {
+		panic();
+	}
+
+	return (val & 0x1U);
+}
+
+int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts)
+{
+	uint8_t voltage_index = stpmu1_voltage_find_index(name, millivolts);
+	const struct regul_struct *regul = stpmu1_get_regulator_data(name);
+
+	return stpmu1_register_update(regul->control_reg, voltage_index << 2,
+				      0xFC);
+}
+
+int stpmu1_register_read(uint8_t register_id,  uint8_t *value)
+{
+	return stm32_i2c_mem_read(stpmu_i2c_handle, stpmu_i2c_addr,
+				    (uint16_t)register_id, I2C_MEMADD_SIZE_8BIT,
+				    value, 1, 100000);
+}
+
+int stpmu1_register_write(uint8_t register_id, uint8_t value)
+{
+	int status;
+
+	status = stm32_i2c_mem_write(stpmu_i2c_handle, stpmu_i2c_addr,
+				     (uint16_t)register_id,
+				     I2C_MEMADD_SIZE_8BIT, &value, 1, 100000);
+
+	if (status != 0) {
+		return status;
+	}
+
+	if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) {
+		uint8_t readval;
+
+		status = stpmu1_register_read(register_id, &readval);
+		if (status != 0) {
+			return status;
+		}
+
+		if (readval != value) {
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask)
+{
+	int status;
+	uint8_t val;
+
+	status = stpmu1_register_read(register_id, &val);
+	if (status != 0) {
+		return status;
+	}
+
+	/* Clear bits to update */
+	val &= ~mask;
+
+	/* Update appropriate bits*/
+	val |= (value & mask);
+
+	/* Send new value on I2C Bus */
+	return stpmu1_register_write(register_id, val);
+}
+
+void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr)
+{
+	stpmu_i2c_handle = i2c_handle;
+	stpmu_i2c_addr = i2c_addr;
+}
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/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S
new file mode 100644
index 0000000..792703a
--- /dev/null
+++ b/drivers/st/uart/aarch32/stm32_console.S
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <asm_macros.S>
+
+#define USART_TIMEOUT		0x1000
+
+#define USART_CR1		0x00
+#define USART_CR1_UE		0x00000001
+#define USART_CR1_TE		0x00000008
+#define USART_CR1_FIFOEN	0x20000000
+
+#define USART_CR2		0x04
+#define USART_CR2_STOP		0x00003000
+
+#define USART_BRR		0x0C
+
+#define USART_ISR		0x1C
+#define USART_ISR_TC		0x00000040
+#define USART_ISR_TXE		0x00000080
+#define USART_ISR_TEACK		0x00200000
+
+#define USART_TDR		0x28
+
+	.globl	console_core_init
+	.globl	console_core_putc
+	.globl	console_core_getc
+	.globl	console_core_flush
+
+	/* -----------------------------------------------------------------
+	 * int console_core_init(uintptr_t base_addr,
+	 *			 unsigned int uart_clk,
+	 *			 unsigned int baud_rate)
+	 *
+	 * Function to initialize the console without a C Runtime to print
+	 * debug information. This function will be accessed by console_init
+	 * and crash reporting.
+	 *
+	 * In: r0 - console base address
+	 *     r1 - Uart clock in Hz
+	 *     r2 - Baud rate
+	 * Out: return 1 on success else 0 on error
+	 * Clobber list : r1, r2, r3
+	 * -----------------------------------------------------------------
+	 */
+func console_core_init
+	/* Check the input base address */
+	cmp	r0, #0
+	beq	core_init_fail
+#if defined(IMAGE_BL2)
+	/* Check baud rate and uart clock for sanity */
+	cmp	r1, #0
+	beq	core_init_fail
+	cmp	r2, #0
+	beq	core_init_fail
+	/* Disable UART */
+	ldr	r3, [r0, #USART_CR1]
+	bic	r3, r3, #USART_CR1_UE
+	str	r3, [r0, #USART_CR1]
+	/* Configure UART */
+	orr	r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN)
+	str	r3, [r0, #USART_CR1]
+	ldr	r3, [r0, #USART_CR2]
+	bic	r3, r3, #USART_CR2_STOP
+	str	r3, [r0, #USART_CR2]
+	/* Divisor =  (Uart clock + (baudrate / 2)) / baudrate */
+	lsl	r3, r2, #1
+	add	r3, r1, r3
+	udiv	r3, r3, r2
+	str	r3, [r0, #USART_BRR]
+	/* Enable UART */
+	ldr	r3, [r0, #USART_CR1]
+	orr	r3, r3, #USART_CR1_UE
+	str	r3, [r0, #USART_CR1]
+	/* Check TEACK bit */
+	mov	r2, #USART_TIMEOUT
+teack_loop:
+	subs	r2, r2, #1
+	beq	core_init_fail
+	ldr	r3, [r0, #USART_ISR]
+	tst	r3, #USART_ISR_TEACK
+	beq	teack_loop
+#endif /* IMAGE_BL2 */
+	mov	r0, #1
+	bx	lr
+core_init_fail:
+	mov	r0, #0
+	bx	lr
+endfunc console_core_init
+
+	/* ---------------------------------------------------------------
+	 * int console_core_putc(int c, uintptr_t base_addr)
+	 *
+	 * Function to output a character over the console. It returns the
+	 * character printed on success or -1 on error.
+	 *
+	 * In : r0 - character to be printed
+	 *      r1 - console base address
+	 * Out : return -1 on error else return character.
+	 * Clobber list : r2
+	 * ---------------------------------------------------------------
+	 */
+func console_core_putc
+	/* Check the input parameter */
+	cmp	r1, #0
+	beq	putc_error
+	/* Prepend '\r' to '\n' */
+	cmp	r0, #0xA
+	bne	2f
+1:
+	/* Check Transmit Data Register Empty */
+txe_loop_1:
+	ldr	r2, [r1, #USART_ISR]
+	tst	r2, #USART_ISR_TXE
+	beq	txe_loop_1
+	mov	r2, #0xD
+	str	r2, [r1, #USART_TDR]
+	/* Check transmit complete flag */
+tc_loop_1:
+	ldr	r2, [r1, #USART_ISR]
+	tst	r2, #USART_ISR_TC
+	beq	tc_loop_1
+2:
+	/* Check Transmit Data Register Empty */
+txe_loop_2:
+	ldr	r2, [r1, #USART_ISR]
+	tst	r2, #USART_ISR_TXE
+	beq	txe_loop_2
+	str	r0, [r1, #USART_TDR]
+	/* Check transmit complete flag */
+tc_loop_2:
+	ldr	r2, [r1, #USART_ISR]
+	tst	r2, #USART_ISR_TC
+	beq	tc_loop_2
+	bx	lr
+putc_error:
+	mov	r0, #-1
+	bx	lr
+endfunc console_core_putc
+
+	/* -----------------------------------------------------------
+	 * int console_core_getc(uintptr_t base_addr)
+	 *
+	 * Function to get a character from the console.
+	 * It returns the character grabbed on success or -1 on error.
+	 *
+	 * In : r0 - console base address
+	 * Out : return -1.
+	 * Clobber list : r0, r1
+	 * -----------------------------------------------------------
+	 */
+func console_core_getc
+	/* Not supported */
+	mov	r0, #-1
+	bx	lr
+endfunc console_core_getc
+
+	/* ---------------------------------------------------------------
+	 * int console_core_flush(uintptr_t base_addr)
+	 *
+	 * Function to force a write of all buffered data that hasn't been
+	 * output.
+	 *
+	 * In : r0 - console base address
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : r0, r1
+	 * ---------------------------------------------------------------
+	 */
+func console_core_flush
+	cmp	r0, #0
+	beq	flush_error
+	/* Check Transmit Data Register Empty */
+txe_loop_3:
+	ldr	r1, [r0, #USART_ISR]
+	tst	r1, #USART_ISR_TXE
+	beq	txe_loop_3
+	mov	r0, #0
+	bx	lr
+flush_error:
+	mov	r0, #-1
+	bx	lr
+endfunc console_core_flush
diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi
new file mode 100644
index 0000000..be4e2c3
--- /dev/null
+++ b/fdts/stm32mp15-ddr.dtsi
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+/ {
+	soc {
+		ddr: ddr@0x5A003000{
+
+			compatible = "st,stm32mp1-ddr";
+
+			reg = <0x5A003000 0x550
+			       0x5A004000 0x234>;
+
+			clocks = <&rcc AXIDCG>,
+				 <&rcc DDRC1>,
+				 <&rcc DDRC2>,
+				 <&rcc DDRPHYC>,
+				 <&rcc DDRCAPB>,
+				 <&rcc DDRPHYCAPB>;
+
+			clock-names = "axidcg",
+				      "ddrc1",
+				      "ddrc2",
+				      "ddrphyc",
+				      "ddrcapb",
+				      "ddrphycapb";
+
+			st,mem-name = DDR_MEM_NAME;
+			st,mem-speed = <DDR_MEM_SPEED>;
+			st,mem-size = <DDR_MEM_SIZE>;
+
+			st,ctl-reg = <
+				DDR_MSTR
+				DDR_MRCTRL0
+				DDR_MRCTRL1
+				DDR_DERATEEN
+				DDR_DERATEINT
+				DDR_PWRCTL
+				DDR_PWRTMG
+				DDR_HWLPCTL
+				DDR_RFSHCTL0
+				DDR_RFSHCTL3
+				DDR_CRCPARCTL0
+				DDR_ZQCTL0
+				DDR_DFITMG0
+				DDR_DFITMG1
+				DDR_DFILPCFG0
+				DDR_DFIUPD0
+				DDR_DFIUPD1
+				DDR_DFIUPD2
+				DDR_DFIPHYMSTR
+				DDR_ODTMAP
+				DDR_DBG0
+				DDR_DBG1
+				DDR_DBGCMD
+				DDR_POISONCFG
+				DDR_PCCFG
+			>;
+
+			st,ctl-timing = <
+				DDR_RFSHTMG
+				DDR_DRAMTMG0
+				DDR_DRAMTMG1
+				DDR_DRAMTMG2
+				DDR_DRAMTMG3
+				DDR_DRAMTMG4
+				DDR_DRAMTMG5
+				DDR_DRAMTMG6
+				DDR_DRAMTMG7
+				DDR_DRAMTMG8
+				DDR_DRAMTMG14
+				DDR_ODTCFG
+			>;
+
+			st,ctl-map = <
+				DDR_ADDRMAP1
+				DDR_ADDRMAP2
+				DDR_ADDRMAP3
+				DDR_ADDRMAP4
+				DDR_ADDRMAP5
+				DDR_ADDRMAP6
+				DDR_ADDRMAP9
+				DDR_ADDRMAP10
+				DDR_ADDRMAP11
+			>;
+
+			st,ctl-perf = <
+				DDR_SCHED
+				DDR_SCHED1
+				DDR_PERFHPR1
+				DDR_PERFLPR1
+				DDR_PERFWR1
+				DDR_PCFGR_0
+				DDR_PCFGW_0
+				DDR_PCFGQOS0_0
+				DDR_PCFGQOS1_0
+				DDR_PCFGWQOS0_0
+				DDR_PCFGWQOS1_0
+				DDR_PCFGR_1
+				DDR_PCFGW_1
+				DDR_PCFGQOS0_1
+				DDR_PCFGQOS1_1
+				DDR_PCFGWQOS0_1
+				DDR_PCFGWQOS1_1
+			>;
+
+			st,phy-reg = <
+				DDR_PGCR
+				DDR_ACIOCR
+				DDR_DXCCR
+				DDR_DSGCR
+				DDR_DCR
+				DDR_ODTCR
+				DDR_ZQ0CR1
+				DDR_DX0GCR
+				DDR_DX1GCR
+				DDR_DX2GCR
+				DDR_DX3GCR
+			>;
+
+			st,phy-timing = <
+				DDR_PTR0
+				DDR_PTR1
+				DDR_PTR2
+				DDR_DTPR0
+				DDR_DTPR1
+				DDR_DTPR2
+				DDR_MR0
+				DDR_MR1
+				DDR_MR2
+				DDR_MR3
+			>;
+
+			st,phy-cal = <
+				DDR_DX0DLLCR
+				DDR_DX0DQTR
+				DDR_DX0DQSTR
+				DDR_DX1DLLCR
+				DDR_DX1DQTR
+				DDR_DX1DQSTR
+				DDR_DX2DLLCR
+				DDR_DX2DQTR
+				DDR_DX2DQSTR
+				DDR_DX3DLLCR
+				DDR_DX3DQTR
+				DDR_DX3DQSTR
+			>;
+
+			status = "okay";
+		};
+	};
+};
diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
new file mode 100644
index 0000000..58a4cdc
--- /dev/null
+++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+/* STM32MP157C ED1 and ED2 BOARD configuration
+ * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology.
+ * Reference used NT5CC256M16DP-DI from NANYA
+ *
+ * DDR type / Platform	DDR3/3L
+ * freq		533MHz
+ * width	32
+ * datasheet	0  = MT41J256M16-187 / DDR3-1066 bin G
+ * DDR density	8
+ * timing mode	optimized
+ * Scheduling/QoS options : type = 2
+ * address mapping : RBC
+ */
+
+#define DDR_MEM_NAME "DDR3-1066 bin G 2x4Gb 533MHz v1.39"
+#define DDR_MEM_SPEED 533
+#define DDR_MEM_SIZE 0x40000000
+
+#define DDR_MSTR 0x00040401
+#define DDR_MRCTRL0 0x00000010
+#define DDR_MRCTRL1 0x00000000
+#define DDR_DERATEEN 0x00000000
+#define DDR_DERATEINT 0x00800000
+#define DDR_PWRCTL 0x00000000
+#define DDR_PWRTMG 0x00400010
+#define DDR_HWLPCTL 0x00000000
+#define DDR_RFSHCTL0 0x00210000
+#define DDR_RFSHCTL3 0x00000000
+#define DDR_RFSHTMG 0x0081008B
+#define DDR_CRCPARCTL0 0x00000000
+#define DDR_DRAMTMG0 0x121B2414
+#define DDR_DRAMTMG1 0x000A041C
+#define DDR_DRAMTMG2 0x0608090F
+#define DDR_DRAMTMG3 0x0050400C
+#define DDR_DRAMTMG4 0x08040608
+#define DDR_DRAMTMG5 0x06060403
+#define DDR_DRAMTMG6 0x02020002
+#define DDR_DRAMTMG7 0x00000202
+#define DDR_DRAMTMG8 0x00001005
+#define DDR_DRAMTMG14 0x000000A0
+#define DDR_ZQCTL0 0xC2000040
+#define DDR_DFITMG0 0x02060105
+#define DDR_DFITMG1 0x00000202
+#define DDR_DFILPCFG0 0x07000000
+#define DDR_DFIUPD0 0xC0400003
+#define DDR_DFIUPD1 0x00000000
+#define DDR_DFIUPD2 0x00000000
+#define DDR_DFIPHYMSTR 0x00000000
+#define DDR_ADDRMAP1 0x00080808
+#define DDR_ADDRMAP2 0x00000000
+#define DDR_ADDRMAP3 0x00000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x07070707
+#define DDR_ADDRMAP6 0x0F070707
+#define DDR_ADDRMAP9 0x00000000
+#define DDR_ADDRMAP10 0x00000000
+#define DDR_ADDRMAP11 0x00000000
+#define DDR_ODTCFG 0x06000600
+#define DDR_ODTMAP 0x00000001
+#define DDR_SCHED 0x00001201
+#define DDR_SCHED1 0x00000000
+#define DDR_PERFHPR1 0x01000001
+#define DDR_PERFLPR1 0x08000200
+#define DDR_PERFWR1 0x08000400
+#define DDR_DBG0 0x00000000
+#define DDR_DBG1 0x00000000
+#define DDR_DBGCMD 0x00000000
+#define DDR_POISONCFG 0x00000000
+#define DDR_PCCFG 0x00000010
+#define DDR_PCFGR_0 0x00010000
+#define DDR_PCFGW_0 0x00000000
+#define DDR_PCFGQOS0_0 0x02100B03
+#define DDR_PCFGQOS1_0 0x00800100
+#define DDR_PCFGWQOS0_0 0x01100B03
+#define DDR_PCFGWQOS1_0 0x01000200
+#define DDR_PCFGR_1 0x00010000
+#define DDR_PCFGW_1 0x00000000
+#define DDR_PCFGQOS0_1 0x02100B03
+#define DDR_PCFGQOS1_1 0x00800000
+#define DDR_PCFGWQOS0_1 0x01100B03
+#define DDR_PCFGWQOS1_1 0x01000200
+#define DDR_PGCR 0x01442E02
+#define DDR_PTR0 0x0022AA5B
+#define DDR_PTR1 0x04841104
+#define DDR_PTR2 0x042DA068
+#define DDR_ACIOCR 0x10400812
+#define DDR_DXCCR 0x00000C40
+#define DDR_DSGCR 0xF200001F
+#define DDR_DCR 0x0000000B
+#define DDR_DTPR0 0x38D488D0
+#define DDR_DTPR1 0x098B00D8
+#define DDR_DTPR2 0x10023600
+#define DDR_MR0 0x00000840
+#define DDR_MR1 0x00000000
+#define DDR_MR2 0x00000208
+#define DDR_MR3 0x00000000
+#define DDR_ODTCR 0x00010000
+#define DDR_ZQ0CR1 0x00000038
+#define DDR_DX0GCR 0x0000CE81
+#define DDR_DX0DLLCR 0x40000000
+#define DDR_DX0DQTR 0xFFFFFFFF
+#define DDR_DX0DQSTR 0x3DB02000
+#define DDR_DX1GCR 0x0000CE81
+#define DDR_DX1DLLCR 0x40000000
+#define DDR_DX1DQTR 0xFFFFFFFF
+#define DDR_DX1DQSTR 0x3DB02000
+#define DDR_DX2GCR 0x0000CE81
+#define DDR_DX2DLLCR 0x40000000
+#define DDR_DX2DQTR 0xFFFFFFFF
+#define DDR_DX2DQSTR 0x3DB02000
+#define DDR_DX3GCR 0x0000CE81
+#define DDR_DX3DLLCR 0x40000000
+#define DDR_DX3DQTR 0xFFFFFFFF
+#define DDR_DX3DQSTR 0x3DB02000
+
+#include "stm32mp15-ddr.dtsi"
diff --git a/fdts/stm32mp157-pinctrl.dtsi b/fdts/stm32mp157-pinctrl.dtsi
new file mode 100644
index 0000000..21bd34e
--- /dev/null
+++ b/fdts/stm32mp157-pinctrl.dtsi
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
+ */
+
+#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+/ {
+	soc {
+		pinctrl: pin-controller {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x50002000 0xa400>;
+			pins-are-numbered;
+
+			gpioa: gpio@50002000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x0 0x400>;
+				clocks = <&rcc GPIOA>;
+				st,bank-name = "GPIOA";
+				status = "disabled";
+			};
+
+			gpiob: gpio@50003000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x1000 0x400>;
+				clocks = <&rcc GPIOB>;
+				st,bank-name = "GPIOB";
+				status = "disabled";
+			};
+
+			gpioc: gpio@50004000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x2000 0x400>;
+				clocks = <&rcc GPIOC>;
+				st,bank-name = "GPIOC";
+				status = "disabled";
+			};
+
+			gpiod: gpio@50005000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x3000 0x400>;
+				clocks = <&rcc GPIOD>;
+				st,bank-name = "GPIOD";
+				status = "disabled";
+			};
+
+			gpioe: gpio@50006000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x4000 0x400>;
+				clocks = <&rcc GPIOE>;
+				st,bank-name = "GPIOE";
+				status = "disabled";
+			};
+
+			gpiof: gpio@50007000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x5000 0x400>;
+				clocks = <&rcc GPIOF>;
+				st,bank-name = "GPIOF";
+				status = "disabled";
+			};
+
+			gpiog: gpio@50008000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x6000 0x400>;
+				clocks = <&rcc GPIOG>;
+				st,bank-name = "GPIOG";
+				status = "disabled";
+			};
+
+			gpioh: gpio@50009000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x7000 0x400>;
+				clocks = <&rcc GPIOH>;
+				st,bank-name = "GPIOH";
+				status = "disabled";
+			};
+
+			gpioi: gpio@5000a000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x8000 0x400>;
+				clocks = <&rcc GPIOI>;
+				st,bank-name = "GPIOI";
+				status = "disabled";
+			};
+
+			gpioj: gpio@5000b000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x9000 0x400>;
+				clocks = <&rcc GPIOJ>;
+				st,bank-name = "GPIOJ";
+				status = "disabled";
+			};
+
+			gpiok: gpio@5000c000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0xa000 0x400>;
+				clocks = <&rcc GPIOK>;
+				st,bank-name = "GPIOK";
+				status = "disabled";
+			};
+
+			uart4_pins_a: uart4@0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <0>;
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+					bias-disable;
+				};
+			};
+
+			usart3_pins_a: usart3@0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
+						 <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <0>;
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
+						 <STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */
+					bias-disable;
+				};
+			};
+
+			sdmmc1_b4_pins_a: sdmmc1-b4@0 {
+				pins {
+					pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+						 <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+						 <STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
+						 <STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */
+						 <STM32_PINMUX('C', 12, AF12)>, /* SDMMC1_CK */
+						 <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+					slew-rate = <3>;
+					drive-push-pull;
+					bias-disable;
+				};
+			};
+
+			sdmmc1_dir_pins_a: sdmmc1-dir@0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */
+						 <STM32_PINMUX('C', 7, AF8)>, /* SDMMC1_D123DIR */
+						 <STM32_PINMUX('B', 9, AF11)>; /* SDMMC1_CDIR */
+					slew-rate = <3>;
+					drive-push-pull;
+					bias-pull-up;
+				};
+				pins2{
+					pinmux = <STM32_PINMUX('E', 4, AF8)>; /* SDMMC1_CKIN */
+					bias-pull-up;
+				};
+			};
+
+			sdmmc2_b4_pins_a: sdmmc2-b4@0 {
+				pins {
+					pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
+						 <STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
+						 <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
+						 <STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
+						 <STM32_PINMUX('E', 3, AF9)>, /* SDMMC2_CK */
+						 <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
+					slew-rate = <3>;
+					drive-push-pull;
+					bias-pull-up;
+				};
+			};
+
+			sdmmc2_d47_pins_a: sdmmc2-d47@0 {
+				pins {
+					pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
+						 <STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
+						 <STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */
+						 <STM32_PINMUX('D', 3, AF9)>; /* SDMMC2_D7 */
+					slew-rate = <3>;
+					drive-push-pull;
+					bias-pull-up;
+				};
+			};
+		};
+
+		pinctrl_z: pin-controller-z {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x54004000 0x400>;
+			pins-are-numbered;
+
+			gpioz: gpio@54004000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0 0x400>;
+				clocks = <&rcc GPIOZ>;
+				st,bank-name = "GPIOZ";
+				st,bank-ioport = <11>;
+				status = "disabled";
+			};
+
+			i2c4_pins_a: i2c4@0 {
+				pins {
+					pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
+						 <STM32_PINMUX('Z', 5, AF6)>; /* I2C4_SDA */
+					bias-disable;
+					drive-open-drain;
+					slew-rate = <0>;
+				};
+			};
+		};
+	};
+};
diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts
new file mode 100644
index 0000000..e3dabe8
--- /dev/null
+++ b/fdts/stm32mp157c-ed1.dts
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
+ */
+
+/dts-v1/;
+
+#include "stm32mp157c.dtsi"
+#include "stm32mp157caa-pinctrl.dtsi"
+
+/ {
+	model = "STMicroelectronics STM32MP157C-ED1 pmic eval daughter";
+	compatible = "st,stm32mp157c-ed1", "st,stm32mp157";
+
+	chosen {
+		bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram";
+		stdout-path = "serial3:115200n8";
+	};
+};
+
+&i2c4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_pins_a>;
+	i2c-scl-rising-time-ns = <185>;
+	i2c-scl-falling-time-ns = <20>;
+	status = "okay";
+
+	pmic: stpmu1@33 {
+		compatible = "st,stpmu1";
+		reg = <0x33>;
+		status = "okay";
+
+		st,main_control_register = <0x04>;
+		st,vin_control_register = <0xc0>;
+		st,usb_control_register = <0x30>;
+
+		regulators {
+			compatible = "st,stpmu1-regulators";
+
+			v3v3: buck4 {
+				regulator-name = "v3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-over-current-protection;
+				regulator-initial-mode = <8>;
+
+				regulator-state-standby {
+					regulator-suspend-microvolt = <3300000>;
+					regulator-unchanged-in-suspend;
+					regulator-mode = <8>;
+				};
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+				regulator-state-disk {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_sd: ldo5 {
+				regulator-name = "vdd_sd";
+				regulator-min-microvolt = <2900000>;
+				regulator-max-microvolt = <2900000>;
+				regulator-boot-on;
+
+				regulator-state-standby {
+					regulator-suspend-microvolt = <2900000>;
+					regulator-unchanged-in-suspend;
+				};
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+				regulator-state-disk {
+					regulator-off-in-suspend;
+				};
+			};
+		};
+	};
+};
+
+&iwdg2 {
+	instance = <2>;
+	timeout-sec = <32>;
+	status = "okay";
+};
+
+&rng1 {
+	status = "okay";
+};
+
+&sdmmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
+	broken-cd;
+	st,dirpol;
+	st,negedge;
+	st,pin-ckin;
+	bus-width = <4>;
+	sd-uhs-sdr12;
+	sd-uhs-sdr25;
+	sd-uhs-sdr50;
+	sd-uhs-ddr50;
+	sd-uhs-sdr104;
+	status = "okay";
+};
+
+&sdmmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
+	non-removable;
+	no-sd;
+	no-sdio;
+	st,dirpol;
+	st,negedge;
+	bus-width = <8>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins_a>;
+	resets = <&rcc UART4_R>;
+	status = "okay";
+};
+
+/* ATF Specific */
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"
+
+/ {
+	aliases {
+		gpio0 = &gpioa;
+		gpio1 = &gpiob;
+		gpio2 = &gpioc;
+		gpio3 = &gpiod;
+		gpio4 = &gpioe;
+		gpio5 = &gpiof;
+		gpio6 = &gpiog;
+		gpio7 = &gpioh;
+		gpio8 = &gpioi;
+		gpio9 = &gpioj;
+		gpio10 = &gpiok;
+		gpio25 = &gpioz;
+		i2c3 = &i2c4;
+	};
+
+	soc {
+		stgen: stgen@5C008000 {
+			compatible = "st,stm32-stgen";
+			reg = <0x5C008000 0x1000>;
+			status = "okay";
+		};
+	};
+};
+
+/* CLOCK init */
+&rcc {
+	st,clksrc = <
+		CLK_MPU_PLL1P
+		CLK_AXI_PLL2P
+		CLK_PLL12_HSE
+		CLK_PLL3_HSE
+		CLK_PLL4_HSE
+		CLK_RTC_LSE
+		CLK_MCO1_DISABLED
+		CLK_MCO2_DISABLED
+	>;
+
+	st,clkdiv = <
+		1 /*MPU*/
+		0 /*AXI*/
+		1 /*APB1*/
+		1 /*APB2*/
+		1 /*APB3*/
+		1 /*APB4*/
+		2 /*APB5*/
+		23 /*RTC*/
+		0 /*MCO1*/
+		0 /*MCO2*/
+	>;
+
+	st,pkcs = <
+		CLK_CKPER_HSE
+		CLK_FMC_ACLK
+		CLK_QSPI_ACLK
+		CLK_ETH_DISABLED
+		CLK_SDMMC12_PLL3R
+		CLK_DSI_DSIPLL
+		CLK_STGEN_HSE
+		CLK_USBPHY_HSE
+		CLK_SPI2S1_PLL3Q
+		CLK_SPI2S23_PLL3Q
+		CLK_SPI45_HSI
+		CLK_SPI6_HSI
+		CLK_I2C46_HSI
+		CLK_SDMMC3_PLL3R
+		CLK_USBO_USBPHY
+		CLK_ADC_CKPER
+		CLK_CEC_LSE
+		CLK_I2C12_HSI
+		CLK_I2C35_HSI
+		CLK_UART1_HSI
+		CLK_UART24_HSI
+		CLK_UART35_HSI
+		CLK_UART6_HSI
+		CLK_UART78_HSI
+		CLK_SPDIF_PLL3Q
+		CLK_FDCAN_PLL4Q
+		CLK_SAI1_PLL3Q
+		CLK_SAI2_PLL3Q
+		CLK_SAI3_PLL3Q
+		CLK_SAI4_PLL3Q
+		CLK_RNG1_CSI
+		CLK_RNG2_CSI
+		CLK_LPTIM1_PCLK1
+		CLK_LPTIM23_PCLK3
+		CLK_LPTIM45_PCLK3
+	>;
+
+	/* VCO = 1300.0 MHz => P = 650 (CPU) */
+	pll1: st,pll@0 {
+		cfg = < 2 80 0 0 0 PQR(1,0,0) >;
+		frac = < 0x800 >;
+	};
+
+	/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
+	pll2: st,pll@1 {
+		cfg = < 2 65 1 0 0 PQR(1,1,1) >;
+		frac = < 0x1400 >;
+	};
+
+	/* VCO = 786.4 MHz => P = 197, Q = 49, R = 98 */
+	pll3: st,pll@2 {
+		cfg = < 2 97 3 15 7 PQR(1,1,1) >;
+		frac = < 0x9ba >;
+	};
+
+	/* VCO = 508.0 MHz => P = 56, Q = 56, R = 56 */
+	pll4: st,pll@3 {
+		cfg = < 5 126 8 8 8 PQR(1,1,1) >;
+	};
+};
+
+/delete-node/ &clk_csi;
diff --git a/fdts/stm32mp157c-ev1.dts b/fdts/stm32mp157c-ev1.dts
new file mode 100644
index 0000000..98a9d35
--- /dev/null
+++ b/fdts/stm32mp157c-ev1.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
+ */
+
+/dts-v1/;
+#include "stm32mp157c-ed1.dts"
+
+/ {
+	model = "STMicroelectronics STM32MP157C-EV1 pmic eval daughter on eval mother";
+	compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157";
+
+	chosen {
+		bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram";
+		stdout-path = "serial3:115200n8";
+	};
+};
+
+&usart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usart3_pins_a>;
+	resets = <&rcc USART3_R>;
+	status = "disabled";
+};
diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi
new file mode 100644
index 0000000..8b13c0e
--- /dev/null
+++ b/fdts/stm32mp157c.dtsi
@@ -0,0 +1,240 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
+ */
+
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		serial0 = &usart1;
+		serial1 = &usart2;
+		serial2 = &usart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		serial5 = &usart6;
+		serial6 = &uart7;
+		serial7 = &uart8;
+	};
+
+	clocks {
+		clk_hse: clk-hse {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+
+		clk_hsi: clk-hsi {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <64000000>;
+		};
+
+		clk_lse: clk-lse {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		clk_lsi: clk-lsi {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32000>;
+		};
+
+		clk_csi: clk-csi {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <4000000>;
+		};
+
+		clk_i2s_ckin: i2s_ckin {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <64000000>;
+		};
+
+		clk_dsi_phy: ck_dsi_phy {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		clk_usbo_48m: ck_usbo_48m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <48000000>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		usart2: serial@4000e000 {
+			compatible = "st,stm32h7-usart";
+			reg = <0x4000e000 0x400>;
+			clocks = <&rcc USART2_K>;
+			status = "disabled";
+		};
+
+		usart3: serial@4000f000 {
+			compatible = "st,stm32h7-usart";
+			reg = <0x4000f000 0x400>;
+			clocks = <&rcc USART3_K>;
+			status = "disabled";
+		};
+
+		uart4: serial@40010000 {
+			compatible = "st,stm32h7-uart";
+			reg = <0x40010000 0x400>;
+			clocks = <&rcc UART4_K>;
+			status = "disabled";
+		};
+
+		uart5: serial@40011000 {
+			compatible = "st,stm32h7-uart";
+			reg = <0x40011000 0x400>;
+			clocks = <&rcc UART5_K>;
+			status = "disabled";
+		};
+
+
+		uart7: serial@40018000 {
+			compatible = "st,stm32h7-uart";
+			reg = <0x40018000 0x400>;
+			clocks = <&rcc UART7_K>;
+			status = "disabled";
+		};
+
+		uart8: serial@40019000 {
+			compatible = "st,stm32h7-uart";
+			reg = <0x40019000 0x400>;
+			clocks = <&rcc UART8_K>;
+			status = "disabled";
+		};
+
+		usart6: serial@44003000 {
+			compatible = "st,stm32h7-usart";
+			reg = <0x44003000 0x400>;
+			clocks = <&rcc USART6_K>;
+			status = "disabled";
+		};
+
+		sdmmc3: sdmmc@48004000 {
+			compatible = "st,stm32-sdmmc2";
+			reg = <0x48004000 0x400>, <0x48005000 0x400>;
+			reg-names = "sdmmc", "delay";
+			clocks = <&rcc SDMMC3_K>;
+			resets = <&rcc SDMMC3_R>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			max-frequency = <120000000>;
+			status = "disabled";
+		};
+
+		rcc: rcc@50000000 {
+			compatible = "syscon", "st,stm32mp1-rcc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			reg = <0x50000000 0x1000>;
+		};
+
+		rcc_reboot: rcc-reboot@50000000 {
+				compatible = "syscon-reboot";
+				regmap = <&rcc>;
+				offset = <0x404>;
+				mask = <0x1>;
+		};
+
+		rng1: rng@54003000 {
+			compatible = "st,stm32-rng";
+			reg = <0x54003000 0x400>;
+			clocks = <&rcc RNG1_K>;
+			resets = <&rcc RNG1_R>;
+			status = "disabled";
+		};
+
+		fmc_nand: fmc_nand@58002000 {
+			compatible = "st,stm32mp1-fmc";
+			reg = <0x58002000 0x1000>,
+			      <0x80000000 0x40000>,
+			      <0x81000000 0x40000>,
+			      <0x88000000 0x40000>,
+			      <0x89000000 0x40000>;
+			clocks = <&rcc FMC_K>;
+			resets = <&rcc FMC_R>;
+			status = "disabled";
+		};
+
+		qspi: qspi@58003000 {
+			compatible = "st,stm32f469-qspi";
+			reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
+			clocks = <&rcc QSPI_K>;
+			status = "disabled";
+		};
+
+		sdmmc1: sdmmc@58005000 {
+			compatible = "st,stm32-sdmmc2";
+			reg = <0x58005000 0x1000>, <0x58006000 0x1000>;
+			reg-names = "sdmmc", "delay";
+			clocks = <&rcc SDMMC1_K>;
+			resets = <&rcc SDMMC1_R>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			max-frequency = <120000000>;
+			status = "disabled";
+		};
+
+		sdmmc2: sdmmc@58007000 {
+			compatible = "st,stm32-sdmmc2";
+			reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
+			reg-names = "sdmmc", "delay";
+			clocks = <&rcc SDMMC2_K>;
+			resets = <&rcc SDMMC2_R>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			max-frequency = <120000000>;
+			status = "disabled";
+		};
+
+		iwdg2: iwdg@5a002000 {
+			compatible = "st,stm32mp1-iwdg";
+			reg = <0x5a002000 0x400>;
+			clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
+			clock-names = "pclk", "lsi";
+			status = "disabled";
+		};
+
+		usart1: serial@5c000000 {
+			compatible = "st,stm32h7-usart";
+			reg = <0x5c000000 0x400>;
+			clocks = <&rcc USART1_K>;
+			status = "disabled";
+		};
+
+		i2c4: i2c@5c002000 {
+			compatible = "st,stm32f7-i2c";
+			reg = <0x5c002000 0x400>;
+			clocks = <&rcc I2C4_K>;
+			resets = <&rcc I2C4_R>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		rtc: rtc@5c004000 {
+			compatible = "st,stm32mp1-rtc";
+			reg = <0x5c004000 0x400>;
+			clocks = <&rcc RTCAPB>, <&rcc RTC>;
+			clock-names = "pclk", "rtc_ck";
+		};
+	};
+};
diff --git a/fdts/stm32mp157caa-pinctrl.dtsi b/fdts/stm32mp157caa-pinctrl.dtsi
new file mode 100644
index 0000000..774561a
--- /dev/null
+++ b/fdts/stm32mp157caa-pinctrl.dtsi
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com>
+ */
+
+#include "stm32mp157-pinctrl.dtsi"
+/ {
+	soc {
+		pinctrl: pin-controller {
+			compatible = "st,stm32mp157caa-pinctrl";
+
+			gpioa: gpio@50002000 {
+				status = "okay";
+				ngpios = <16>;
+				gpio-ranges = <&pinctrl 0 0 16>;
+			};
+
+			gpiob: gpio@50003000 {
+				status = "okay";
+				ngpios = <16>;
+				gpio-ranges = <&pinctrl 0 16 16>;
+			};
+
+			gpioc: gpio@50004000 {
+				status = "okay";
+				ngpios = <16>;
+				gpio-ranges = <&pinctrl 0 32 16>;
+			};
+
+			gpiod: gpio@50005000 {
+				status = "okay";
+				ngpios = <16>;
+				gpio-ranges = <&pinctrl 0 48 16>;
+			};
+
+			gpioe: gpio@50006000 {
+				status = "okay";
+				ngpios = <16>;
+				gpio-ranges = <&pinctrl 0 64 16>;
+			};
+
+			gpiof: gpio@50007000 {
+				status = "okay";
+				ngpios = <16>;
+				gpio-ranges = <&pinctrl 0 80 16>;
+			};
+
+			gpiog: gpio@50008000 {
+				status = "okay";
+				ngpios = <16>;
+				gpio-ranges = <&pinctrl 0 96 16>;
+			};
+
+			gpioh: gpio@50009000 {
+				status = "okay";
+				ngpios = <16>;
+				gpio-ranges = <&pinctrl 0 112 16>;
+			};
+
+			gpioi: gpio@5000a000 {
+				status = "okay";
+				ngpios = <16>;
+				gpio-ranges = <&pinctrl 0 128 16>;
+			};
+
+			gpioj: gpio@5000b000 {
+				status = "okay";
+				ngpios = <16>;
+				gpio-ranges = <&pinctrl 0 144 16>;
+			};
+
+			gpiok: gpio@5000c000 {
+				status = "okay";
+				ngpios = <8>;
+				gpio-ranges = <&pinctrl 0 160 8>;
+			};
+		};
+
+		pinctrl_z: pin-controller-z {
+			compatible = "st,stm32mp157caa-z-pinctrl";
+
+			gpioz: gpio@54004000 {
+				status = "okay";
+				ngpios = <8>;
+				gpio-ranges = <&pinctrl_z 0 400 8>;
+			};
+		};
+	};
+};
diff --git a/include/drivers/st/stm32_gpio.h b/include/drivers/st/stm32_gpio.h
new file mode 100644
index 0000000..7a5ccd3
--- /dev/null
+++ b/include/drivers/st/stm32_gpio.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_GPIO_H__
+#define __PLAT_GPIO_H__
+
+#include <utils_def.h>
+
+#define STM32_GPIOA_BANK	U(0x50002000)
+#define STM32_GPIOZ_BANK	U(0x54004000)
+#define STM32_GPIO_BANK_OFFSET	U(0x1000)
+
+#define GPIO_MODE_OFFSET	U(0x00)
+#define GPIO_TYPE_OFFSET	U(0x04)
+#define GPIO_SPEED_OFFSET	U(0x08)
+#define GPIO_PUPD_OFFSET	U(0x0C)
+#define GPIO_BSRR_OFFSET	U(0x18)
+#define GPIO_AFRL_OFFSET	U(0x20)
+#define GPIO_AFRH_OFFSET	U(0x24)
+
+#define GPIO_ALT_LOWER_LIMIT	U(0x08)
+
+#define GPIO_BANK_A		U(0x00)
+#define GPIO_BANK_B		U(0x01)
+#define GPIO_BANK_C		U(0x02)
+#define GPIO_BANK_D		U(0x03)
+#define GPIO_BANK_E		U(0x04)
+#define GPIO_BANK_F		U(0x05)
+#define GPIO_BANK_G		U(0x06)
+#define GPIO_BANK_H		U(0x07)
+#define GPIO_BANK_I		U(0x08)
+#define GPIO_BANK_J		U(0x09)
+#define GPIO_BANK_K		U(0x0A)
+#define GPIO_BANK_Z		U(0x19)
+
+#define GPIO_PIN_0		U(0x00)
+#define GPIO_PIN_1		U(0x01)
+#define GPIO_PIN_2		U(0x02)
+#define GPIO_PIN_3		U(0x03)
+#define GPIO_PIN_4		U(0x04)
+#define GPIO_PIN_5		U(0x05)
+#define GPIO_PIN_6		U(0x06)
+#define GPIO_PIN_7		U(0x07)
+#define GPIO_PIN_8		U(0x08)
+#define GPIO_PIN_9		U(0x09)
+#define GPIO_PIN_10		U(0x0A)
+#define GPIO_PIN_11		U(0x0B)
+#define GPIO_PIN_12		U(0x0C)
+#define GPIO_PIN_13		U(0x0D)
+#define GPIO_PIN_14		U(0x0E)
+#define GPIO_PIN_15		U(0x0F)
+#define GPIO_PIN_MAX		GPIO_PIN_15
+
+#define GPIO_ALTERNATE_0	0x00
+#define GPIO_ALTERNATE_1	0x01
+#define GPIO_ALTERNATE_2	0x02
+#define GPIO_ALTERNATE_3	0x03
+#define GPIO_ALTERNATE_4	0x04
+#define GPIO_ALTERNATE_5	0x05
+#define GPIO_ALTERNATE_6	0x06
+#define GPIO_ALTERNATE_7	0x07
+#define GPIO_ALTERNATE_8	0x08
+#define GPIO_ALTERNATE_9	0x09
+#define GPIO_ALTERNATE_10	0x0A
+#define GPIO_ALTERNATE_11	0x0B
+#define GPIO_ALTERNATE_12	0x0C
+#define GPIO_ALTERNATE_13	0x0D
+#define GPIO_ALTERNATE_14	0x0E
+#define GPIO_ALTERNATE_15	0x0F
+#define GPIO_ALTERNATE_MASK	U(0x0F)
+
+#define GPIO_MODE_INPUT		0x00
+#define GPIO_MODE_OUTPUT	0x01
+#define GPIO_MODE_ALTERNATE	0x02
+#define GPIO_MODE_ANALOG	0x03
+#define GPIO_MODE_MASK		U(0x03)
+
+#define GPIO_OPEN_DRAIN		U(0x10)
+
+#define GPIO_SPEED_LOW		0x00
+#define GPIO_SPEED_MEDIUM	0x01
+#define GPIO_SPEED_FAST		0x02
+#define GPIO_SPEED_HIGH		0x03
+#define GPIO_SPEED_MASK		U(0x03)
+
+#define GPIO_NO_PULL		0x00
+#define GPIO_PULL_UP		0x01
+#define GPIO_PULL_DOWN		0x02
+#define GPIO_PULL_MASK		U(0x03)
+
+#ifndef __ASSEMBLY__
+#include <stdint.h>
+
+void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
+	      uint32_t pull, uint32_t alternate);
+#endif /*__ASSEMBLY__*/
+
+#endif /*__PLAT_GPIO_H__*/
diff --git a/include/drivers/st/stm32_i2c.h b/include/drivers/st/stm32_i2c.h
new file mode 100644
index 0000000..29b9d34
--- /dev/null
+++ b/include/drivers/st/stm32_i2c.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_I2C_H
+#define __STM32MP1_I2C_H
+
+#include <stdint.h>
+#include <utils_def.h>
+
+/* Bit definition for I2C_CR1 register */
+#define I2C_CR1_PE			BIT(0)
+#define I2C_CR1_TXIE			BIT(1)
+#define I2C_CR1_RXIE			BIT(2)
+#define I2C_CR1_ADDRIE			BIT(3)
+#define I2C_CR1_NACKIE			BIT(4)
+#define I2C_CR1_STOPIE			BIT(5)
+#define I2C_CR1_TCIE			BIT(6)
+#define I2C_CR1_ERRIE			BIT(7)
+#define I2C_CR1_DNF			GENMASK(11, 8)
+#define I2C_CR1_ANFOFF			BIT(12)
+#define I2C_CR1_SWRST			BIT(13)
+#define I2C_CR1_TXDMAEN			BIT(14)
+#define I2C_CR1_RXDMAEN			BIT(15)
+#define I2C_CR1_SBC			BIT(16)
+#define I2C_CR1_NOSTRETCH		BIT(17)
+#define I2C_CR1_WUPEN			BIT(18)
+#define I2C_CR1_GCEN			BIT(19)
+#define I2C_CR1_SMBHEN			BIT(22)
+#define I2C_CR1_SMBDEN			BIT(21)
+#define I2C_CR1_ALERTEN			BIT(22)
+#define I2C_CR1_PECEN			BIT(23)
+
+/* Bit definition for I2C_CR2 register */
+#define I2C_CR2_SADD			GENMASK(9, 0)
+#define I2C_CR2_RD_WRN			BIT(10)
+#define I2C_CR2_RD_WRN_OFFSET		10U
+#define I2C_CR2_ADD10			BIT(11)
+#define I2C_CR2_HEAD10R			BIT(12)
+#define I2C_CR2_START			BIT(13)
+#define I2C_CR2_STOP			BIT(14)
+#define I2C_CR2_NACK			BIT(15)
+#define I2C_CR2_NBYTES			GENMASK(23, 16)
+#define I2C_CR2_NBYTES_OFFSET		16U
+#define I2C_CR2_RELOAD			BIT(24)
+#define I2C_CR2_AUTOEND			BIT(25)
+#define I2C_CR2_PECBYTE			BIT(26)
+
+/* Bit definition for I2C_OAR1 register */
+#define I2C_OAR1_OA1			GENMASK(9, 0)
+#define I2C_OAR1_OA1MODE		BIT(10)
+#define I2C_OAR1_OA1EN			BIT(15)
+
+/* Bit definition for I2C_OAR2 register */
+#define I2C_OAR2_OA2			GENMASK(7, 1)
+#define I2C_OAR2_OA2MSK			GENMASK(10, 8)
+#define I2C_OAR2_OA2NOMASK		0
+#define I2C_OAR2_OA2MASK01		BIT(8)
+#define I2C_OAR2_OA2MASK02		BIT(9)
+#define I2C_OAR2_OA2MASK03		GENMASK(9, 8)
+#define I2C_OAR2_OA2MASK04		BIT(10)
+#define I2C_OAR2_OA2MASK05		(BIT(8) | BIT(10))
+#define I2C_OAR2_OA2MASK06		(BIT(9) | BIT(10))
+#define I2C_OAR2_OA2MASK07		GENMASK(10, 8)
+#define I2C_OAR2_OA2EN			BIT(15)
+
+/* Bit definition for I2C_TIMINGR register */
+#define I2C_TIMINGR_SCLL		GENMASK(7, 0)
+#define I2C_TIMINGR_SCLH		GENMASK(15, 8)
+#define I2C_TIMINGR_SDADEL		GENMASK(19, 16)
+#define I2C_TIMINGR_SCLDEL		GENMASK(23, 20)
+#define I2C_TIMINGR_PRESC		GENMASK(31, 28)
+
+/* Bit definition for I2C_TIMEOUTR register */
+#define I2C_TIMEOUTR_TIMEOUTA		GENMASK(11, 0)
+#define I2C_TIMEOUTR_TIDLE		BIT(12)
+#define I2C_TIMEOUTR_TIMOUTEN		BIT(15)
+#define I2C_TIMEOUTR_TIMEOUTB		GENMASK(27, 16)
+#define I2C_TIMEOUTR_TEXTEN		BIT(31)
+
+/* Bit definition for I2C_ISR register */
+#define I2C_ISR_TXE			BIT(0)
+#define I2C_ISR_TXIS			BIT(1)
+#define I2C_ISR_RXNE			BIT(2)
+#define I2C_ISR_ADDR			BIT(3)
+#define I2C_ISR_NACKF			BIT(4)
+#define I2C_ISR_STOPF			BIT(5)
+#define I2C_ISR_TC			BIT(6)
+#define I2C_ISR_TCR			BIT(7)
+#define I2C_ISR_BERR			BIT(8)
+#define I2C_ISR_ARLO			BIT(9)
+#define I2C_ISR_OVR			BIT(10)
+#define I2C_ISR_PECERR			BIT(11)
+#define I2C_ISR_TIMEOUT			BIT(12)
+#define I2C_ISR_ALERT			BIT(13)
+#define I2C_ISR_BUSY			BIT(15)
+#define I2C_ISR_DIR			BIT(16)
+#define I2C_ISR_ADDCODE			GENMASK(23, 17)
+
+/* Bit definition for I2C_ICR register */
+#define I2C_ICR_ADDRCF			BIT(3)
+#define I2C_ICR_NACKCF			BIT(4)
+#define I2C_ICR_STOPCF			BIT(5)
+#define I2C_ICR_BERRCF			BIT(8)
+#define I2C_ICR_ARLOCF			BIT(9)
+#define I2C_ICR_OVRCF			BIT(10)
+#define I2C_ICR_PECCF			BIT(11)
+#define I2C_ICR_TIMOUTCF		BIT(12)
+#define I2C_ICR_ALERTCF			BIT(13)
+
+struct stm32_i2c_init_s {
+	uint32_t timing;           /* Specifies the I2C_TIMINGR_register value
+				    * This parameter is calculated by referring
+				    * to I2C initialization section in Reference
+				    * manual.
+				    */
+
+	uint32_t own_address1;     /* Specifies the first device own address.
+				    * This parameter can be a 7-bit or 10-bit
+				    * address.
+				    */
+
+	uint32_t addressing_mode;  /* Specifies if 7-bit or 10-bit addressing
+				    * mode is selected.
+				    * This parameter can be a value of @ref
+				    * I2C_ADDRESSING_MODE.
+				    */
+
+	uint32_t dual_address_mode; /* Specifies if dual addressing mode is
+				     * selected.
+				     * This parameter can be a value of @ref
+				     * I2C_DUAL_ADDRESSING_MODE.
+				     */
+
+	uint32_t own_address2;     /* Specifies the second device own address
+				    * if dual addressing mode is selected.
+				    * This parameter can be a 7-bit address.
+				    */
+
+	uint32_t own_address2_masks; /* Specifies the acknowledge mask address
+				      * second device own address if dual
+				      * addressing mode is selected.
+				      * This parameter can be a value of @ref
+				      * I2C_OWN_ADDRESS2_MASKS.
+				      */
+
+	uint32_t general_call_mode; /* Specifies if general call mode is
+				     * selected.
+				     * This parameter can be a value of @ref
+				     * I2C_GENERAL_CALL_ADDRESSING_MODE.
+				     */
+
+	uint32_t no_stretch_mode;  /* Specifies if nostretch mode is
+				    * selected.
+				    * This parameter can be a value of @ref
+				    * I2C_NOSTRETCH_MODE.
+				    */
+
+};
+
+enum i2c_state_e {
+	I2C_STATE_RESET          = 0x00U,   /* Peripheral is not yet
+					     * initialized.
+					     */
+	I2C_STATE_READY          = 0x20U,   /* Peripheral Initialized
+					     * and ready for use.
+					     */
+	I2C_STATE_BUSY           = 0x24U,   /* An internal process is
+					     * ongoing.
+					     */
+	I2C_STATE_BUSY_TX        = 0x21U,   /* Data Transmission process
+					     * is ongoing.
+					     */
+	I2C_STATE_BUSY_RX        = 0x22U,   /* Data Reception process
+					     * is ongoing.
+					     */
+	I2C_STATE_LISTEN         = 0x28U,   /* Address Listen Mode is
+					     * ongoing.
+					     */
+	I2C_STATE_BUSY_TX_LISTEN = 0x29U,   /* Address Listen Mode
+					     * and Data Transmission
+					     * process is ongoing.
+					     */
+	I2C_STATE_BUSY_RX_LISTEN = 0x2AU,   /* Address Listen Mode
+					     * and Data Reception
+					     * process is ongoing.
+					     */
+	I2C_STATE_ABORT          = 0x60U,   /* Abort user request ongoing. */
+	I2C_STATE_TIMEOUT        = 0xA0U,   /* Timeout state. */
+	I2C_STATE_ERROR          = 0xE0U    /* Error. */
+
+};
+
+enum i2c_mode_e {
+	I2C_MODE_NONE   = 0x00U,   /* No I2C communication on going.       */
+	I2C_MODE_MASTER = 0x10U,   /* I2C communication is in Master Mode. */
+	I2C_MODE_SLAVE  = 0x20U,   /* I2C communication is in Slave Mode.  */
+	I2C_MODE_MEM    = 0x40U    /* I2C communication is in Memory Mode. */
+
+};
+
+#define I2C_ERROR_NONE		0x00000000U	/* No error              */
+#define I2C_ERROR_BERR		0x00000001U	/* BERR error            */
+#define I2C_ERROR_ARLO		0x00000002U	/* ARLO error            */
+#define I2C_ERROR_AF		0x00000004U	/* ACKF error            */
+#define I2C_ERROR_OVR		0x00000008U	/* OVR error             */
+#define I2C_ERROR_DMA		0x00000010U	/* DMA transfer error    */
+#define I2C_ERROR_TIMEOUT	0x00000020U	/* Timeout error         */
+#define I2C_ERROR_SIZE		0x00000040U	/* Size Management error */
+
+struct i2c_handle_s {
+	uint32_t i2c_base_addr;			/* Registers base address */
+
+	struct stm32_i2c_init_s i2c_init;	/* Communication parameters */
+
+	uint8_t *p_buff;			/* Pointer to transfer buffer */
+
+	uint16_t xfer_size;			/* Transfer size */
+
+	uint16_t xfer_count;			/* Transfer counter */
+
+	uint32_t prev_state;			/* Communication previous
+						 * state
+						 */
+
+	uint8_t lock;				/* Locking object */
+
+	enum i2c_state_e i2c_state;		/* Communication state */
+
+	enum i2c_mode_e i2c_mode;		/* Communication mode */
+
+	uint32_t i2c_err;			/* Error code */
+};
+
+#define I2C_ADDRESSINGMODE_7BIT		0x00000001U
+#define I2C_ADDRESSINGMODE_10BIT	0x00000002U
+
+#define I2C_DUALADDRESS_DISABLE		0x00000000U
+#define I2C_DUALADDRESS_ENABLE		I2C_OAR2_OA2EN
+
+#define I2C_GENERALCALL_DISABLE		0x00000000U
+#define I2C_GENERALCALL_ENABLE		I2C_CR1_GCEN
+
+#define I2C_NOSTRETCH_DISABLE		0x00000000U
+#define I2C_NOSTRETCH_ENABLE		I2C_CR1_NOSTRETCH
+
+#define I2C_MEMADD_SIZE_8BIT		0x00000001U
+#define I2C_MEMADD_SIZE_16BIT		0x00000002U
+
+#define  I2C_RELOAD_MODE		I2C_CR2_RELOAD
+#define  I2C_AUTOEND_MODE		I2C_CR2_AUTOEND
+#define  I2C_SOFTEND_MODE		0x00000000U
+
+#define  I2C_NO_STARTSTOP		0x00000000U
+#define  I2C_GENERATE_STOP		(BIT(31) | I2C_CR2_STOP)
+#define  I2C_GENERATE_START_READ	(BIT(31) | I2C_CR2_START | \
+					 I2C_CR2_RD_WRN)
+#define  I2C_GENERATE_START_WRITE	(BIT(31) | I2C_CR2_START)
+
+#define I2C_FLAG_TXE			I2C_ISR_TXE
+#define I2C_FLAG_TXIS			I2C_ISR_TXIS
+#define I2C_FLAG_RXNE			I2C_ISR_RXNE
+#define I2C_FLAG_ADDR			I2C_ISR_ADDR
+#define I2C_FLAG_AF			I2C_ISR_NACKF
+#define I2C_FLAG_STOPF			I2C_ISR_STOPF
+#define I2C_FLAG_TC			I2C_ISR_TC
+#define I2C_FLAG_TCR			I2C_ISR_TCR
+#define I2C_FLAG_BERR			I2C_ISR_BERR
+#define I2C_FLAG_ARLO			I2C_ISR_ARLO
+#define I2C_FLAG_OVR			I2C_ISR_OVR
+#define I2C_FLAG_PECERR			I2C_ISR_PECERR
+#define I2C_FLAG_TIMEOUT		I2C_ISR_TIMEOUT
+#define I2C_FLAG_ALERT			I2C_ISR_ALERT
+#define I2C_FLAG_BUSY			I2C_ISR_BUSY
+#define I2C_FLAG_DIR			I2C_ISR_DIR
+
+#define I2C_RESET_CR2			(I2C_CR2_SADD | I2C_CR2_HEAD10R | \
+					 I2C_CR2_NBYTES | I2C_CR2_RELOAD  | \
+					 I2C_CR2_RD_WRN)
+
+#define I2C_ANALOGFILTER_ENABLE		((uint32_t)0x00000000U)
+#define I2C_ANALOGFILTER_DISABLE	I2C_CR1_ANFOFF
+
+int stm32_i2c_init(struct i2c_handle_s *hi2c);
+
+int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+			uint16_t mem_addr, uint16_t mem_add_size,
+			uint8_t *p_data, uint16_t size, uint32_t timeout);
+int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+		       uint16_t mem_addr, uint16_t mem_add_size,
+		       uint8_t *p_data, uint16_t size, uint32_t timeout);
+int stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+			      uint32_t trials, uint32_t timeout);
+
+int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c,
+				   uint32_t analog_filter);
+
+#endif /* __STM32MP1_I2C_H */
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_ddr.h b/include/drivers/st/stm32mp1_ddr.h
new file mode 100644
index 0000000..0765664
--- /dev/null
+++ b/include/drivers/st/stm32mp1_ddr.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+ */
+
+#ifndef _STM32MP1_DDR_H
+#define _STM32MP1_DDR_H
+
+#include <stdbool.h>
+
+#define DT_DDR_COMPAT	"st,stm32mp1-ddr"
+
+struct stm32mp1_ddr_size {
+	uint64_t base;
+	uint64_t size;
+};
+
+/**
+ * struct ddr_info
+ *
+ * @dev: pointer for the device
+ * @info: UCLASS RAM information
+ * @ctl: DDR controleur base address
+ * @phy: DDR PHY base address
+ * @syscfg: syscfg base address
+ */
+struct ddr_info {
+	struct stm32mp1_ddr_size info;
+	struct stm32mp1_ddrctl *ctl;
+	struct stm32mp1_ddrphy *phy;
+	uintptr_t pwr;
+	uintptr_t rcc;
+};
+
+struct stm32mp1_ddrctrl_reg {
+	uint32_t mstr;
+	uint32_t mrctrl0;
+	uint32_t mrctrl1;
+	uint32_t derateen;
+	uint32_t derateint;
+	uint32_t pwrctl;
+	uint32_t pwrtmg;
+	uint32_t hwlpctl;
+	uint32_t rfshctl0;
+	uint32_t rfshctl3;
+	uint32_t crcparctl0;
+	uint32_t zqctl0;
+	uint32_t dfitmg0;
+	uint32_t dfitmg1;
+	uint32_t dfilpcfg0;
+	uint32_t dfiupd0;
+	uint32_t dfiupd1;
+	uint32_t dfiupd2;
+	uint32_t dfiphymstr;
+	uint32_t odtmap;
+	uint32_t dbg0;
+	uint32_t dbg1;
+	uint32_t dbgcmd;
+	uint32_t poisoncfg;
+	uint32_t pccfg;
+};
+
+struct stm32mp1_ddrctrl_timing {
+	uint32_t rfshtmg;
+	uint32_t dramtmg0;
+	uint32_t dramtmg1;
+	uint32_t dramtmg2;
+	uint32_t dramtmg3;
+	uint32_t dramtmg4;
+	uint32_t dramtmg5;
+	uint32_t dramtmg6;
+	uint32_t dramtmg7;
+	uint32_t dramtmg8;
+	uint32_t dramtmg14;
+	uint32_t odtcfg;
+};
+
+struct stm32mp1_ddrctrl_map {
+	uint32_t addrmap1;
+	uint32_t addrmap2;
+	uint32_t addrmap3;
+	uint32_t addrmap4;
+	uint32_t addrmap5;
+	uint32_t addrmap6;
+	uint32_t addrmap9;
+	uint32_t addrmap10;
+	uint32_t addrmap11;
+};
+
+struct stm32mp1_ddrctrl_perf {
+	uint32_t sched;
+	uint32_t sched1;
+	uint32_t perfhpr1;
+	uint32_t perflpr1;
+	uint32_t perfwr1;
+	uint32_t pcfgr_0;
+	uint32_t pcfgw_0;
+	uint32_t pcfgqos0_0;
+	uint32_t pcfgqos1_0;
+	uint32_t pcfgwqos0_0;
+	uint32_t pcfgwqos1_0;
+	uint32_t pcfgr_1;
+	uint32_t pcfgw_1;
+	uint32_t pcfgqos0_1;
+	uint32_t pcfgqos1_1;
+	uint32_t pcfgwqos0_1;
+	uint32_t pcfgwqos1_1;
+};
+
+struct stm32mp1_ddrphy_reg {
+	uint32_t pgcr;
+	uint32_t aciocr;
+	uint32_t dxccr;
+	uint32_t dsgcr;
+	uint32_t dcr;
+	uint32_t odtcr;
+	uint32_t zq0cr1;
+	uint32_t dx0gcr;
+	uint32_t dx1gcr;
+	uint32_t dx2gcr;
+	uint32_t dx3gcr;
+};
+
+struct stm32mp1_ddrphy_timing {
+	uint32_t ptr0;
+	uint32_t ptr1;
+	uint32_t ptr2;
+	uint32_t dtpr0;
+	uint32_t dtpr1;
+	uint32_t dtpr2;
+	uint32_t mr0;
+	uint32_t mr1;
+	uint32_t mr2;
+	uint32_t mr3;
+};
+
+struct stm32mp1_ddrphy_cal {
+	uint32_t dx0dllcr;
+	uint32_t dx0dqtr;
+	uint32_t dx0dqstr;
+	uint32_t dx1dllcr;
+	uint32_t dx1dqtr;
+	uint32_t dx1dqstr;
+	uint32_t dx2dllcr;
+	uint32_t dx2dqtr;
+	uint32_t dx2dqstr;
+	uint32_t dx3dllcr;
+	uint32_t dx3dqtr;
+	uint32_t dx3dqstr;
+};
+
+struct stm32mp1_ddr_info {
+	const char *name;
+	uint16_t speed; /* in MHZ */
+	uint32_t size;  /* Memory size in byte = col * row * width */
+};
+
+struct stm32mp1_ddr_config {
+	struct stm32mp1_ddr_info info;
+	struct stm32mp1_ddrctrl_reg c_reg;
+	struct stm32mp1_ddrctrl_timing c_timing;
+	struct stm32mp1_ddrctrl_map c_map;
+	struct stm32mp1_ddrctrl_perf c_perf;
+	struct stm32mp1_ddrphy_reg p_reg;
+	struct stm32mp1_ddrphy_timing p_timing;
+	struct stm32mp1_ddrphy_cal p_cal;
+};
+
+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed);
+void stm32mp1_ddr_init(struct ddr_info *priv,
+		       struct stm32mp1_ddr_config *config);
+#endif /* _STM32MP1_DDR_H */
diff --git a/include/drivers/st/stm32mp1_ddr_helpers.h b/include/drivers/st/stm32mp1_ddr_helpers.h
new file mode 100644
index 0000000..298a080
--- /dev/null
+++ b/include/drivers/st/stm32mp1_ddr_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_DDR_HELPERS_H__
+#define __STM32MP1_DDR_HELPERS_H__
+
+void ddr_enable_clock(void);
+
+#endif /* __STM32MP1_DDR_HELPERS_H__ */
diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h
new file mode 100644
index 0000000..64ad965
--- /dev/null
+++ b/include/drivers/st/stm32mp1_ddr_regs.h
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+ */
+
+#ifndef _RAM_STM32MP1_DDR_REGS_H
+#define _RAM_STM32MP1_DDR_REGS_H
+
+#include <utils_def.h>
+
+/* DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL) registers */
+struct stm32mp1_ddrctl {
+	uint32_t mstr ;		/* 0x0 Master */
+	uint32_t stat;		/* 0x4 Operating Mode Status */
+	uint8_t reserved008[0x10 - 0x8];
+	uint32_t mrctrl0;	/* 0x10 Control 0 */
+	uint32_t mrctrl1;	/* 0x14 Control 1 */
+	uint32_t mrstat;	/* 0x18 Status */
+	uint32_t reserved01c;	/* 0x1c */
+	uint32_t derateen;	/* 0x20 Temperature Derate Enable */
+	uint32_t derateint;	/* 0x24 Temperature Derate Interval */
+	uint8_t reserved028[0x30 - 0x28];
+	uint32_t pwrctl;	/* 0x30 Low Power Control */
+	uint32_t pwrtmg;	/* 0x34 Low Power Timing */
+	uint32_t hwlpctl;	/* 0x38 Hardware Low Power Control */
+	uint8_t reserved03c[0x50 - 0x3C];
+	uint32_t rfshctl0;	/* 0x50 Refresh Control 0 */
+	uint32_t reserved054;	/* 0x54 Refresh Control 1 */
+	uint32_t reserved058;	/* 0x58 Refresh Control 2 */
+	uint32_t reserved05C;
+	uint32_t rfshctl3;	/* 0x60 Refresh Control 0 */
+	uint32_t rfshtmg;	/* 0x64 Refresh Timing */
+	uint8_t reserved068[0xc0 - 0x68];
+	uint32_t crcparctl0;		/* 0xc0 CRC Parity Control0 */
+	uint32_t reserved0c4;	/* 0xc4 CRC Parity Control1 */
+	uint32_t reserved0c8;	/* 0xc8 CRC Parity Control2 */
+	uint32_t crcparstat;		/* 0xcc CRC Parity Status */
+	uint32_t init0;		/* 0xd0 SDRAM Initialization 0 */
+	uint32_t init1;		/* 0xd4 SDRAM Initialization 1 */
+	uint32_t init2;		/* 0xd8 SDRAM Initialization 2 */
+	uint32_t init3;		/* 0xdc SDRAM Initialization 3 */
+	uint32_t init4;		/* 0xe0 SDRAM Initialization 4 */
+	uint32_t init5;		/* 0xe4 SDRAM Initialization 5 */
+	uint32_t reserved0e8;
+	uint32_t reserved0ec;
+	uint32_t dimmctl;	/* 0xf0 DIMM Control */
+	uint8_t reserved0f4[0x100 - 0xf4];
+	uint32_t dramtmg0;	/* 0x100 SDRAM Timing 0 */
+	uint32_t dramtmg1;	/* 0x104 SDRAM Timing 1 */
+	uint32_t dramtmg2;	/* 0x108 SDRAM Timing 2 */
+	uint32_t dramtmg3;	/* 0x10c SDRAM Timing 3 */
+	uint32_t dramtmg4;	/* 0x110 SDRAM Timing 4 */
+	uint32_t dramtmg5;	/* 0x114 SDRAM Timing 5 */
+	uint32_t dramtmg6;	/* 0x118 SDRAM Timing 6 */
+	uint32_t dramtmg7;	/* 0x11c SDRAM Timing 7 */
+	uint32_t dramtmg8;	/* 0x120 SDRAM Timing 8 */
+	uint8_t reserved124[0x138 - 0x124];
+	uint32_t dramtmg14;	/* 0x138 SDRAM Timing 14 */
+	uint32_t dramtmg15;	/* 0x13C SDRAM Timing 15 */
+	uint8_t reserved140[0x180 - 0x140];
+	uint32_t zqctl0;	/* 0x180 ZQ Control 0 */
+	uint32_t zqctl1;	/* 0x184 ZQ Control 1 */
+	uint32_t zqctl2;	/* 0x188 ZQ Control 2 */
+	uint32_t zqstat;	/* 0x18c ZQ Status */
+	uint32_t dfitmg0;	/* 0x190 DFI Timing 0 */
+	uint32_t dfitmg1;	/* 0x194 DFI Timing 1 */
+	uint32_t dfilpcfg0;	/* 0x198 DFI Low Power Configuration 0 */
+	uint32_t reserved19c;
+	uint32_t dfiupd0;	/* 0x1a0 DFI Update 0 */
+	uint32_t dfiupd1;	/* 0x1a4 DFI Update 1 */
+	uint32_t dfiupd2;	/* 0x1a8 DFI Update 2 */
+	uint32_t reserved1ac;
+	uint32_t dfimisc;	/* 0x1b0 DFI Miscellaneous Control */
+	uint8_t reserved1b4[0x1bc - 0x1b4];
+	uint32_t dfistat;	/* 0x1bc DFI Miscellaneous Control */
+	uint8_t reserved1c0[0x1c4 - 0x1c0];
+	uint32_t dfiphymstr;	/* 0x1c4 DFI PHY Master interface */
+	uint8_t reserved1c8[0x204 - 0x1c8];
+	uint32_t addrmap1;	/* 0x204 Address Map 1 */
+	uint32_t addrmap2;	/* 0x208 Address Map 2 */
+	uint32_t addrmap3;	/* 0x20c Address Map 3 */
+	uint32_t addrmap4;	/* 0x210 Address Map 4 */
+	uint32_t addrmap5;	/* 0x214 Address Map 5 */
+	uint32_t addrmap6;	/* 0x218 Address Map 6 */
+	uint8_t reserved21c[0x224 - 0x21c];
+	uint32_t addrmap9;	/* 0x224 Address Map 9 */
+	uint32_t addrmap10;	/* 0x228 Address Map 10 */
+	uint32_t addrmap11;	/* 0x22C Address Map 11 */
+	uint8_t reserved230[0x240 - 0x230];
+	uint32_t odtcfg;	/* 0x240 ODT Configuration */
+	uint32_t odtmap;	/* 0x244 ODT/Rank Map */
+	uint8_t reserved248[0x250 - 0x248];
+	uint32_t sched;		/* 0x250 Scheduler Control */
+	uint32_t sched1;	/* 0x254 Scheduler Control 1 */
+	uint32_t reserved258;
+	uint32_t perfhpr1;	/* 0x25c High Priority Read CAM 1 */
+	uint32_t reserved260;
+	uint32_t perflpr1;	/* 0x264 Low Priority Read CAM 1 */
+	uint32_t reserved268;
+	uint32_t perfwr1;	/* 0x26c Write CAM 1 */
+	uint8_t reserved27c[0x300 - 0x270];
+	uint32_t dbg0;		/* 0x300 Debug 0 */
+	uint32_t dbg1;		/* 0x304 Debug 1 */
+	uint32_t dbgcam;	/* 0x308 CAM Debug */
+	uint32_t dbgcmd;	/* 0x30c Command Debug */
+	uint32_t dbgstat;	/* 0x310 Status Debug */
+	uint8_t reserved314[0x320 - 0x314];
+	uint32_t swctl;		/* 0x320 Software Programming Control Enable */
+	uint32_t swstat;	/* 0x324 Software Programming Control Status */
+	uint8_t reserved328[0x36c - 0x328];
+	uint32_t poisoncfg;	/* 0x36c AXI Poison Configuration Register */
+	uint32_t poisonstat;	/* 0x370 AXI Poison Status Register */
+	uint8_t reserved374[0x3fc - 0x374];
+
+	/* Multi Port registers */
+	uint32_t pstat;		/* 0x3fc Port Status */
+	uint32_t pccfg;		/* 0x400 Port Common Configuration */
+
+	/* PORT 0 */
+	uint32_t pcfgr_0;	/* 0x404 Configuration Read */
+	uint32_t pcfgw_0;	/* 0x408 Configuration Write */
+	uint8_t reserved40c[0x490 - 0x40c];
+	uint32_t pctrl_0;	/* 0x490 Port Control Register */
+	uint32_t pcfgqos0_0;	/* 0x494 Read QoS Configuration 0 */
+	uint32_t pcfgqos1_0;	/* 0x498 Read QoS Configuration 1 */
+	uint32_t pcfgwqos0_0;	/* 0x49c Write QoS Configuration 0 */
+	uint32_t pcfgwqos1_0;	/* 0x4a0 Write QoS Configuration 1 */
+	uint8_t reserved4a4[0x4b4 - 0x4a4];
+
+	/* PORT 1 */
+	uint32_t pcfgr_1;	/* 0x4b4 Configuration Read */
+	uint32_t pcfgw_1;	/* 0x4b8 Configuration Write */
+	uint8_t reserved4bc[0x540 - 0x4bc];
+	uint32_t pctrl_1;	/* 0x540 Port 2 Control Register */
+	uint32_t pcfgqos0_1;	/* 0x544 Read QoS Configuration 0 */
+	uint32_t pcfgqos1_1;	/* 0x548 Read QoS Configuration 1 */
+	uint32_t pcfgwqos0_1;	/* 0x54c Write QoS Configuration 0 */
+	uint32_t pcfgwqos1_1;	/* 0x550 Write QoS Configuration 1 */
+} __packed;
+
+/* DDR Physical Interface Control (DDRPHYC) registers*/
+struct stm32mp1_ddrphy {
+	uint32_t ridr;		/* 0x00 R Revision Identification */
+	uint32_t pir;		/* 0x04 R/W PHY Initialization */
+	uint32_t pgcr;		/* 0x08 R/W PHY General Configuration */
+	uint32_t pgsr;		/* 0x0C PHY General Status */
+	uint32_t dllgcr;	/* 0x10 R/W DLL General Control */
+	uint32_t acdllcr;	/* 0x14 R/W AC DLL Control */
+	uint32_t ptr0;		/* 0x18 R/W PHY Timing 0 */
+	uint32_t ptr1;		/* 0x1C R/W PHY Timing 1 */
+	uint32_t ptr2;		/* 0x20 R/W PHY Timing 2 */
+	uint32_t aciocr;	/* 0x24 AC I/O Configuration */
+	uint32_t dxccr;		/* 0x28 DATX8 Common Configuration */
+	uint32_t dsgcr;		/* 0x2C DDR System General Configuration */
+	uint32_t dcr;		/* 0x30 DRAM Configuration */
+	uint32_t dtpr0;		/* 0x34 DRAM Timing Parameters0 */
+	uint32_t dtpr1;		/* 0x38 DRAM Timing Parameters1 */
+	uint32_t dtpr2;		/* 0x3C DRAM Timing Parameters2 */
+	uint32_t mr0;		/* 0x40 Mode 0 */
+	uint32_t mr1;		/* 0x44 Mode 1 */
+	uint32_t mr2;		/* 0x48 Mode 2 */
+	uint32_t mr3;		/* 0x4C Mode 3 */
+	uint32_t odtcr;		/* 0x50 ODT Configuration */
+	uint32_t dtar;		/* 0x54 data training address */
+	uint32_t dtdr0;		/* 0x58 */
+	uint32_t dtdr1;		/* 0x5c */
+	uint8_t res1[0x0c0 - 0x060];	/* 0x60 */
+	uint32_t dcuar;		/* 0xc0 Address */
+	uint32_t dcudr;		/* 0xc4 DCU Data */
+	uint32_t dcurr;		/* 0xc8 DCU Run */
+	uint32_t dculr;		/* 0xcc DCU Loop */
+	uint32_t dcugcr;	/* 0xd0 DCU General Configuration */
+	uint32_t dcutpr;	/* 0xd4 DCU Timing Parameters */
+	uint32_t dcusr0;	/* 0xd8 DCU Status 0 */
+	uint32_t dcusr1;	/* 0xdc DCU Status 1 */
+	uint8_t res2[0x100 - 0xe0];	/* 0xe0 */
+	uint32_t bistrr;	/* 0x100 BIST Run */
+	uint32_t bistmskr0;	/* 0x104 BIST Mask 0 */
+	uint32_t bistmskr1;	/* 0x108 BIST Mask 0 */
+	uint32_t bistwcr;	/* 0x10c BIST Word Count */
+	uint32_t bistlsr;	/* 0x110 BIST LFSR Seed */
+	uint32_t bistar0;	/* 0x114 BIST Address 0 */
+	uint32_t bistar1;	/* 0x118 BIST Address 1 */
+	uint32_t bistar2;	/* 0x11c BIST Address 2 */
+	uint32_t bistupdr;	/* 0x120 BIST User Data Pattern */
+	uint32_t bistgsr;	/* 0x124 BIST General Status */
+	uint32_t bistwer;	/* 0x128 BIST Word Error */
+	uint32_t bistber0;	/* 0x12c BIST Bit Error 0 */
+	uint32_t bistber1;	/* 0x130 BIST Bit Error 1 */
+	uint32_t bistber2;	/* 0x134 BIST Bit Error 2 */
+	uint32_t bistwcsr;	/* 0x138 BIST Word Count Status */
+	uint32_t bistfwr0;	/* 0x13c BIST Fail Word 0 */
+	uint32_t bistfwr1;	/* 0x140 BIST Fail Word 1 */
+	uint8_t res3[0x178 - 0x144];	/* 0x144 */
+	uint32_t gpr0;		/* 0x178 General Purpose 0 (GPR0) */
+	uint32_t gpr1;		/* 0x17C General Purpose 1 (GPR1) */
+	uint32_t zq0cr0;	/* 0x180 zq 0 control 0 */
+	uint32_t zq0cr1;	/* 0x184 zq 0 control 1 */
+	uint32_t zq0sr0;	/* 0x188 zq 0 status 0 */
+	uint32_t zq0sr1;	/* 0x18C zq 0 status 1 */
+	uint8_t res4[0x1C0 - 0x190];	/* 0x190 */
+	uint32_t dx0gcr;	/* 0x1c0 Byte lane 0 General Configuration */
+	uint32_t dx0gsr0;	/* 0x1c4 Byte lane 0 General Status 0 */
+	uint32_t dx0gsr1;	/* 0x1c8 Byte lane 0 General Status 1 */
+	uint32_t dx0dllcr;	/* 0x1cc Byte lane 0 DLL Control */
+	uint32_t dx0dqtr;	/* 0x1d0 Byte lane 0 DQ Timing */
+	uint32_t dx0dqstr;	/* 0x1d4 Byte lane 0 DQS Timing */
+	uint8_t res5[0x200 - 0x1d8];	/* 0x1d8 */
+	uint32_t dx1gcr;	/* 0x200 Byte lane 1 General Configuration */
+	uint32_t dx1gsr0;	/* 0x204 Byte lane 1 General Status 0 */
+	uint32_t dx1gsr1;	/* 0x208 Byte lane 1 General Status 1 */
+	uint32_t dx1dllcr;	/* 0x20c Byte lane 1 DLL Control */
+	uint32_t dx1dqtr;	/* 0x210 Byte lane 1 DQ Timing */
+	uint32_t dx1dqstr;	/* 0x214 Byte lane 1 QS Timing */
+	uint8_t res6[0x240 - 0x218];	/* 0x218 */
+	uint32_t dx2gcr;	/* 0x240 Byte lane 2 General Configuration */
+	uint32_t dx2gsr0;	/* 0x244 Byte lane 2 General Status 0 */
+	uint32_t dx2gsr1;	/* 0x248 Byte lane 2 General Status 1 */
+	uint32_t dx2dllcr;	/* 0x24c Byte lane 2 DLL Control */
+	uint32_t dx2dqtr;	/* 0x250 Byte lane 2 DQ Timing */
+	uint32_t dx2dqstr;	/* 0x254 Byte lane 2 QS Timing */
+	uint8_t res7[0x280 - 0x258];	/* 0x258 */
+	uint32_t dx3gcr;	/* 0x280 Byte lane 3 General Configuration */
+	uint32_t dx3gsr0;	/* 0x284 Byte lane 3 General Status 0 */
+	uint32_t dx3gsr1;	/* 0x288 Byte lane 3 General Status 1 */
+	uint32_t dx3dllcr;	/* 0x28c Byte lane 3 DLL Control */
+	uint32_t dx3dqtr;	/* 0x290 Byte lane 3 DQ Timing */
+	uint32_t dx3dqstr;	/* 0x294 Byte lane 3 QS Timing */
+} __packed;
+
+/* DDR Controller registers offsets */
+#define DDRCTRL_MSTR				0x000
+#define DDRCTRL_STAT				0x004
+#define DDRCTRL_MRCTRL0				0x010
+#define DDRCTRL_MRSTAT				0x018
+#define DDRCTRL_PWRCTL				0x030
+#define DDRCTRL_PWRTMG				0x034
+#define DDRCTRL_HWLPCTL				0x038
+#define DDRCTRL_RFSHCTL3			0x060
+#define DDRCTRL_RFSHTMG				0x064
+#define DDRCTRL_INIT0				0x0D0
+#define DDRCTRL_DFIMISC				0x1B0
+#define DDRCTRL_DBG1				0x304
+#define DDRCTRL_DBGCAM				0x308
+#define DDRCTRL_DBGCMD				0x30C
+#define DDRCTRL_DBGSTAT				0x310
+#define DDRCTRL_SWCTL				0x320
+#define DDRCTRL_SWSTAT				0x324
+#define DDRCTRL_PCTRL_0				0x490
+#define DDRCTRL_PCTRL_1				0x540
+
+/* DDR Controller Register fields */
+#define DDRCTRL_MSTR_DDR3			BIT(0)
+#define DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK	GENMASK(13, 12)
+#define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL	0
+#define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF	BIT(12)
+#define DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER	BIT(13)
+#define DDRCTRL_MSTR_DLL_OFF_MODE		BIT(15)
+
+#define DDRCTRL_STAT_OPERATING_MODE_MASK	GENMASK(2, 0)
+#define DDRCTRL_STAT_OPERATING_MODE_NORMAL	BIT(0)
+#define DDRCTRL_STAT_OPERATING_MODE_SR		(BIT(0) | BIT(1))
+#define DDRCTRL_STAT_SELFREF_TYPE_MASK		GENMASK(5, 4)
+#define DDRCTRL_STAT_SELFREF_TYPE_ASR		(BIT(4) | BIT(5))
+#define DDRCTRL_STAT_SELFREF_TYPE_SR		BIT(5)
+
+#define DDRCTRL_MRCTRL0_MR_TYPE_WRITE		U(0)
+/* Only one rank supported */
+#define DDRCTRL_MRCTRL0_MR_RANK_SHIFT		4
+#define DDRCTRL_MRCTRL0_MR_RANK_ALL \
+		(0x1U << DDRCTRL_MRCTRL0_MR_RANK_SHIFT)
+#define DDRCTRL_MRCTRL0_MR_ADDR_SHIFT		12
+#define DDRCTRL_MRCTRL0_MR_ADDR_MASK		GENMASK(15, 12)
+#define DDRCTRL_MRCTRL0_MR_WR			BIT(31)
+
+#define DDRCTRL_MRSTAT_MR_WR_BUSY		BIT(0)
+
+#define DDRCTRL_PWRCTL_SELFREF_EN		BIT(0)
+#define DDRCTRL_PWRCTL_POWERDOWN_EN		BIT(1)
+#define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE	BIT(3)
+#define DDRCTRL_PWRCTL_SELFREF_SW		BIT(5)
+
+#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK	GENMASK(19, 12)
+#define DDRCTRL_PWRTMG_SELFREF_TO_X32_0		BIT(16)
+
+#define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH	BIT(0)
+
+#define DDRCTRL_HWLPCTL_HW_LP_EN		BIT(0)
+
+#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK	GENMASK(27, 16)
+#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT	16
+
+#define DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK	GENMASK(31, 30)
+#define DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL	BIT(30)
+
+#define DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN	BIT(0)
+
+#define DDRCTRL_DBG1_DIS_HIF			BIT(1)
+
+#define DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY	BIT(29)
+#define DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY	BIT(28)
+#define DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY		BIT(26)
+#define DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH		GENMASK(12, 8)
+#define DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH		GENMASK(4, 0)
+#define DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY \
+		(DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY | \
+		 DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY)
+#define DDRCTRL_DBGCAM_DBG_Q_DEPTH \
+		(DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY | \
+		 DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH | \
+		 DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH)
+
+#define DDRCTRL_DBGCMD_RANK0_REFRESH		BIT(0)
+
+#define DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY	BIT(0)
+
+#define DDRCTRL_SWCTL_SW_DONE			BIT(0)
+
+#define DDRCTRL_SWSTAT_SW_DONE_ACK		BIT(0)
+
+#define DDRCTRL_PCTRL_N_PORT_EN			BIT(0)
+
+/* DDR PHY registers offsets */
+#define DDRPHYC_PIR				0x004
+#define DDRPHYC_PGCR				0x008
+#define DDRPHYC_PGSR				0x00C
+#define DDRPHYC_DLLGCR				0x010
+#define DDRPHYC_ACDLLCR				0x014
+#define DDRPHYC_PTR0				0x018
+#define DDRPHYC_ACIOCR				0x024
+#define DDRPHYC_DXCCR				0x028
+#define DDRPHYC_DSGCR				0x02C
+#define DDRPHYC_ZQ0CR0				0x180
+#define DDRPHYC_DX0GCR				0x1C0
+#define DDRPHYC_DX0DLLCR			0x1CC
+#define DDRPHYC_DX1GCR				0x200
+#define DDRPHYC_DX1DLLCR			0x20C
+#define DDRPHYC_DX2GCR				0x240
+#define DDRPHYC_DX2DLLCR			0x24C
+#define DDRPHYC_DX3GCR				0x280
+#define DDRPHYC_DX3DLLCR			0x28C
+
+/* DDR PHY Register fields */
+#define DDRPHYC_PIR_INIT			BIT(0)
+#define DDRPHYC_PIR_DLLSRST			BIT(1)
+#define DDRPHYC_PIR_DLLLOCK			BIT(2)
+#define DDRPHYC_PIR_ZCAL			BIT(3)
+#define DDRPHYC_PIR_ITMSRST			BIT(4)
+#define DDRPHYC_PIR_DRAMRST			BIT(5)
+#define DDRPHYC_PIR_DRAMINIT			BIT(6)
+#define DDRPHYC_PIR_QSTRN			BIT(7)
+#define DDRPHYC_PIR_ICPC			BIT(16)
+#define DDRPHYC_PIR_ZCALBYP			BIT(30)
+#define DDRPHYC_PIR_INITSTEPS_MASK		GENMASK(31, 7)
+
+#define DDRPHYC_PGCR_DFTCMP			BIT(2)
+#define DDRPHYC_PGCR_PDDISDX			BIT(24)
+#define DDRPHYC_PGCR_RFSHDT_MASK		GENMASK(28, 25)
+
+#define DDRPHYC_PGSR_IDONE			BIT(0)
+#define DDRPHYC_PGSR_DTERR			BIT(5)
+#define DDRPHYC_PGSR_DTIERR			BIT(6)
+#define DDRPHYC_PGSR_DFTERR			BIT(7)
+#define DDRPHYC_PGSR_RVERR			BIT(8)
+#define DDRPHYC_PGSR_RVEIRR			BIT(9)
+
+#define DDRPHYC_DLLGCR_BPS200			BIT(23)
+
+#define DDRPHYC_ACDLLCR_DLLDIS			BIT(31)
+
+#define DDRPHYC_PTR0_TDLLSRST_OFFSET		0
+#define DDRPHYC_PTR0_TDLLSRST_MASK		GENMASK(5, 0)
+#define DDRPHYC_PTR0_TDLLLOCK_OFFSET		6
+#define DDRPHYC_PTR0_TDLLLOCK_MASK		GENMASK(17, 6)
+#define DDRPHYC_PTR0_TITMSRST_OFFSET		18
+#define DDRPHYC_PTR0_TITMSRST_MASK		GENMASK(21, 18)
+
+#define DDRPHYC_ACIOCR_ACPDD			BIT(3)
+#define DDRPHYC_ACIOCR_ACPDR			BIT(4)
+#define DDRPHYC_ACIOCR_CKPDD_MASK		GENMASK(10, 8)
+#define DDRPHYC_ACIOCR_CKPDD_0			BIT(8)
+#define DDRPHYC_ACIOCR_CKPDR_MASK		GENMASK(13, 11)
+#define DDRPHYC_ACIOCR_CKPDR_0			BIT(11)
+#define DDRPHYC_ACIOCR_CSPDD_MASK		GENMASK(21, 18)
+#define DDRPHYC_ACIOCR_CSPDD_0			BIT(18)
+#define DDRPHYC_ACIOCR_RSTPDD			BIT(27)
+#define DDRPHYC_ACIOCR_RSTPDR			BIT(28)
+
+#define DDRPHYC_DXCCR_DXPDD			BIT(2)
+#define DDRPHYC_DXCCR_DXPDR			BIT(3)
+
+#define DDRPHYC_DSGCR_CKEPDD_MASK		GENMASK(19, 16)
+#define DDRPHYC_DSGCR_CKEPDD_0			BIT(16)
+#define DDRPHYC_DSGCR_ODTPDD_MASK		GENMASK(23, 20)
+#define DDRPHYC_DSGCR_ODTPDD_0			BIT(20)
+#define DDRPHYC_DSGCR_NL2PD			BIT(24)
+
+#define DDRPHYC_ZQ0CRN_ZDATA_MASK		GENMASK(27, 0)
+#define DDRPHYC_ZQ0CRN_ZDATA_SHIFT		0
+#define DDRPHYC_ZQ0CRN_ZDEN			BIT(28)
+#define DDRPHYC_ZQ0CRN_ZQPD			BIT(31)
+
+#define DDRPHYC_DXNGCR_DXEN			BIT(0)
+
+#define DDRPHYC_DXNDLLCR_DLLSRST		BIT(30)
+#define DDRPHYC_DXNDLLCR_DLLDIS			BIT(31)
+#define DDRPHYC_DXNDLLCR_SDPHASE_MASK		GENMASK(17, 14)
+#define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT		14
+
+void ddr_enable_clock(void);
+
+#endif /* _RAM_STM32MP1_DDR_REGS_H */
diff --git a/include/drivers/st/stm32mp1_pmic.h b/include/drivers/st/stm32mp1_pmic.h
new file mode 100644
index 0000000..5d94b40
--- /dev/null
+++ b/include/drivers/st/stm32mp1_pmic.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_PMIC_H__
+#define __STM32MP1_PMIC_H__
+
+#include <stdbool.h>
+
+bool dt_check_pmic(void);
+int dt_pmic_enable_boot_on_regulators(void);
+void initialize_pmic_i2c(void);
+void initialize_pmic(void);
+int pmic_ddr_power_init(enum ddr_type ddr_type);
+
+#endif /* __STM32MP1_PMIC_H__ */
diff --git a/include/drivers/st/stm32mp1_pwr.h b/include/drivers/st/stm32mp1_pwr.h
new file mode 100644
index 0000000..e567042
--- /dev/null
+++ b/include/drivers/st/stm32mp1_pwr.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_PWR_H__
+#define __STM32MP1_PWR_H__
+
+#include <utils_def.h>
+
+#define PWR_CR1			U(0x00)
+#define PWR_CR2			U(0x08)
+#define PWR_CR3			U(0x0C)
+#define PWR_MPUCR		U(0x10)
+#define PWR_WKUPCR		U(0x20)
+#define PWR_MPUWKUPENR		U(0x28)
+
+#define PWR_CR1_LPDS		BIT(0)
+#define PWR_CR1_LPCFG		BIT(1)
+#define PWR_CR1_LVDS		BIT(2)
+#define PWR_CR1_DBP		BIT(8)
+
+#define PWR_CR3_DDRSREN		BIT(10)
+#define PWR_CR3_DDRSRDIS	BIT(11)
+#define PWR_CR3_DDRRETEN	BIT(12)
+
+#define PWR_MPUCR_PDDS		BIT(0)
+#define PWR_MPUCR_CSTDBYDIS	BIT(3)
+#define PWR_MPUCR_CSSF		BIT(9)
+
+#endif /* __STM32MP1_PWR_H__ */
diff --git a/include/drivers/st/stm32mp1_ram.h b/include/drivers/st/stm32mp1_ram.h
new file mode 100644
index 0000000..af96177
--- /dev/null
+++ b/include/drivers/st/stm32mp1_ram.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _STM32MP1_RAM_H
+#define _STM32MP1_RAM_H
+
+int stm32mp1_ddr_probe(void);
+
+#endif /* _STM32MP1_RAM_H */
diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h
new file mode 100644
index 0000000..e28ca97
--- /dev/null
+++ b/include/drivers/st/stm32mp1_rcc.h
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_RCC_H__
+#define __STM32MP1_RCC_H__
+
+#include <utils_def.h>
+
+#define RCC_TZCR			U(0x00)
+#define RCC_OCENSETR			U(0x0C)
+#define RCC_OCENCLRR			U(0x10)
+#define RCC_HSICFGR			U(0x18)
+#define RCC_CSICFGR			U(0x1C)
+#define RCC_MPCKSELR			U(0x20)
+#define RCC_ASSCKSELR			U(0x24)
+#define RCC_RCK12SELR			U(0x28)
+#define RCC_MPCKDIVR			U(0x2C)
+#define RCC_AXIDIVR			U(0x30)
+#define RCC_APB4DIVR			U(0x3C)
+#define RCC_APB5DIVR			U(0x40)
+#define RCC_RTCDIVR			U(0x44)
+#define RCC_MSSCKSELR			U(0x48)
+#define RCC_PLL1CR			U(0x80)
+#define RCC_PLL1CFGR1			U(0x84)
+#define RCC_PLL1CFGR2			U(0x88)
+#define RCC_PLL1FRACR			U(0x8C)
+#define RCC_PLL1CSGR			U(0x90)
+#define RCC_PLL2CR			U(0x94)
+#define RCC_PLL2CFGR1			U(0x98)
+#define RCC_PLL2CFGR2			U(0x9C)
+#define RCC_PLL2FRACR			U(0xA0)
+#define RCC_PLL2CSGR			U(0xA4)
+#define RCC_I2C46CKSELR			U(0xC0)
+#define RCC_SPI6CKSELR			U(0xC4)
+#define RCC_UART1CKSELR			U(0xC8)
+#define RCC_RNG1CKSELR			U(0xCC)
+#define RCC_CPERCKSELR			U(0xD0)
+#define RCC_STGENCKSELR			U(0xD4)
+#define RCC_DDRITFCR			U(0xD8)
+#define RCC_MP_BOOTCR			U(0x100)
+#define RCC_MP_SREQSETR			U(0x104)
+#define RCC_MP_SREQCLRR			U(0x108)
+#define RCC_MP_GCR			U(0x10C)
+#define RCC_MP_APRSTCR			U(0x110)
+#define RCC_MP_APRSTSR			U(0x114)
+#define RCC_BDCR			U(0x140)
+#define RCC_RDLSICR			U(0x144)
+#define RCC_APB4RSTSETR			U(0x180)
+#define RCC_APB4RSTCLRR			U(0x184)
+#define RCC_APB5RSTSETR			U(0x188)
+#define RCC_APB5RSTCLRR			U(0x18C)
+#define RCC_AHB5RSTSETR			U(0x190)
+#define RCC_AHB5RSTCLRR			U(0x194)
+#define RCC_AHB6RSTSETR			U(0x198)
+#define RCC_AHB6RSTCLRR			U(0x19C)
+#define RCC_TZAHB6RSTSETR		U(0x1A0)
+#define RCC_TZAHB6RSTCLRR		U(0x1A4)
+#define RCC_MP_APB4ENSETR		U(0x200)
+#define RCC_MP_APB4ENCLRR		U(0x204)
+#define RCC_MP_APB5ENSETR		U(0x208)
+#define RCC_MP_APB5ENCLRR		U(0x20C)
+#define RCC_MP_AHB5ENSETR		U(0x210)
+#define RCC_MP_AHB5ENCLRR		U(0x214)
+#define RCC_MP_AHB6ENSETR		U(0x218)
+#define RCC_MP_AHB6ENCLRR		U(0x21C)
+#define RCC_MP_TZAHB6ENSETR		U(0x220)
+#define RCC_MP_TZAHB6ENCLRR		U(0x224)
+#define RCC_MP_APB4LPENSETR		U(0x300)
+#define RCC_MP_APB4LPENCLRR		U(0x304)
+#define RCC_MP_APB5LPENSETR		U(0x308)
+#define RCC_MP_APB5LPENCLRR		U(0x30C)
+#define RCC_MP_AHB5LPENSETR		U(0x310)
+#define RCC_MP_AHB5LPENCLRR		U(0x314)
+#define RCC_MP_AHB6LPENSETR		U(0x318)
+#define RCC_MP_AHB6LPENCLRR		U(0x31C)
+#define RCC_MP_TZAHB6LPENSETR		U(0x320)
+#define RCC_MP_TZAHB6LPENCLRR		U(0x324)
+#define RCC_BR_RSTSCLRR			U(0x400)
+#define RCC_MP_GRSTCSETR		U(0x404)
+#define RCC_MP_RSTSCLRR			U(0x408)
+#define RCC_MP_IWDGFZSETR		U(0x40C)
+#define RCC_MP_IWDGFZCLRR		U(0x410)
+#define RCC_MP_CIER			U(0x414)
+#define RCC_MP_CIFR			U(0x418)
+#define RCC_PWRLPDLYCR			U(0x41C)
+#define RCC_MP_RSTSSETR			U(0x420)
+#define RCC_MCO1CFGR			U(0x800)
+#define RCC_MCO2CFGR			U(0x804)
+#define RCC_OCRDYR			U(0x808)
+#define RCC_DBGCFGR			U(0x80C)
+#define RCC_RCK3SELR			U(0x820)
+#define RCC_RCK4SELR			U(0x824)
+#define RCC_TIMG1PRER			U(0x828)
+#define RCC_TIMG2PRER			U(0x82C)
+#define RCC_APB1DIVR			U(0x834)
+#define RCC_APB2DIVR			U(0x838)
+#define RCC_APB3DIVR			U(0x83C)
+#define RCC_PLL3CR			U(0x880)
+#define RCC_PLL3CFGR1			U(0x884)
+#define RCC_PLL3CFGR2			U(0x888)
+#define RCC_PLL3FRACR			U(0x88C)
+#define RCC_PLL3CSGR			U(0x890)
+#define RCC_PLL4CR			U(0x894)
+#define RCC_PLL4CFGR1			U(0x898)
+#define RCC_PLL4CFGR2			U(0x89C)
+#define RCC_PLL4FRACR			U(0x8A0)
+#define RCC_PLL4CSGR			U(0x8A4)
+#define RCC_I2C12CKSELR			U(0x8C0)
+#define RCC_I2C35CKSELR			U(0x8C4)
+#define RCC_SAI1CKSELR			U(0x8C8)
+#define RCC_SAI2CKSELR			U(0x8CC)
+#define RCC_SAI3CKSELR			U(0x8D0)
+#define RCC_SAI4CKSELR			U(0x8D4)
+#define RCC_SPI2S1CKSELR		U(0x8D8)
+#define RCC_SPI2S23CKSELR		U(0x8DC)
+#define RCC_SPI45CKSELR			U(0x8E0)
+#define RCC_UART6CKSELR			U(0x8E4)
+#define RCC_UART24CKSELR		U(0x8E8)
+#define RCC_UART35CKSELR		U(0x8EC)
+#define RCC_UART78CKSELR		U(0x8F0)
+#define RCC_SDMMC12CKSELR		U(0x8F4)
+#define RCC_SDMMC3CKSELR		U(0x8F8)
+#define RCC_ETHCKSELR			U(0x8FC)
+#define RCC_QSPICKSELR			U(0x900)
+#define RCC_FMCCKSELR			U(0x904)
+#define RCC_FDCANCKSELR			U(0x90C)
+#define RCC_SPDIFCKSELR			U(0x914)
+#define RCC_CECCKSELR			U(0x918)
+#define RCC_USBCKSELR			U(0x91C)
+#define RCC_RNG2CKSELR			U(0x920)
+#define RCC_DSICKSELR			U(0x924)
+#define RCC_ADCCKSELR			U(0x928)
+#define RCC_LPTIM45CKSELR		U(0x92C)
+#define RCC_LPTIM23CKSELR		U(0x930)
+#define RCC_LPTIM1CKSELR		U(0x934)
+#define RCC_APB1RSTSETR			U(0x980)
+#define RCC_APB1RSTCLRR			U(0x984)
+#define RCC_APB2RSTSETR			U(0x988)
+#define RCC_APB2RSTCLRR			U(0x98C)
+#define RCC_APB3RSTSETR			U(0x990)
+#define RCC_APB3RSTCLRR			U(0x994)
+#define RCC_AHB2RSTSETR			U(0x998)
+#define RCC_AHB2RSTCLRR			U(0x99C)
+#define RCC_AHB3RSTSETR			U(0x9A0)
+#define RCC_AHB3RSTCLRR			U(0x9A4)
+#define RCC_AHB4RSTSETR			U(0x9A8)
+#define RCC_AHB4RSTCLRR			U(0x9AC)
+#define RCC_MP_APB1ENSETR		U(0xA00)
+#define RCC_MP_APB1ENCLRR		U(0xA04)
+#define RCC_MP_APB2ENSETR		U(0xA08)
+#define RCC_MP_APB2ENCLRR		U(0xA0C)
+#define RCC_MP_APB3ENSETR		U(0xA10)
+#define RCC_MP_APB3ENCLRR		U(0xA14)
+#define RCC_MP_AHB2ENSETR		U(0xA18)
+#define RCC_MP_AHB2ENCLRR		U(0xA1C)
+#define RCC_MP_AHB3ENSETR		U(0xA20)
+#define RCC_MP_AHB3ENCLRR		U(0xA24)
+#define RCC_MP_AHB4ENSETR		U(0xA28)
+#define RCC_MP_AHB4ENCLRR		U(0xA2C)
+#define RCC_MP_MLAHBENSETR		U(0xA38)
+#define RCC_MP_MLAHBENCLRR		U(0xA3C)
+#define RCC_MP_APB1LPENSETR		U(0xB00)
+#define RCC_MP_APB1LPENCLRR		U(0xB04)
+#define RCC_MP_APB2LPENSETR		U(0xB08)
+#define RCC_MP_APB2LPENCLRR		U(0xB0C)
+#define RCC_MP_APB3LPENSETR		U(0xB10)
+#define RCC_MP_APB3LPENCLRR		U(0xB14)
+#define RCC_MP_AHB2LPENSETR		U(0xB18)
+#define RCC_MP_AHB2LPENCLRR		U(0xB1C)
+#define RCC_MP_AHB3LPENSETR		U(0xB20)
+#define RCC_MP_AHB3LPENCLRR		U(0xB24)
+#define RCC_MP_AHB4LPENSETR		U(0xB28)
+#define RCC_MP_AHB4LPENCLRR		U(0xB2C)
+#define RCC_MP_AXIMLPENSETR		U(0xB30)
+#define RCC_MP_AXIMLPENCLRR		U(0xB34)
+#define RCC_MP_MLAHBLPENSETR		U(0xB38)
+#define RCC_MP_MLAHBLPENCLRR		U(0xB3C)
+#define RCC_VERR			U(0xFF4)
+#define RCC_IDR				U(0xFF8)
+#define RCC_SIDR			U(0xFFC)
+
+/* Values for RCC_TZCR register */
+#define RCC_TZCR_TZEN			BIT(0)
+
+/* Used for most of RCC_<x>SELR registers */
+#define RCC_SELR_SRC_MASK		GENMASK(2, 0)
+#define RCC_SELR_REFCLK_SRC_MASK	GENMASK(1, 0)
+#define RCC_SELR_SRCRDY			BIT(31)
+
+/* Values of RCC_MPCKSELR register */
+#define RCC_MPCKSELR_HSI		0x00000000
+#define RCC_MPCKSELR_HSE		0x00000001
+#define RCC_MPCKSELR_PLL		0x00000002
+#define RCC_MPCKSELR_PLL_MPUDIV		0x00000003
+
+/* Values of RCC_ASSCKSELR register */
+#define RCC_ASSCKSELR_HSI		0x00000000
+#define RCC_ASSCKSELR_HSE		0x00000001
+#define RCC_ASSCKSELR_PLL		0x00000002
+
+/* Values of RCC_MSSCKSELR register */
+#define RCC_MSSCKSELR_HSI		0x00000000
+#define RCC_MSSCKSELR_HSE		0x00000001
+#define RCC_MSSCKSELR_CSI		0x00000002
+#define RCC_MSSCKSELR_PLL		0x00000003
+
+/* Values of RCC_CPERCKSELR register */
+#define RCC_CPERCKSELR_HSI		0x00000000
+#define RCC_CPERCKSELR_CSI		0x00000001
+#define RCC_CPERCKSELR_HSE		0x00000002
+
+/* Used for most of DIVR register: max div for RTC */
+#define RCC_DIVR_DIV_MASK		GENMASK(5, 0)
+#define RCC_DIVR_DIVRDY			BIT(31)
+
+/* Masks for specific DIVR registers */
+#define RCC_APBXDIV_MASK		GENMASK(2, 0)
+#define RCC_MPUDIV_MASK			GENMASK(2, 0)
+#define RCC_AXIDIV_MASK			GENMASK(2, 0)
+
+/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */
+#define RCC_MP_ENCLRR_OFFSET		U(4)
+
+/* Fields of RCC_BDCR register */
+#define RCC_BDCR_LSEON			BIT(0)
+#define RCC_BDCR_LSEBYP			BIT(1)
+#define RCC_BDCR_LSERDY			BIT(2)
+#define RCC_BDCR_LSEDRV_MASK		GENMASK(5, 4)
+#define RCC_BDCR_LSEDRV_SHIFT		4
+#define RCC_BDCR_LSECSSON		BIT(8)
+#define RCC_BDCR_RTCCKEN		BIT(20)
+#define RCC_BDCR_RTCSRC_MASK		GENMASK(17, 16)
+#define RCC_BDCR_RTCSRC_SHIFT		16
+#define RCC_BDCR_VSWRST			BIT(31)
+
+/* Fields of RCC_RDLSICR register */
+#define RCC_RDLSICR_LSION		BIT(0)
+#define RCC_RDLSICR_LSIRDY		BIT(1)
+
+/* Used for all RCC_PLL<n>CR registers */
+#define RCC_PLLNCR_PLLON		BIT(0)
+#define RCC_PLLNCR_PLLRDY		BIT(1)
+#define RCC_PLLNCR_DIVPEN		BIT(4)
+#define RCC_PLLNCR_DIVQEN		BIT(5)
+#define RCC_PLLNCR_DIVREN		BIT(6)
+#define RCC_PLLNCR_DIVEN_SHIFT		4
+
+/* Used for all RCC_PLL<n>CFGR1 registers */
+#define RCC_PLLNCFGR1_DIVM_SHIFT	16
+#define RCC_PLLNCFGR1_DIVM_MASK		GENMASK(21, 16)
+#define RCC_PLLNCFGR1_DIVN_SHIFT	0
+#define RCC_PLLNCFGR1_DIVN_MASK		GENMASK(8, 0)
+/* Only for PLL3 and PLL4 */
+#define RCC_PLLNCFGR1_IFRGE_SHIFT	24
+#define RCC_PLLNCFGR1_IFRGE_MASK	GENMASK(25, 24)
+
+/* Used for all RCC_PLL<n>CFGR2 registers */
+#define RCC_PLLNCFGR2_DIVX_MASK		GENMASK(6, 0)
+#define RCC_PLLNCFGR2_DIVP_SHIFT	0
+#define RCC_PLLNCFGR2_DIVP_MASK		GENMASK(6, 0)
+#define RCC_PLLNCFGR2_DIVQ_SHIFT	8
+#define RCC_PLLNCFGR2_DIVQ_MASK		GENMASK(14, 8)
+#define RCC_PLLNCFGR2_DIVR_SHIFT	16
+#define RCC_PLLNCFGR2_DIVR_MASK		GENMASK(22, 16)
+
+/* Used for all RCC_PLL<n>FRACR registers */
+#define RCC_PLLNFRACR_FRACV_SHIFT	3
+#define RCC_PLLNFRACR_FRACV_MASK	GENMASK(15, 3)
+#define RCC_PLLNFRACR_FRACLE		BIT(16)
+
+/* Used for all RCC_PLL<n>CSGR registers */
+#define RCC_PLLNCSGR_INC_STEP_SHIFT	16
+#define RCC_PLLNCSGR_INC_STEP_MASK	GENMASK(30, 16)
+#define RCC_PLLNCSGR_MOD_PER_SHIFT	0
+#define RCC_PLLNCSGR_MOD_PER_MASK	GENMASK(12, 0)
+#define RCC_PLLNCSGR_SSCG_MODE_SHIFT	15
+#define RCC_PLLNCSGR_SSCG_MODE_MASK	BIT(15)
+
+/* Used for RCC_OCENSETR and RCC_OCENCLRR registers */
+#define RCC_OCENR_HSION			BIT(0)
+#define RCC_OCENR_CSION			BIT(4)
+#define RCC_OCENR_HSEON			BIT(8)
+#define RCC_OCENR_HSEBYP		BIT(10)
+#define RCC_OCENR_HSECSSON		BIT(11)
+
+/* Fields of RCC_OCRDYR register */
+#define RCC_OCRDYR_HSIRDY		BIT(0)
+#define RCC_OCRDYR_HSIDIVRDY		BIT(2)
+#define RCC_OCRDYR_CSIRDY		BIT(4)
+#define RCC_OCRDYR_HSERDY		BIT(8)
+
+/* Fields of RCC_DDRITFCR register */
+#define RCC_DDRITFCR_DDRC1EN		BIT(0)
+#define RCC_DDRITFCR_DDRC1LPEN		BIT(1)
+#define RCC_DDRITFCR_DDRC2EN		BIT(2)
+#define RCC_DDRITFCR_DDRC2LPEN		BIT(3)
+#define RCC_DDRITFCR_DDRPHYCEN		BIT(4)
+#define RCC_DDRITFCR_DDRPHYCLPEN	BIT(5)
+#define RCC_DDRITFCR_DDRCAPBEN		BIT(6)
+#define RCC_DDRITFCR_DDRCAPBLPEN	BIT(7)
+#define RCC_DDRITFCR_AXIDCGEN		BIT(8)
+#define RCC_DDRITFCR_DDRPHYCAPBEN	BIT(9)
+#define RCC_DDRITFCR_DDRPHYCAPBLPEN	BIT(10)
+#define RCC_DDRITFCR_DDRCAPBRST		BIT(14)
+#define RCC_DDRITFCR_DDRCAXIRST		BIT(15)
+#define RCC_DDRITFCR_DDRCORERST		BIT(16)
+#define RCC_DDRITFCR_DPHYAPBRST		BIT(17)
+#define RCC_DDRITFCR_DPHYRST		BIT(18)
+#define RCC_DDRITFCR_DPHYCTLRST		BIT(19)
+#define RCC_DDRITFCR_DDRCKMOD_MASK	GENMASK(22, 20)
+#define RCC_DDRITFCR_DDRCKMOD_SHIFT	20
+#define RCC_DDRITFCR_DDRCKMOD_SSR	0
+#define RCC_DDRITFCR_DDRCKMOD_ASR1	BIT(20)
+#define RCC_DDRITFCR_DDRCKMOD_HSR1	BIT(21)
+#define RCC_DDRITFCR_GSKPCTRL		BIT(24)
+
+/* Fields of RCC_HSICFGR register */
+#define RCC_HSICFGR_HSIDIV_MASK		GENMASK(1, 0)
+
+/* Used for RCC_MCO related operations */
+#define RCC_MCOCFG_MCOON		BIT(12)
+#define RCC_MCOCFG_MCODIV_MASK		GENMASK(7, 4)
+#define RCC_MCOCFG_MCODIV_SHIFT		4
+#define RCC_MCOCFG_MCOSRC_MASK		GENMASK(2, 0)
+
+/* Fields of RCC_DBGCFGR register */
+#define RCC_DBGCFGR_DBGCKEN		BIT(8)
+
+/* RCC register fields for reset reasons */
+#define  RCC_MP_RSTSCLRR_PORRSTF	BIT(0)
+#define  RCC_MP_RSTSCLRR_BORRSTF	BIT(1)
+#define  RCC_MP_RSTSCLRR_PADRSTF	BIT(2)
+#define  RCC_MP_RSTSCLRR_HCSSRSTF	BIT(3)
+#define  RCC_MP_RSTSCLRR_VCORERSTF	BIT(4)
+#define  RCC_MP_RSTSCLRR_MPSYSRSTF	BIT(6)
+#define  RCC_MP_RSTSCLRR_IWDG1RSTF	BIT(8)
+#define  RCC_MP_RSTSCLRR_IWDG2RSTF	BIT(9)
+#define  RCC_MP_RSTSCLRR_STDBYRSTF	BIT(11)
+#define  RCC_MP_RSTSCLRR_CSTDBYRSTF	BIT(12)
+
+/* Global Reset Register */
+#define RCC_MP_GRSTCSETR_MPSYSRST	BIT(0)
+
+/* Clock Source Interrupt Flag Register */
+#define RCC_MP_CIFR_MASK		U(0x110F1F)
+#define RCC_MP_CIFR_WKUPF		BIT(20)
+
+/* Stop Request Set Register */
+#define RCC_MP_SREQSETR_STPREQ_P0	BIT(0)
+#define RCC_MP_SREQSETR_STPREQ_P1	BIT(1)
+
+/* Stop Request Clear Register */
+#define RCC_MP_SREQCLRR_STPREQ_P0	BIT(0)
+#define RCC_MP_SREQCLRR_STPREQ_P1	BIT(1)
+
+/* Values of RCC_UART24CKSELR register */
+#define RCC_UART24CKSELR_HSI		0x00000002
+
+/* Values of RCC_MP_APB1ENSETR register */
+#define RCC_MP_APB1ENSETR_UART4EN	BIT(16)
+
+/* Values of RCC_MP_AHB4ENSETR register */
+#define RCC_MP_AHB4ENSETR_GPIOGEN	BIT(6)
+
+#endif /* __STM32MP1_RCC_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/drivers/st/stpmu1.h b/include/drivers/st/stpmu1.h
new file mode 100644
index 0000000..1b93ab2
--- /dev/null
+++ b/include/drivers/st/stpmu1.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#ifndef __STPMU1_H__
+#define __STPMU1_H__
+
+#include <stm32_i2c.h>
+#include <utils_def.h>
+
+#define TURN_ON_REG			0x1U
+#define TURN_OFF_REG			0x2U
+#define ICC_LDO_TURN_OFF_REG		0x3U
+#define ICC_BUCK_TURN_OFF_REG		0x4U
+#define RESET_STATUS_REG		0x5U
+#define VERSION_STATUS_REG		0x6U
+#define MAIN_CONTROL_REG		0x10U
+#define PADS_PULL_REG			0x11U
+#define BUCK_PULL_DOWN_REG		0x12U
+#define LDO14_PULL_DOWN_REG		0x13U
+#define LDO56_PULL_DOWN_REG		0x14U
+#define VIN_CONTROL_REG			0x15U
+#define PONKEY_TIMER_REG		0x16U
+#define MASK_RANK_BUCK_REG		0x17U
+#define MASK_RESET_BUCK_REG		0x18U
+#define MASK_RANK_LDO_REG		0x19U
+#define MASK_RESET_LDO_REG		0x1AU
+#define WATCHDOG_CONTROL_REG		0x1BU
+#define WATCHDOG_TIMER_REG		0x1CU
+#define BUCK_ICC_TURNOFF_REG		0x1DU
+#define LDO_ICC_TURNOFF_REG		0x1EU
+#define BUCK_APM_CONTROL_REG		0x1FU
+#define BUCK1_CONTROL_REG		0x20U
+#define BUCK2_CONTROL_REG		0x21U
+#define BUCK3_CONTROL_REG		0x22U
+#define BUCK4_CONTROL_REG		0x23U
+#define VREF_DDR_CONTROL_REG		0x24U
+#define LDO1_CONTROL_REG		0x25U
+#define LDO2_CONTROL_REG		0x26U
+#define LDO3_CONTROL_REG		0x27U
+#define LDO4_CONTROL_REG		0x28U
+#define LDO5_CONTROL_REG		0x29U
+#define LDO6_CONTROL_REG		0x2AU
+#define BUCK1_PWRCTRL_REG		0x30U
+#define BUCK2_PWRCTRL_REG		0x31U
+#define BUCK3_PWRCTRL_REG		0x32U
+#define BUCK4_PWRCTRL_REG		0x33U
+#define VREF_DDR_PWRCTRL_REG		0x34U
+#define LDO1_PWRCTRL_REG		0x35U
+#define LDO2_PWRCTRL_REG		0x36U
+#define LDO3_PWRCTRL_REG		0x37U
+#define LDO4_PWRCTRL_REG		0x38U
+#define LDO5_PWRCTRL_REG		0x39U
+#define LDO6_PWRCTRL_REG		0x3AU
+#define FREQUENCY_SPREADING_REG		0x3BU
+#define USB_CONTROL_REG			0x40U
+#define ITLATCH1_REG			0x50U
+#define ITLATCH2_REG			0x51U
+#define ITLATCH3_REG			0x52U
+#define ITLATCH4_REG			0x53U
+#define ITSETLATCH1_REG			0x60U
+#define ITSETLATCH2_REG			0x61U
+#define ITSETLATCH3_REG			0x62U
+#define ITSETLATCH4_REG			0x63U
+#define ITCLEARLATCH1_REG		0x70U
+#define ITCLEARLATCH2_REG		0x71U
+#define ITCLEARLATCH3_REG		0x72U
+#define ITCLEARLATCH4_REG		0x73U
+#define ITMASK1_REG			0x80U
+#define ITMASK2_REG			0x81U
+#define ITMASK3_REG			0x82U
+#define ITMASK4_REG			0x83U
+#define ITSETMASK1_REG			0x90U
+#define ITSETMASK2_REG			0x91U
+#define ITSETMASK3_REG			0x92U
+#define ITSETMASK4_REG			0x93U
+#define ITCLEARMASK1_REG		0xA0U
+#define ITCLEARMASK2_REG		0xA1U
+#define ITCLEARMASK3_REG		0xA2U
+#define ITCLEARMASK4_REG		0xA3U
+#define ITSOURCE1_REG			0xB0U
+#define ITSOURCE2_REG			0xB1U
+#define ITSOURCE3_REG			0xB2U
+#define ITSOURCE4_REG			0xB3U
+#define LDO_VOLTAGE_MASK		0x7CU
+#define BUCK_VOLTAGE_MASK		0xFCU
+#define LDO_BUCK_VOLTAGE_SHIFT		2
+#define LDO_ENABLE_MASK			0x01U
+#define BUCK_ENABLE_MASK		0x01U
+#define BUCK_HPLP_ENABLE_MASK		0x02U
+#define LDO_HPLP_ENABLE_MASK		0x02U
+#define LDO_BUCK_HPLP_SHIFT		1
+#define LDO_BUCK_RANK_MASK		0x01U
+#define LDO_BUCK_RESET_MASK		0x01U
+#define LDO_BUCK_PULL_DOWN_MASK		0x03U
+
+/* Main PMIC Control Register (MAIN_CONTROL_REG) */
+#define ICC_EVENT_ENABLED		BIT(4)
+#define PWRCTRL_POLARITY_HIGH		BIT(3)
+#define PWRCTRL_PIN_VALID		BIT(2)
+#define RESTART_REQUEST_ENABLED		BIT(1)
+#define SOFTWARE_SWITCH_OFF_ENABLED	BIT(0)
+
+/* Main PMIC PADS Control Register (PADS_PULL_REG) */
+#define WAKEUP_DETECTOR_DISABLED	BIT(4)
+#define PWRCTRL_PD_ACTIVE		BIT(3)
+#define PWRCTRL_PU_ACTIVE		BIT(2)
+#define WAKEUP_PD_ACTIVE		BIT(1)
+#define PONKEY_PU_ACTIVE		BIT(0)
+
+/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */
+#define SWIN_DETECTOR_ENABLED		BIT(7)
+#define SWOUT_DETECTOR_ENABLED          BIT(6)
+#define VINLOW_HYST_MASK		0x3
+#define VINLOW_HYST_SHIFT		4
+#define VINLOW_THRESHOLD_MASK		0x7
+#define VINLOW_THRESHOLD_SHIFT		1
+#define VINLOW_ENABLED			0x01
+#define VINLOW_CTRL_REG_MASK		0xFF
+
+/* USB Control Register */
+#define BOOST_OVP_DISABLED		BIT(7)
+#define VBUS_OTG_DETECTION_DISABLED	BIT(6)
+#define OCP_LIMIT_HIGH			BIT(3)
+#define SWIN_SWOUT_ENABLED		BIT(2)
+#define USBSW_OTG_SWITCH_ENABLED	BIT(1)
+
+int stpmu1_switch_off(void);
+int stpmu1_register_read(uint8_t register_id, uint8_t *value);
+int stpmu1_register_write(uint8_t register_id, uint8_t value);
+int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask);
+int stpmu1_regulator_enable(const char *name);
+int stpmu1_regulator_disable(const char *name);
+uint8_t stpmu1_is_regulator_enabled(const char *name);
+int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts);
+void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr);
+
+#endif /* __STPMU1_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/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h
new file mode 100644
index 0000000..e2f1f1b
--- /dev/null
+++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Torgue Alexandre <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+
+#ifndef _DT_BINDINGS_STM32_PINFUNC_H
+#define _DT_BINDINGS_STM32_PINFUNC_H
+
+/*  define PIN modes */
+#define GPIO	0x0
+#define AF0	0x1
+#define AF1	0x2
+#define AF2	0x3
+#define AF3	0x4
+#define AF4	0x5
+#define AF5	0x6
+#define AF6	0x7
+#define AF7	0x8
+#define AF8	0x9
+#define AF9	0xa
+#define AF10	0xb
+#define AF11	0xc
+#define AF12	0xd
+#define AF13	0xe
+#define AF14	0xf
+#define AF15	0x10
+#define ANALOG	0x11
+
+/* define Pins number*/
+#define PIN_NO(port, line)	(((port) - 'A') * 0x10 + (line))
+
+#define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode))
+
+#endif /* _DT_BINDINGS_STM32_PINFUNC_H */
diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h
new file mode 100644
index 0000000..f0c3aae
--- /dev/null
+++ b/include/dt-bindings/reset/stm32mp1-resets.h
@@ -0,0 +1,108 @@
+/* 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_RESET_H_
+#define _DT_BINDINGS_STM32MP1_RESET_H_
+
+#define LTDC_R		3072
+#define DSI_R		3076
+#define DDRPERFM_R	3080
+#define USBPHY_R	3088
+#define SPI6_R		3136
+#define I2C4_R		3138
+#define I2C6_R		3139
+#define USART1_R	3140
+#define STGEN_R		3156
+#define GPIOZ_R		3200
+#define CRYP1_R		3204
+#define HASH1_R		3205
+#define RNG1_R		3206
+#define AXIM_R		3216
+#define GPU_R		3269
+#define ETHMAC_R	3274
+#define FMC_R		3276
+#define QSPI_R		3278
+#define SDMMC1_R	3280
+#define SDMMC2_R	3281
+#define CRC1_R		3284
+#define USBH_R		3288
+#define MDMA_R		3328
+#define MCU_R		8225
+#define TIM2_R		19456
+#define TIM3_R		19457
+#define TIM4_R		19458
+#define TIM5_R		19459
+#define TIM6_R		19460
+#define TIM7_R		19461
+#define TIM12_R		16462
+#define TIM13_R		16463
+#define TIM14_R		16464
+#define LPTIM1_R	19465
+#define SPI2_R		19467
+#define SPI3_R		19468
+#define USART2_R	19470
+#define USART3_R	19471
+#define UART4_R		19472
+#define UART5_R		19473
+#define UART7_R		19474
+#define UART8_R		19475
+#define I2C1_R		19477
+#define I2C2_R		19478
+#define I2C3_R		19479
+#define I2C5_R		19480
+#define SPDIF_R		19482
+#define CEC_R		19483
+#define DAC12_R		19485
+#define MDIO_R		19847
+#define TIM1_R		19520
+#define TIM8_R		19521
+#define TIM15_R		19522
+#define TIM16_R		19523
+#define TIM17_R		19524
+#define SPI1_R		19528
+#define SPI4_R		19529
+#define SPI5_R		19530
+#define USART6_R	19533
+#define SAI1_R		19536
+#define SAI2_R		19537
+#define SAI3_R		19538
+#define DFSDM_R		19540
+#define FDCAN_R		19544
+#define LPTIM2_R	19584
+#define LPTIM3_R	19585
+#define LPTIM4_R	19586
+#define LPTIM5_R	19587
+#define SAI4_R		19592
+#define SYSCFG_R	19595
+#define VREF_R		19597
+#define TMPSENS_R	19600
+#define PMBCTRL_R	19601
+#define DMA1_R		19648
+#define DMA2_R		19649
+#define DMAMUX_R	19650
+#define ADC12_R		19653
+#define USBO_R		19656
+#define SDMMC3_R	19664
+#define CAMITF_R	19712
+#define CRYP2_R		19716
+#define HASH2_R		19717
+#define RNG2_R		19718
+#define CRC2_R		19719
+#define HSEM_R		19723
+#define MBOX_R		19724
+#define GPIOA_R		19776
+#define GPIOB_R		19777
+#define GPIOC_R		19778
+#define GPIOD_R		19779
+#define GPIOE_R		19780
+#define GPIOF_R		19781
+#define GPIOG_R		19782
+#define GPIOH_R		19783
+#define GPIOI_R		19784
+#define GPIOJ_R		19785
+#define GPIOK_R		19786
+
+#endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */
diff --git a/maintainers.rst b/maintainers.rst
index 76fede8..28127f8 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -125,6 +125,16 @@
 :G: `rockchip-linux`_
 :F: plat/rockchip/
 
+STM32MP1 platform port
+----------------------
+:M: Yann Gautier <yann.gautier@st.com>
+:G: `Yann-lms`_
+:F: docs/plat/stm32mp1.rst
+:F: fdts/stm32\*
+:F: include/dt-bindings/\*/stm32\*
+:F: plat/st/
+:F: tools/stm32image/
+
 Synquacer platform port
 -----------------------
 :M: Sumit Garg <sumit.garg@linaro.org>
@@ -184,3 +194,4 @@
 .. _soby-mathew: https://github.com/soby-mathew
 .. _TonyXie06: https://github.com/TonyXie06
 .. _vwadekar: https://github.com/vwadekar
+.. _Yann-lms: https://github.com/Yann-lms
diff --git a/plat/st/stm32mp1/bl2_io_storage.c b/plat/st/stm32mp1/bl2_io_storage.c
new file mode 100644
index 0000000..7346c0c
--- /dev/null
+++ b/plat/st/stm32mp1/bl2_io_storage.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <io_driver.h>
+#include <io_dummy.h>
+#include <io_storage.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_rcc.h>
+#include <string.h>
+#include <utils.h>
+
+/* IO devices */
+static const io_dev_connector_t *dummy_dev_con;
+static uintptr_t dummy_dev_handle;
+static uintptr_t dummy_dev_spec;
+
+static const io_block_spec_t bl32_block_spec = {
+	.offset = BL32_BASE,
+	.length = STM32MP1_BL32_SIZE
+};
+
+static const io_block_spec_t bl2_block_spec = {
+	.offset = BL2_BASE,
+	.length = STM32MP1_BL2_SIZE,
+};
+
+static int open_dummy(const uintptr_t spec);
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+	[BL2_IMAGE_ID] = {
+		.dev_handle = &dummy_dev_handle,
+		.image_spec = (uintptr_t)&bl2_block_spec,
+		.check = open_dummy
+	},
+	[BL32_IMAGE_ID] = {
+		.dev_handle = &dummy_dev_handle,
+		.image_spec = (uintptr_t)&bl32_block_spec,
+		.check = open_dummy
+	},
+};
+
+static int open_dummy(const uintptr_t spec)
+{
+	return io_dev_init(dummy_dev_handle, 0);
+}
+
+static void print_boot_device(boot_api_context_t *boot_context)
+{
+	switch (boot_context->boot_interface_selected) {
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+		INFO("Using SDMMC\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		INFO("Using EMMC\n");
+		break;
+	default:
+		ERROR("Boot interface not found\n");
+		panic();
+		break;
+	}
+
+	if (boot_context->boot_interface_instance != 0U) {
+		INFO("  Instance %d\n", boot_context->boot_interface_instance);
+	}
+}
+
+static void print_reset_reason(void)
+{
+	uint32_t rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR);
+
+	if (rstsr == 0U) {
+		WARN("Reset reason unknown\n");
+		return;
+	}
+
+	INFO("Reset reason (0x%x):\n", rstsr);
+
+	if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) {
+		if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) {
+			INFO("System exits from STANDBY\n");
+			return;
+		}
+
+		if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) {
+			INFO("MPU exits from CSTANDBY\n");
+			return;
+		}
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) {
+		INFO("  Power-on Reset (rst_por)\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) {
+		INFO("  Brownout Reset (rst_bor)\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) {
+		INFO("  System reset generated by MPU (MPSYSRST)\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) {
+		INFO("  Reset due to a clock failure on HSE\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) {
+		INFO("  IWDG1 Reset (rst_iwdg1)\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) {
+		INFO("  IWDG2 Reset (rst_iwdg2)\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
+		INFO("  Pad Reset from NRST\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) {
+		INFO("  Reset due to a failure of VDD_CORE\n");
+		return;
+	}
+
+	ERROR("  Unidentified reset reason\n");
+}
+
+void stm32mp1_io_setup(void)
+{
+	int io_result __unused;
+	boot_api_context_t *boot_context =
+		(boot_api_context_t *)stm32mp1_get_boot_ctx_address();
+
+	print_reset_reason();
+
+	print_boot_device(boot_context);
+
+	if ((boot_context->boot_partition_used_toboot == 1U) ||
+	    (boot_context->boot_partition_used_toboot == 2U)) {
+		INFO("Boot used partition fsbl%d\n",
+		     boot_context->boot_partition_used_toboot);
+	}
+
+	io_result = register_io_dev_dummy(&dummy_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
+				&dummy_dev_handle);
+	assert(io_result == 0);
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy.
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int rc;
+	const struct plat_io_policy *policy;
+
+	assert(image_id < ARRAY_SIZE(policies));
+
+	policy = &policies[image_id];
+	rc = policy->check(policy->image_spec);
+	if (rc == 0) {
+		*image_spec = policy->image_spec;
+		*dev_handle = *(policy->dev_handle);
+	}
+
+	return rc;
+}
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
new file mode 100644
index 0000000..9f2d8bd
--- /dev/null
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <boot_api.h>
+#include <console.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <desc_image_load.h>
+#include <generic_delay_timer.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_dt.h>
+#include <stm32mp1_pmic.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_context.h>
+#include <stm32mp1_pwr.h>
+#include <stm32mp1_ram.h>
+#include <stm32mp1_rcc.h>
+#include <stm32mp1_reset.h>
+#include <string.h>
+#include <xlat_tables_v2.h>
+
+void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
+				  u_register_t arg2, u_register_t arg3)
+{
+	stm32mp1_save_boot_ctx_address(arg0);
+}
+
+void bl2_platform_setup(void)
+{
+	int ret;
+
+	if (dt_check_pmic()) {
+		initialize_pmic();
+	}
+
+	ret = stm32mp1_ddr_probe();
+	if (ret < 0) {
+		ERROR("Invalid DDR init: error %d\n", ret);
+		panic();
+	}
+
+	INFO("BL2 runs SP_MIN setup\n");
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+	int32_t result;
+	struct dt_node_info dt_dev_info;
+	const char *board_model;
+	boot_api_context_t *boot_context =
+		(boot_api_context_t *)stm32mp1_get_boot_ctx_address();
+	uint32_t clk_rate;
+
+	/*
+	 * Disable the backup domain write protection.
+	 * The protection is enable at each reset by hardware
+	 * and must be disabled by software.
+	 */
+	mmio_setbits_32(PWR_BASE + PWR_CR1, PWR_CR1_DBP);
+
+	while ((mmio_read_32(PWR_BASE + PWR_CR1) & PWR_CR1_DBP) == 0U) {
+		;
+	}
+
+	/* Reset backup domain on cold boot cases */
+	if ((mmio_read_32(RCC_BASE + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) {
+		mmio_setbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST);
+
+		while ((mmio_read_32(RCC_BASE + RCC_BDCR) & RCC_BDCR_VSWRST) ==
+		       0U) {
+			;
+		}
+
+		mmio_clrbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST);
+	}
+
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+			BL_CODE_END - BL_CODE_BASE,
+			MT_CODE | MT_SECURE);
+
+	/* Prevent corruption of preloaded BL32 */
+	mmap_add_region(BL32_BASE, BL32_BASE,
+			BL32_LIMIT - BL32_BASE,
+			MT_MEMORY | MT_RO | MT_SECURE);
+
+	/* Prevent corruption of preloaded Device Tree */
+	mmap_add_region(DTB_BASE, DTB_BASE,
+			DTB_LIMIT - DTB_BASE,
+			MT_MEMORY | MT_RO | MT_SECURE);
+
+	configure_mmu();
+
+	generic_delay_timer_init();
+
+	if (dt_open_and_check() < 0) {
+		panic();
+	}
+
+	if (stm32mp1_clk_probe() < 0) {
+		panic();
+	}
+
+	if (stm32mp1_clk_init() < 0) {
+		panic();
+	}
+
+	result = dt_get_stdout_uart_info(&dt_dev_info);
+
+	if ((result <= 0) ||
+	    (dt_dev_info.status == 0U) ||
+	    (dt_dev_info.clock < 0) ||
+	    (dt_dev_info.reset < 0)) {
+		goto skip_console_init;
+	}
+
+	if (dt_set_stdout_pinctrl() != 0) {
+		goto skip_console_init;
+	}
+
+	if (stm32mp1_clk_enable((unsigned long)dt_dev_info.clock) != 0) {
+		goto skip_console_init;
+	}
+
+	stm32mp1_reset_assert((uint32_t)dt_dev_info.reset);
+	udelay(2);
+	stm32mp1_reset_deassert((uint32_t)dt_dev_info.reset);
+	mdelay(1);
+
+	clk_rate = stm32mp1_clk_get_rate((unsigned long)dt_dev_info.clock);
+
+	if (console_init(dt_dev_info.base, clk_rate,
+			 STM32MP1_UART_BAUDRATE) == 0) {
+		panic();
+	}
+
+	board_model = dt_get_board_model();
+	if (board_model != NULL) {
+		NOTICE("%s\n", board_model);
+	}
+
+skip_console_init:
+
+	if (stm32_save_boot_interface(boot_context->boot_interface_selected,
+				      boot_context->boot_interface_instance) !=
+	    0) {
+		ERROR("Cannot save boot interface\n");
+	}
+
+	stm32mp1_arch_security_setup();
+
+	stm32mp1_io_setup();
+}
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
new file mode 100644
index 0000000..71c3593
--- /dev/null
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __BOOT_API_H
+#define __BOOT_API_H
+
+#include <stdint.h>
+
+/*
+ * Possible value of boot context field 'boot_interface_sel'
+ */
+
+/* Value of field 'boot_interface_sel' when no boot occurred */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_NO			0x0U
+
+/* Boot occurred on SD */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD		0x1U
+
+/* Boot occurred on EMMC */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC		0x2U
+
+/**
+ * @brief  Possible value of boot context field 'EmmcXferStatus'
+ */
+/*
+ * Possible value of boot context field 'emmc_xfer_status'
+ */
+#define BOOT_API_CTX_EMMC_XFER_STATUS_NOT_STARTED			0x0U
+#define BOOT_API_CTX_EMMC_XFER_STATUS_DATAEND_DETECTED			0x1U
+#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_OVERALL_TIMEOUT_DETECTED	0x2U
+#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_DATA_TIMEOUT			0x3U
+
+/*
+ * Possible value of boot context field 'emmc_error_status'
+ */
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_NONE                     0x0U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_CMD_TIMEOUT              0x1U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_TIMEOUT              0x2U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_DATA_CRC_FAIL            0x3U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_NOT_ENOUGH_BOOT_DATA_RX  0x4U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND         0x5U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO         0x6U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE       0x7U
+
+/* Image Header related definitions */
+
+/* Definition of header version */
+#define BOOT_API_HEADER_VERSION					0x00010000U
+
+/*
+ * Magic number used to detect header in memory
+ * Its value must be 'S' 'T' 'M' 0x32, i.e 0x324D5453 as field
+ * 'bootapi_image_header_t.magic'
+ * This identifies the start of a boot image.
+ */
+#define BOOT_API_IMAGE_HEADER_MAGIC_NB				0x324D5453U
+
+/* Definitions related to Authentication used in image header structure */
+#define BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES			64
+#define BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES			64
+#define BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES			32
+
+/* Possible values of the field 'boot_api_image_header_t.ecc_algo_type' */
+#define BOOT_API_ECDSA_ALGO_TYPE_P256NIST			1
+#define BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256			2
+
+/*
+ * Cores secure magic numbers
+ * Constant to be stored in bakcup register
+ * BOOT_API_MAGIC_NUMBER_TAMP_BCK_REG_IDX
+ */
+#define BOOT_API_A7_CORE0_MAGIC_NUMBER				0xCA7FACE0U
+#define BOOT_API_A7_CORE1_MAGIC_NUMBER				0xCA7FACE1U
+
+/*
+ * TAMP_BCK4R register index
+ * This register is used to write a Magic Number in order to restart
+ * Cortex A7 Core 1 and make it execute @ branch address from TAMP_BCK5R
+ */
+#define BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX		4U
+
+/*
+ * TAMP_BCK5R register index
+ * This register is used to contain the branch address of
+ * Cortex A7 Core 1 when restarted by a TAMP_BCK4R magic number writing
+ */
+#define BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX		5U
+
+/*
+ * Possible value of boot context field 'hse_clock_value_in_hz'
+ */
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_UNDEFINED			0U
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_24_MHZ			24000000U
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_25_MHZ			25000000U
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_26_MHZ			26000000U
+
+/*
+ * Possible value of boot context field 'boot_partition_used_toboot'
+ */
+#define BOOT_API_CTX_BOOT_PARTITION_UNDEFINED			0U
+
+/* Used FSBL1 to boot */
+#define BOOT_API_CTX_BOOT_PARTITION_FSBL1			1U
+
+/* Used FSBL2 to boot */
+#define BOOT_API_CTX_BOOT_PARTITION_FSBL2			2U
+
+/* OTP_CFG0 */
+#define BOOT_API_OTP_MODE_WORD_NB				0
+/* Closed = OTP_CFG0[6] */
+#define BOOT_API_OTP_MODE_CLOSED_BIT_POS			6
+
+/*
+ * Boot Context related definitions
+ */
+
+/*
+ * Boot core boot configuration structure
+ * Specifies all items of the cold boot configuration
+ * Memory and peripheral part.
+ */
+typedef struct {
+	/*
+	 * Boot interface used to boot : take values from defines
+	 * BOOT_API_CTX_BOOT_INTERFACE_SEL_XXX above
+	 */
+	uint16_t boot_interface_selected;
+	uint16_t boot_interface_instance;
+	uint32_t reserved1[13];
+	uint32_t otp_afmux_values[3];
+	uint32_t reserved[9];
+	/*
+	 * Information specific to an SD boot
+	 * Updated each time an SD boot is at least attempted,
+	 * even if not successful
+	 * Note : This is useful to understand why an SD boot failed
+	 * in particular
+	 */
+	uint32_t sd_err_internal_timeout_cnt;
+	uint32_t sd_err_dcrc_fail_cnt;
+	uint32_t sd_err_dtimeout_cnt;
+	uint32_t sd_err_ctimeout_cnt;
+	uint32_t sd_err_ccrc_fail_cnt;
+	uint32_t sd_overall_retry_cnt;
+	/*
+	 * Information specific to an eMMC boot
+	 * Updated each time an eMMC boot is at least attempted,
+	 * even if not successful
+	 * Note : This is useful to understand why an eMMC boot failed
+	 * in particular
+	 */
+	uint32_t emmc_xfer_status;
+	uint32_t emmc_error_status;
+	uint32_t emmc_nbbytes_rxcopied_tosysram_download_area;
+	uint32_t hse_clock_value_in_hz;
+	/*
+	 * Boot partition :
+	 * ie FSBL partition on which the boot was successful
+	 */
+	uint32_t boot_partition_used_toboot;
+
+} __packed boot_api_context_t;
+
+/*
+ * Image Header related definitions
+ */
+
+/*
+ * Structure used to define the common Header format used for FSBL, xloader,
+ * ... and in particular used by bootROM for FSBL header readout.
+ * FSBL header size is 256 Bytes = 0x100
+ */
+typedef struct {
+	/* BOOT_API_IMAGE_HEADER_MAGIC_NB */
+	uint32_t magic;
+	uint8_t image_signature[BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES];
+	/*
+	 * Checksum of payload
+	 * 32-bit sum all all payload bytes considered as 8 bit unigned numbers,
+	 * discarding any overflow bits.
+	 * Use to check UART/USB downloaded image integrity when signature
+	 * is not used (i.e bit 0 : 'No_sig_check' = 1 in option flags)
+	 */
+	uint32_t payload_checksum;
+	/* Image header version : should have value BOOT_API_HEADER_VERSION */
+	uint32_t header_version;
+	/* Image length in bytes */
+	uint32_t image_length;
+	/*
+	 * Image Entry point address : should be in the SYSRAM area
+	 * and at least within the download area range
+	 */
+	uint32_t image_entry_point;
+	/* Reserved */
+	uint32_t reserved1;
+	/*
+	 * Image load address : not used by bootROM but to be consistent
+	 * with header format for other packages (xloader, ...)
+	 */
+	uint32_t load_address;
+	/* Reserved */
+	uint32_t reserved2;
+	/* Image version to be compared by bootROM with monotonic
+	 * counter value in OTP_CFG4 prior executing the downloaded image
+	 */
+	uint32_t image_version;
+	/*
+	 * Option flags:
+	 * Bit 0 : No signature check request : 'No_sig_check'
+	 *      value 1 : for No signature check request
+	 *      value 0 : No request to bypass the signature check
+	 * Note : No signature check is never allowed on a Secured chip
+	 */
+	uint32_t option_flags;
+	/*
+	 * Type of ECC algorithm to use  :
+	 * value 1 : for P-256 NIST algorithm
+	 * value 2 : for Brainpool 256 algorithm
+	 * See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above.
+	 */
+	uint32_t ecc_algo_type;
+	/*
+	 * OEM ECC Public Key (aka Root pubk) provided in header on 512 bits.
+	 * The SHA-256 hash of the OEM ECC pubk must match the one stored
+	 * in OTP cells.
+	 */
+	uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
+	/* Pad up to 256 byte total size */
+	uint8_t pad[84];
+} __packed boot_api_image_header_t;
+
+#endif /* __BOOT_API_H */
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
new file mode 100644
index 0000000..47e1ffc
--- /dev/null
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common_def.h>
+#include <gic_common.h>
+#include <utils_def.h>
+#include "../stm32mp1_def.h"
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL32)
+#define PLATFORM_STACK_SIZE		0x600
+#else
+#define PLATFORM_STACK_SIZE		0xC00
+#endif
+
+/* SSBL = second stage boot loader */
+#define BL33_IMAGE_NAME			"ssbl"
+
+#define STM32MP1_PRIMARY_CPU		U(0x0)
+
+#define PLATFORM_CACHE_LINE_SIZE	64
+#define PLATFORM_CLUSTER_COUNT		ULL(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	U(2)
+#define PLATFORM_CLUSTER1_CORE_COUNT	U(0)
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER1_CORE_COUNT + \
+					 PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	2
+
+#define MAX_IO_DEVICES			4
+#define MAX_IO_HANDLES			4
+
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define BL2_BASE			STM32MP1_BL2_BASE
+#define BL2_LIMIT			(STM32MP1_BL2_BASE + \
+					 STM32MP1_BL2_SIZE)
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+#define BL32_BASE			STM32MP1_BL32_BASE
+#define BL32_LIMIT			(STM32MP1_BL32_BASE + \
+					 STM32MP1_BL32_SIZE)
+
+/*******************************************************************************
+ * BL33 specific defines.
+ ******************************************************************************/
+#define BL33_BASE			STM32MP1_BL33_BASE
+
+/*
+ * Load address of BL33 for this platform port
+ */
+#define PLAT_STM32MP1_NS_IMAGE_OFFSET	BL33_BASE
+
+/*******************************************************************************
+ * DTB specific defines.
+ ******************************************************************************/
+#define DTB_BASE			STM32MP1_DTB_BASE
+#define DTB_LIMIT			(STM32MP1_DTB_BASE + \
+					 STM32MP1_DTB_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT		6
+#define CACHE_WRITEBACK_GRANULE		(U(1) << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Secure Interrupt: based on the standard ARM mapping
+ */
+#define ARM_IRQ_SEC_PHY_TIMER		U(29)
+
+#define ARM_IRQ_SEC_SGI_0		U(8)
+#define ARM_IRQ_SEC_SGI_1		U(9)
+#define ARM_IRQ_SEC_SGI_2		U(10)
+#define ARM_IRQ_SEC_SGI_3		U(11)
+#define ARM_IRQ_SEC_SGI_4		U(12)
+#define ARM_IRQ_SEC_SGI_5		U(13)
+#define ARM_IRQ_SEC_SGI_6		U(14)
+#define ARM_IRQ_SEC_SGI_7		U(15)
+
+#define STM32MP1_IRQ_TZC400		U(36)
+#define STM32MP1_IRQ_TAMPSERRS		U(229)
+#define STM32MP1_IRQ_AXIERRIRQ		U(244)
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLATFORM_G1S_PROPS(grp) \
+	INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_LEVEL),	\
+	INTR_PROP_DESC(STM32MP1_IRQ_TAMPSERRS,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_LEVEL),	\
+	INTR_PROP_DESC(STM32MP1_IRQ_AXIERRIRQ,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_LEVEL),	\
+	INTR_PROP_DESC(STM32MP1_IRQ_TZC400,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_LEVEL),	\
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_EDGE),		\
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_EDGE),		\
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_EDGE),		\
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_EDGE),		\
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_EDGE),		\
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_EDGE)
+
+#define PLATFORM_G0_PROPS(grp) \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_EDGE),		\
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6,		\
+		       GIC_HIGHEST_SEC_PRIORITY,	\
+		       grp, GIC_INTR_CFG_EDGE)
+
+/*
+ * Power
+ */
+#define PLAT_MAX_PWR_LVL	U(1)
+
+/* Local power state for power domains in Run state. */
+#define ARM_LOCAL_STATE_RUN	U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define ARM_LOCAL_STATE_RET	U(1)
+/* Local power state for power-down. Valid for CPU and cluster power domains */
+#define ARM_LOCAL_STATE_OFF	U(2)
+/*
+ * This macro defines the deepest retention state possible.
+ * A higher state id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE		ARM_LOCAL_STATE_RET
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE		ARM_LOCAL_STATE_OFF
+
+/*******************************************************************************
+ * Size of the per-cpu data in bytes that should be reserved in the generic
+ * per-cpu data structure for the FVP port.
+ ******************************************************************************/
+#define PLAT_PCPU_DATA_SIZE	2
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_context.h b/plat/st/stm32mp1/include/stm32mp1_context.h
new file mode 100644
index 0000000..fd08afc
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_context.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_CONTEXT_H__
+#define __STM32MP1_CONTEXT_H__
+
+#include <stdint.h>
+
+int stm32_save_boot_interface(uint32_t interface, uint32_t instance);
+
+#endif /* __STM32MP1_CONTEXT_H__ */
diff --git a/plat/st/stm32mp1/include/stm32mp1_dt.h b/plat/st/stm32mp1/include/stm32mp1_dt.h
new file mode 100644
index 0000000..58e10d1
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_dt.h
@@ -0,0 +1,41 @@
+/*
+ * 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>
+
+struct dt_node_info {
+	uint32_t base;
+	int32_t clock;
+	int32_t reset;
+	bool status;
+	bool sec_status;
+};
+
+/*******************************************************************************
+ * 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);
+int dt_set_pinctrl_config(int node);
+int dt_set_stdout_pinctrl(void);
+void dt_fill_device_info(struct dt_node_info *info, int node);
+int dt_get_node(struct dt_node_info *info, int offset, const char *compat);
+int dt_get_stdout_uart_info(struct dt_node_info *info);
+int dt_get_stdout_node_offset(void);
+uint32_t dt_get_ddr_size(void);
+const char *dt_get_board_model(void);
+
+#endif /* __STM32MP1_DT_H__ */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
new file mode 100644
index 0000000..a789d53
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_PRIVATE_H__
+#define __STM32MP1_PRIVATE_H__
+
+void stm32mp1_io_setup(void);
+void configure_mmu(void);
+
+void stm32mp1_arch_security_setup(void);
+void stm32mp1_security_setup(void);
+
+void stm32mp1_save_boot_ctx_address(uintptr_t address);
+uintptr_t stm32mp1_get_boot_ctx_address(void);
+
+void stm32mp1_gic_pcpu_init(void);
+void stm32mp1_gic_init(void);
+
+#endif /* __STM32MP1_PRIVATE_H__ */
diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
new file mode 100644
index 0000000..6f5bc4c
--- /dev/null
+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+	/* Fill BL32 related information */
+	{
+		.image_id = BL32_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | EXECUTABLE | EP_FIRST_EXE),
+
+		.ep_info.pc = BL32_BASE,
+		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+					    SPSR_E_LITTLE,
+					    DISABLE_ALL_EXCEPTIONS),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_PLAT_SETUP),
+
+		.image_info.image_base = BL32_BASE,
+		.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+		.next_handoff_image_id = BL33_IMAGE_ID,
+	},
+
+	/* Fill BL33 related information */
+	{
+		.image_id = BL33_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      NON_SECURE | EXECUTABLE),
+
+		.ep_info.pc = PLAT_STM32MP1_NS_IMAGE_OFFSET,
+		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+					    SPSR_E_LITTLE,
+					    DISABLE_ALL_EXCEPTIONS),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t, 0),
+
+		.image_info.image_base = PLAT_STM32MP1_NS_IMAGE_OFFSET,
+		.image_info.image_max_size = STM32MP1_DDR_MAX_SIZE -
+			(PLAT_STM32MP1_NS_IMAGE_OFFSET - STM32MP1_DDR_BASE),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	}
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c
new file mode 100644
index 0000000..3c6d677
--- /dev/null
+++ b/plat/st/stm32mp1/plat_image_load.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <desc_image_load.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+	flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+	return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+	return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
new file mode 100644
index 0000000..3f938d9
--- /dev/null
+++ b/plat/st/stm32mp1/platform.mk
@@ -0,0 +1,148 @@
+#
+# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ARM_CORTEX_A7		:=	yes
+ARM_WITH_NEON		:=	yes
+LOAD_IMAGE_V2		:=	1
+BL2_AT_EL3		:=	1
+ENABLE_PLAT_COMPAT	:=	0
+USE_COHERENT_MEM	:=	0
+
+STM32_TF_VERSION	?=	0
+
+# Not needed for Cortex-A7
+WORKAROUND_CVE_2017_5715:=	0
+
+PLAT_INCLUDES		:=	-Iplat/st/stm32mp1/include/
+PLAT_INCLUDES		+=	-Iinclude/common/tbbr
+PLAT_INCLUDES		+=	-Iinclude/drivers/st
+
+# Device tree
+STM32_DTB_FILE_NAME	?=	stm32mp157c-ev1.dtb
+FDT_SOURCES		:=	$(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32_DTB_FILE_NAME)))
+DTC_FLAGS		+=	-Wno-unit_address_vs_reg
+
+include lib/libfdt/libfdt.mk
+
+PLAT_BL_COMMON_SOURCES	:=	plat/st/stm32mp1/stm32mp1_common.c
+
+PLAT_BL_COMMON_SOURCES	+=	drivers/console/aarch32/console.S			\
+				drivers/st/uart/aarch32/stm32_console.S
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES	+=	plat/st/stm32mp1/stm32mp1_stack_protector.c
+endif
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
+
+PLAT_BL_COMMON_SOURCES	+=	lib/cpus/aarch32/cortex_a7.S
+
+PLAT_BL_COMMON_SOURCES	+=	${LIBFDT_SRCS}						\
+				drivers/arm/tzc/tzc400.c				\
+				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/ddr/stm32mp1_ddr_helpers.c			\
+				drivers/st/gpio/stm32_gpio.c				\
+				drivers/st/pmic/stm32_i2c.c				\
+				drivers/st/pmic/stm32mp1_pmic.c				\
+				drivers/st/pmic/stpmu1.c				\
+				drivers/st/reset/stm32mp1_reset.c			\
+				plat/st/stm32mp1/stm32mp1_context.c			\
+				plat/st/stm32mp1/stm32mp1_dt.c				\
+				plat/st/stm32mp1/stm32mp1_helper.S			\
+				plat/st/stm32mp1/stm32mp1_security.c
+
+BL2_SOURCES		+=	drivers/io/io_dummy.c					\
+				drivers/io/io_storage.c					\
+				plat/st/stm32mp1/bl2_io_storage.c			\
+				plat/st/stm32mp1/bl2_plat_setup.c
+
+BL2_SOURCES		+=	drivers/st/ddr/stm32mp1_ddr.c				\
+				drivers/st/ddr/stm32mp1_ram.c
+
+BL2_SOURCES		+=	common/desc_image_load.c				\
+				plat/st/stm32mp1/plat_bl2_mem_params_desc.c		\
+				plat/st/stm32mp1/plat_image_load.c
+
+# For memory footprint optimization, build with thumb and interwork support
+ASFLAGS			+=	-mthumb -mthumb-interwork
+TF_CFLAGS		+=	-mthumb -mthumb-interwork
+
+# Macros and rules to build TF binary
+STM32_TF_ELF_LDFLAGS	:=	--hash-style=gnu --as-needed
+STM32_DT_BASENAME	:=	$(STM32_DTB_FILE_NAME:.dtb=)
+STM32_TF_STM32		:=	${BUILD_PLAT}/tf-a-${STM32_DT_BASENAME}.stm32
+STM32_TF_BINARY		:=	$(STM32_TF_STM32:.stm32=.bin)
+STM32_TF_MAPFILE	:=	$(STM32_TF_STM32:.stm32=.map)
+STM32_TF_LINKERFILE	:=	$(STM32_TF_STM32:.stm32=.ld)
+STM32_TF_ELF		:=	$(STM32_TF_STM32:.stm32=.elf)
+STM32_TF_DTBFILE	:=      ${BUILD_PLAT}/fdts/${STM32_DTB_FILE_NAME}
+STM32_TF_OBJS		:=	${BUILD_PLAT}/stm32mp1.o
+
+# Variables for use with stm32image
+STM32IMAGEPATH		?= tools/stm32image
+STM32IMAGE		?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
+
+.PHONY:			${STM32_TF_STM32}
+.SUFFIXES:
+
+all: check_dtc_version ${STM32_TF_STM32} stm32image
+
+ifeq ($(AARCH32_SP),sp_min)
+# BL32 is built only if using SP_MIN
+BL32_DEP		:= bl32
+BL32_PATH		:= -DBL32_BIN_PATH=\"${BUILD_PLAT}/bl32.bin\"
+endif
+
+distclean realclean clean: clean_stm32image
+
+stm32image:
+	${Q}${MAKE} CPPFLAGS="" --no-print-directory -C ${STM32IMAGEPATH}
+
+clean_stm32image:
+	${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean
+
+check_dtc_version:
+	$(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}'))
+	$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g")))
+	@if [ ${DTC_VERSION} -lt 10404 ]; then \
+		echo "dtc version too old (${DTC_V}), you need at least version 1.4.4"; \
+		false; \
+	fi
+
+
+${STM32_TF_OBJS}:	plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} ${STM32_TF_DTBFILE}
+			@echo "  AS      $<"
+			${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
+				${BL32_PATH} \
+				-DBL2_BIN_PATH=\"${BUILD_PLAT}/bl2.bin\" \
+				-DDTB_BIN_PATH=\"${STM32_TF_DTBFILE}\" \
+				-c plat/st/stm32mp1/stm32mp1.S -o $@
+
+${STM32_TF_LINKERFILE}:	plat/st/stm32mp1/stm32mp1.ld.S
+			@echo "  LDS     $<"
+			${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} -P -E $< -o $@
+
+${STM32_TF_ELF}:	${STM32_TF_OBJS} ${STM32_TF_LINKERFILE}
+			@echo "  LDS     $<"
+			${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=${STM32_TF_MAPFILE} --script ${STM32_TF_LINKERFILE} ${STM32_TF_OBJS}
+
+${STM32_TF_BINARY}:	${STM32_TF_ELF}
+			${Q}${OC} -O binary ${STM32_TF_ELF} $@
+			@echo
+			@echo "Built $@ successfully"
+			@echo
+
+${STM32_TF_STM32}:	stm32image ${STM32_TF_BINARY}
+			@echo
+			@echo "Generated $@"
+			$(eval LOADADDR =  $(shell cat ${STM32_TF_MAPFILE} | grep RAM | awk '{print $$2}'))
+			$(eval ENTRY =  $(shell cat ${STM32_TF_MAPFILE} | grep "__BL2_IMAGE_START" | awk '{print $$1}'))
+			${STM32IMAGE} -s ${STM32_TF_BINARY} -d $@ -l $(LOADADDR) -e ${ENTRY} -v ${STM32_TF_VERSION}
+			@echo
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
new file mode 100644
index 0000000..9fde153
--- /dev/null
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+SP_MIN_WITH_SECURE_FIQ	:=	1
+
+BL32_SOURCES		+=	plat/common/aarch32/platform_mp_stack.S		\
+				plat/st/stm32mp1/sp_min/sp_min_setup.c		\
+				plat/st/stm32mp1/stm32mp1_pm.c			\
+				plat/st/stm32mp1/stm32mp1_topology.c
+# Generic GIC v2
+BL32_SOURCES		+=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v2/gicv2_helpers.c	\
+				drivers/arm/gic/v2/gicv2_main.c		\
+				plat/common/plat_gicv2.c		\
+				plat/st/stm32mp1/stm32mp1_gic.c
+
+# Generic PSCI
+BL32_SOURCES		+=	plat/common/plat_psci_common.c
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
new file mode 100644
index 0000000..1329bdb
--- /dev/null
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <generic_delay_timer.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <platform_sp_min.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_dt.h>
+#include <stm32mp1_private.h>
+#include <string.h>
+#include <tzc400.h>
+#include <xlat_tables_v2.h>
+
+/******************************************************************************
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL32 from BL2.
+ ******************************************************************************/
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Interrupt handler for FIQ (secure IRQ)
+ ******************************************************************************/
+void sp_min_plat_fiq_handler(uint32_t id)
+{
+	switch (id) {
+	case STM32MP1_IRQ_TZC400:
+		ERROR("STM32MP1_IRQ_TZC400 generated\n");
+		panic();
+		break;
+	case STM32MP1_IRQ_AXIERRIRQ:
+		ERROR("STM32MP1_IRQ_AXIERRIRQ generated\n");
+		panic();
+		break;
+	default:
+		ERROR("SECURE IT handler not define for it : %i", id);
+		break;
+	}
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
+{
+	entry_point_info_t *next_image_info;
+
+	next_image_info = &bl33_image_ep_info;
+
+	if (next_image_info->pc == 0U) {
+		return NULL;
+	}
+
+	return next_image_info;
+}
+
+/*******************************************************************************
+ * Perform any BL32 specific platform actions.
+ ******************************************************************************/
+void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				  u_register_t arg2, u_register_t arg3)
+{
+	struct dt_node_info dt_dev_info;
+	int result;
+	bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
+
+	/* Imprecise aborts can be masked in NonSecure */
+	write_scr(read_scr() | SCR_AW_BIT);
+
+	assert(params_from_bl2 != NULL);
+	assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+	assert(params_from_bl2->h.version >= VERSION_2);
+
+	bl_params_node_t *bl_params = params_from_bl2->head;
+
+	/*
+	 * Copy BL33 entry point information.
+	 * They are stored in Secure RAM, in BL2's address space.
+	 */
+	while (bl_params != NULL) {
+		if (bl_params->image_id == BL33_IMAGE_ID) {
+			bl33_image_ep_info = *bl_params->ep_info;
+			break;
+		}
+
+		bl_params = bl_params->next_params_info;
+	}
+
+	if (dt_open_and_check() < 0) {
+		panic();
+	}
+
+	if (stm32mp1_clk_probe() < 0) {
+		panic();
+	}
+
+	result = dt_get_stdout_uart_info(&dt_dev_info);
+
+	if ((result > 0) && dt_dev_info.status) {
+		if (console_init(dt_dev_info.base, 0, STM32MP1_UART_BAUDRATE)
+		    == 0) {
+			panic();
+		}
+	}
+}
+
+/*******************************************************************************
+ * Initialize the MMU, security and the GIC.
+ ******************************************************************************/
+void sp_min_platform_setup(void)
+{
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+			BL_CODE_END - BL_CODE_BASE,
+			MT_CODE | MT_SECURE);
+
+	configure_mmu();
+
+	/* Initialize tzc400 after DDR initialization */
+	stm32mp1_security_setup();
+
+	generic_delay_timer_init();
+
+	stm32mp1_gic_init();
+}
+
+void sp_min_plat_arch_setup(void)
+{
+}
diff --git a/plat/st/stm32mp1/stm32mp1.S b/plat/st/stm32mp1/stm32mp1.S
new file mode 100644
index 0000000..7255fe5
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1.S
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifdef BL32_BIN_PATH
+.section .bl32_image
+.incbin BL32_BIN_PATH
+#endif
+
+.section .bl2_image
+.incbin BL2_BIN_PATH
+
+.section .dtb_image
+.incbin DTB_BIN_PATH
diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S
new file mode 100644
index 0000000..0d7a8bb
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1.ld.S
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_LD_S__
+#define __STM32MP1_LD_S__
+#include <platform_def.h>
+#include <xlat_tables_defs.h>
+
+OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
+OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
+
+ENTRY(__BL2_IMAGE_START__)
+
+MEMORY {
+	HEADER (rw) : ORIGIN = 0x00000000, LENGTH = 0x3000
+	RAM (rwx) : ORIGIN = STM32MP1_BINARY_BASE, LENGTH = STM32MP1_BINARY_SIZE
+}
+
+SECTIONS
+{
+    /*
+     * TF mapping must conform to ROM code specification.
+     */
+    .header : {
+        __HEADER_START__ = .;
+        KEEP(*(.header))
+        . = ALIGN(4);
+        __HEADER_END__ = .;
+    } >HEADER
+
+    . = STM32MP1_BINARY_BASE;
+    .data . : {
+        . = ALIGN(PAGE_SIZE);
+        __DATA_START__ = .;
+        *(.data*)
+
+        /*
+         * dtb.
+         * The strongest and only alignment contraint is MMU 4K page.
+         * Indeed as images below will be removed, 4K pages will be re-used.
+         */
+        . = ( STM32MP1_DTB_BASE - STM32MP1_BINARY_BASE );
+        __DTB_IMAGE_START__ = .;
+        *(.dtb_image*)
+        __DTB_IMAGE_END__ = .;
+
+        /*
+         * bl2.
+         * The strongest and only alignment contraint is MMU 4K page.
+         * Indeed as images below will be removed, 4K pages will be re-used.
+         */
+        . = ( STM32MP1_BL2_BASE - STM32MP1_BINARY_BASE );
+        __BL2_IMAGE_START__ = .;
+        *(.bl2_image*)
+        __BL2_IMAGE_END__ = .;
+
+        /*
+         * bl32 will be settled by bl2.
+         * The strongest and only alignment constraint is 8 words to simplify
+         * memraise8 assembly code.
+         */
+        . = ( STM32MP1_BL32_BASE - STM32MP1_BINARY_BASE );
+        __BL32_IMAGE_START__ = .;
+        *(.bl32_image*)
+        __BL32_IMAGE_END__ = .;
+
+        __DATA_END__ = .;
+    } >RAM
+
+    __TF_END__ = .;
+
+}
+#endif /*__STM32MP1_LD_S__*/
diff --git a/plat/st/stm32mp1/stm32mp1_common.c b/plat/st/stm32mp1/stm32mp1_common.c
new file mode 100644
index 0000000..68ca7db
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_common.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <gicv2.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <platform.h>
+#include <stm32mp1_private.h>
+#include <xlat_tables_v2.h>
+
+#define MAP_SRAM	MAP_REGION_FLAT(STM32MP1_SRAM_BASE, \
+					STM32MP1_SRAM_SIZE, \
+					MT_MEMORY | \
+					MT_RW | \
+					MT_SECURE | \
+					MT_EXECUTE_NEVER)
+
+#define MAP_DEVICE1	MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \
+					STM32MP1_DEVICE1_SIZE, \
+					MT_DEVICE | \
+					MT_RW | \
+					MT_SECURE | \
+					MT_EXECUTE_NEVER)
+
+#define MAP_DEVICE2	MAP_REGION_FLAT(STM32MP1_DEVICE2_BASE, \
+					STM32MP1_DEVICE2_SIZE, \
+					MT_DEVICE | \
+					MT_RW | \
+					MT_SECURE | \
+					MT_EXECUTE_NEVER)
+
+#define MAP_DDR		MAP_REGION_FLAT(STM32MP1_DDR_BASE, \
+					STM32MP1_DDR_MAX_SIZE, \
+					MT_MEMORY | \
+					MT_RW | \
+					MT_SECURE | \
+					MT_EXECUTE_NEVER)
+
+#define MAP_DDR_NS	MAP_REGION_FLAT(STM32MP1_DDR_BASE, \
+					STM32MP1_DDR_MAX_SIZE, \
+					MT_MEMORY | \
+					MT_RW | \
+					MT_NS | \
+					MT_EXECUTE_NEVER)
+
+#if defined(IMAGE_BL2)
+static const mmap_region_t stm32mp1_mmap[] = {
+	MAP_SRAM,
+	MAP_DEVICE1,
+	MAP_DEVICE2,
+	MAP_DDR,
+	{0}
+};
+#endif
+#if defined(IMAGE_BL32)
+static const mmap_region_t stm32mp1_mmap[] = {
+	MAP_SRAM,
+	MAP_DEVICE1,
+	MAP_DEVICE2,
+	MAP_DDR_NS,
+	{0}
+};
+#endif
+
+void configure_mmu(void)
+{
+	mmap_add(stm32mp1_mmap);
+	init_xlat_tables();
+
+	enable_mmu_secure(0);
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+	return BL33_BASE;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return read_cntfrq_el0();
+}
+
+/* Functions to save and get boot context address given by ROM code */
+static uintptr_t boot_ctx_address;
+
+void stm32mp1_save_boot_ctx_address(uintptr_t address)
+{
+	boot_ctx_address = address;
+}
+
+uintptr_t stm32mp1_get_boot_ctx_address(void)
+{
+	return boot_ctx_address;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c
new file mode 100644
index 0000000..245fd17
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_context.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <errno.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_context.h>
+
+#define TAMP_BOOT_ITF_BACKUP_REG_ID	U(20)
+#define TAMP_BOOT_ITF_MASK		U(0x0000FF00)
+#define TAMP_BOOT_ITF_SHIFT		8
+
+int stm32_save_boot_interface(uint32_t interface, uint32_t instance)
+{
+	uint32_t tamp_clk_off = 0;
+	uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID);
+
+	if (!stm32mp1_clk_is_enabled(RTCAPB)) {
+		tamp_clk_off = 1;
+		if (stm32mp1_clk_enable(RTCAPB) != 0) {
+			return -EINVAL;
+		}
+	}
+
+	mmio_clrsetbits_32(bkpr_itf_idx,
+			   TAMP_BOOT_ITF_MASK,
+			   ((interface << 4) | (instance & 0xFU)) <<
+			   TAMP_BOOT_ITF_SHIFT);
+
+	if (tamp_clk_off != 0U) {
+		if (stm32mp1_clk_disable(RTCAPB) != 0) {
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
new file mode 100644
index 0000000..bb3fecf
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_DEF_H
+#define STM32MP1_DEF_H
+
+#include <tbbr_img_def.h>
+#include <utils_def.h>
+#include <xlat_tables_defs.h>
+
+/*******************************************************************************
+ * STM32MP1 memory map related constants
+ ******************************************************************************/
+
+#define STM32MP1_SRAM_BASE		U(0x2FFC0000)
+#define STM32MP1_SRAM_SIZE		U(0x00040000)
+
+/* DDR configuration */
+#define STM32MP1_DDR_BASE		U(0xC0000000)
+#define STM32MP1_DDR_SIZE_DFLT		U(0x20000000)	/* 512 MB */
+#define STM32MP1_DDR_MAX_SIZE		U(0x40000000)	/* Max 1GB */
+#define STM32MP1_DDR_SPEED_DFLT		528
+
+/* DDR power initializations */
+#ifndef __ASSEMBLY__
+enum ddr_type {
+	STM32MP_DDR3,
+	STM32MP_LPDDR2,
+};
+#endif
+
+/* Section used inside TF binaries */
+#define STM32MP1_PARAM_LOAD_SIZE	U(0x00002400)	/* 9 Ko for param */
+/* 256 Octets reserved for header */
+#define STM32MP1_HEADER_SIZE		U(0x00000100)
+
+#define STM32MP1_BINARY_BASE		(STM32MP1_SRAM_BASE +		\
+					 STM32MP1_PARAM_LOAD_SIZE +	\
+					 STM32MP1_HEADER_SIZE)
+
+#define STM32MP1_BINARY_SIZE		(STM32MP1_SRAM_SIZE -		\
+					 (STM32MP1_PARAM_LOAD_SIZE +	\
+					  STM32MP1_HEADER_SIZE))
+
+#if STACK_PROTECTOR_ENABLED
+#define STM32MP1_BL32_SIZE		U(0x00012000)	/* 72 Ko for BL32 */
+#else
+#define STM32MP1_BL32_SIZE		U(0x00011000)	/* 68 Ko for BL32 */
+#endif
+
+#define STM32MP1_BL32_BASE		(STM32MP1_SRAM_BASE + \
+					 STM32MP1_SRAM_SIZE - \
+					 STM32MP1_BL32_SIZE)
+
+#if STACK_PROTECTOR_ENABLED
+#define STM32MP1_BL2_SIZE		U(0x00015000)	/* 84 Ko for BL2 */
+#else
+#define STM32MP1_BL2_SIZE		U(0x00013000)	/* 76 Ko for BL2 */
+#endif
+
+#define STM32MP1_BL2_BASE		(STM32MP1_BL32_BASE - \
+					 STM32MP1_BL2_SIZE)
+
+/* BL2 and BL32/sp_min require 5 tables */
+#define MAX_XLAT_TABLES			5
+
+/*
+ * MAX_MMAP_REGIONS is usually:
+ * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
+ */
+#if defined(IMAGE_BL2)
+  #define MAX_MMAP_REGIONS		11
+#endif
+#if defined(IMAGE_BL32)
+  #define MAX_MMAP_REGIONS		6
+#endif
+
+/* DTB initialization value */
+#define STM32MP1_DTB_SIZE		U(0x00004000)	/* 16Ko for DTB */
+
+#define STM32MP1_DTB_BASE		(STM32MP1_BL2_BASE - \
+					 STM32MP1_DTB_SIZE)
+
+#define STM32MP1_BL33_BASE		(STM32MP1_DDR_BASE + U(0x100000))
+
+/*******************************************************************************
+ * STM32MP1 device/io map related constants (used for MMU)
+ ******************************************************************************/
+#define STM32MP1_DEVICE1_BASE		U(0x40000000)
+#define STM32MP1_DEVICE1_SIZE		U(0x40000000)
+
+#define STM32MP1_DEVICE2_BASE		U(0x80000000)
+#define STM32MP1_DEVICE2_SIZE		U(0x40000000)
+
+/*******************************************************************************
+ * STM32MP1 RCC
+ ******************************************************************************/
+#define RCC_BASE			U(0x50000000)
+
+/*******************************************************************************
+ * STM32MP1 PWR
+ ******************************************************************************/
+#define PWR_BASE			U(0x50001000)
+
+/*******************************************************************************
+ * STM32MP1 UART
+ ******************************************************************************/
+#define USART1_BASE			U(0x5C000000)
+#define USART2_BASE			U(0x4000E000)
+#define USART3_BASE			U(0x4000F000)
+#define UART4_BASE			U(0x40010000)
+#define UART5_BASE			U(0x40011000)
+#define USART6_BASE			U(0x44003000)
+#define UART7_BASE			U(0x40018000)
+#define UART8_BASE			U(0x40019000)
+#define STM32MP1_DEBUG_USART_BASE	UART4_BASE
+#define STM32MP1_UART_BAUDRATE		115200
+
+/*******************************************************************************
+ * STM32MP1 GIC-400
+ ******************************************************************************/
+#define STM32MP1_GICD_BASE		U(0xA0021000)
+#define STM32MP1_GICC_BASE		U(0xA0022000)
+#define STM32MP1_GICH_BASE		U(0xA0024000)
+#define STM32MP1_GICV_BASE		U(0xA0026000)
+
+/*******************************************************************************
+ * STM32MP1 TZC (TZ400)
+ ******************************************************************************/
+#define STM32MP1_TZC_BASE		U(0x5C006000)
+
+#define STM32MP1_TZC_A7_ID		U(0)
+#define STM32MP1_TZC_LCD_ID		U(3)
+#define STM32MP1_TZC_GPU_ID		U(4)
+#define STM32MP1_TZC_MDMA_ID		U(5)
+#define STM32MP1_TZC_DMA_ID		U(6)
+#define STM32MP1_TZC_USB_HOST_ID	U(7)
+#define STM32MP1_TZC_USB_OTG_ID		U(8)
+#define STM32MP1_TZC_SDMMC_ID		U(9)
+#define STM32MP1_TZC_ETH_ID		U(10)
+#define STM32MP1_TZC_DAP_ID		U(15)
+
+#define STM32MP1_MEMORY_NS		0
+#define STM32MP1_MEMORY_SECURE		1
+
+#define STM32MP1_FILTER_BIT_ALL		3
+
+/*******************************************************************************
+ * STM32MP1 SDMMC
+ ******************************************************************************/
+#define STM32MP1_SDMMC1_BASE		U(0x58005000)
+#define STM32MP1_SDMMC2_BASE		U(0x58007000)
+#define STM32MP1_SDMMC3_BASE		U(0x48004000)
+
+#define STM32MP1_SD_INIT_FREQ			400000		/*400 KHz*/
+#define STM32MP1_SD_NORMAL_SPEED_MAX_FREQ	25000000	/*25 MHz*/
+#define STM32MP1_SD_HIGH_SPEED_MAX_FREQ		50000000	/*50 MHz*/
+#define STM32MP1_EMMC_INIT_FREQ			STM32MP1_SD_INIT_FREQ
+#define STM32MP1_EMMC_NORMAL_SPEED_MAX_FREQ	26000000	/*26 MHz*/
+#define STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ	52000000	/*52 MHz*/
+
+/*******************************************************************************
+ * STM32MP1 TAMP
+ ******************************************************************************/
+#define TAMP_BASE			U(0x5C00A000)
+#define TAMP_BKP_REGISTER_BASE		(TAMP_BASE + U(0x100))
+
+#if !(defined(__LINKER__) || defined(__ASSEMBLY__))
+static inline uint32_t tamp_bkpr(uint32_t idx)
+{
+	return TAMP_BKP_REGISTER_BASE + (idx << 2);
+}
+#endif
+
+/*******************************************************************************
+ * STM32MP1 DDRCTRL
+ ******************************************************************************/
+#define DDRCTRL_BASE			U(0x5A003000)
+
+/*******************************************************************************
+ * STM32MP1 DDRPHYC
+ ******************************************************************************/
+#define DDRPHYC_BASE			U(0x5A004000)
+
+/*******************************************************************************
+ * STM32MP1 I2C4
+ ******************************************************************************/
+#define I2C4_BASE			U(0x5C002000)
+
+#endif /* STM32MP1_DEF_H */
diff --git a/plat/st/stm32mp1/stm32mp1_dt.c b/plat/st/stm32mp1/stm32mp1_dt.c
new file mode 100644
index 0000000..bde968a
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_dt.c
@@ -0,0 +1,476 @@
+/*
+ * 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 <stm32_gpio.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_clkfunc.h>
+#include <stm32mp1_ddr.h>
+#include <stm32mp1_dt.h>
+#include <stm32mp1_ram.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 gets the pin settings from DT information.
+ * When analyze and parsing is done, set the GPIO registers.
+ * Return 0 on success, else return a negative FDT_ERR_xxx error code.
+ ******************************************************************************/
+static int dt_set_gpio_config(int node)
+{
+	const fdt32_t *cuint, *slewrate;
+	int len, pinctrl_node, pinctrl_subnode;
+	uint32_t i;
+	uint32_t speed = GPIO_SPEED_LOW;
+	uint32_t pull = GPIO_NO_PULL;
+
+	cuint = fdt_getprop(fdt, node, "pinmux", &len);
+	if (cuint == NULL) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node));
+	if (pinctrl_node < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	slewrate = fdt_getprop(fdt, node, "slew-rate", NULL);
+	if (slewrate != NULL) {
+		speed = fdt32_to_cpu(*slewrate);
+	}
+
+	if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) {
+		pull = GPIO_PULL_UP;
+	} else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) {
+		pull = GPIO_PULL_DOWN;
+	} else {
+		VERBOSE("No bias configured in node %d\n", node);
+	}
+
+	for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
+		uint32_t pincfg;
+		uint32_t bank;
+		uint32_t pin;
+		uint32_t mode;
+		uint32_t alternate = GPIO_ALTERNATE_0;
+
+		pincfg = fdt32_to_cpu(*cuint);
+		cuint++;
+
+		bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT;
+
+		pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT;
+
+		mode = pincfg & DT_GPIO_MODE_MASK;
+
+		switch (mode) {
+		case 0:
+			mode = GPIO_MODE_INPUT;
+			break;
+		case 1 ... 16:
+			alternate = mode - 1U;
+			mode = GPIO_MODE_ALTERNATE;
+			break;
+		case 17:
+			mode = GPIO_MODE_ANALOG;
+			break;
+		default:
+			mode = GPIO_MODE_OUTPUT;
+			break;
+		}
+
+		if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) {
+			mode |= GPIO_OPEN_DRAIN;
+		}
+
+		fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) {
+			uint32_t bank_offset;
+			const fdt32_t *cuint2;
+
+			if (fdt_getprop(fdt, pinctrl_subnode,
+					"gpio-controller", NULL) == NULL) {
+				continue;
+			}
+
+			cuint2 = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL);
+			if (cuint2 == NULL) {
+				continue;
+			}
+
+			if (bank == GPIO_BANK_Z) {
+				bank_offset = 0;
+			} else {
+				bank_offset = bank * STM32_GPIO_BANK_OFFSET;
+			}
+
+			if (fdt32_to_cpu(*cuint2) == bank_offset) {
+				int clk_id = fdt_get_clock_id(pinctrl_subnode);
+
+				if (clk_id < 0) {
+					return -FDT_ERR_NOTFOUND;
+				}
+
+				if (stm32mp1_clk_enable((unsigned long)clk_id) <
+				    0) {
+					return -FDT_ERR_BADVALUE;
+				}
+
+				break;
+			}
+		}
+
+		set_gpio(bank, pin, mode, speed, pull, alternate);
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ * 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;
+}
+
+/*******************************************************************************
+ * This function gets the pin settings from DT information.
+ * When analyze and parsing is done, set the GPIO registers.
+ * Returns 0 if success, and a negative value else.
+ ******************************************************************************/
+int dt_set_pinctrl_config(int node)
+{
+	const fdt32_t *cuint;
+	int lenp = 0;
+	uint32_t i;
+
+	if (!fdt_check_status(node)) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp);
+	if (cuint == NULL) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	for (i = 0; i < ((uint32_t)lenp / 4U); i++) {
+		int phandle_node, phandle_subnode;
+
+		phandle_node =
+			fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+		if (phandle_node < 0) {
+			return -FDT_ERR_NOTFOUND;
+		}
+
+		fdt_for_each_subnode(phandle_subnode, fdt, phandle_node) {
+			int ret = dt_set_gpio_config(phandle_subnode);
+
+			if (ret < 0) {
+				return ret;
+			}
+		}
+
+		cuint++;
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ * This function gets the stdout pin configuration information from the DT.
+ * And then calls the sub-function to treat it and set GPIO registers.
+ * Returns 0 if success, and a negative value else.
+ ******************************************************************************/
+int dt_set_stdout_pinctrl(void)
+{
+	int node;
+
+	node = dt_get_stdout_node_offset();
+	if (node < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	return dt_set_pinctrl_config(node);
+}
+
+/*******************************************************************************
+ * This function fills the generic information from a given node.
+ ******************************************************************************/
+void dt_fill_device_info(struct dt_node_info *info, int node)
+{
+	const fdt32_t *cuint;
+
+	cuint = fdt_getprop(fdt, node, "reg", NULL);
+	if (cuint != NULL) {
+		info->base = fdt32_to_cpu(*cuint);
+	} else {
+		info->base = 0;
+	}
+
+	cuint = fdt_getprop(fdt, node, "clocks", NULL);
+	if (cuint != NULL) {
+		cuint++;
+		info->clock = (int)fdt32_to_cpu(*cuint);
+	} else {
+		info->clock = -1;
+	}
+
+	cuint = fdt_getprop(fdt, node, "resets", NULL);
+	if (cuint != NULL) {
+		cuint++;
+		info->reset = (int)fdt32_to_cpu(*cuint);
+	} else {
+		info->reset = -1;
+	}
+
+	info->status = fdt_check_status(node);
+	info->sec_status = fdt_check_secure_status(node);
+}
+
+/*******************************************************************************
+ * This function retrieve the generic information from DT.
+ * Returns node if success, and a negative value else.
+ ******************************************************************************/
+int dt_get_node(struct dt_node_info *info, int offset, const char *compat)
+{
+	int node;
+
+	node = fdt_node_offset_by_compatible(fdt, offset, compat);
+	if (node < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	dt_fill_device_info(info, node);
+
+	return node;
+}
+
+/*******************************************************************************
+ * This function gets the UART instance info of stdout from the DT.
+ * Returns node if success, and a negative value else.
+ ******************************************************************************/
+int dt_get_stdout_uart_info(struct dt_node_info *info)
+{
+	int node;
+
+	node = dt_get_stdout_node_offset();
+	if (node < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	dt_fill_device_info(info, node);
+
+	return node;
+}
+
+/*******************************************************************************
+ * This function gets the stdout path node.
+ * It reads the value indicated inside the device tree.
+ * Returns node if success, and a negative value else.
+ ******************************************************************************/
+int dt_get_stdout_node_offset(void)
+{
+	int node;
+	const char *cchar;
+
+	node = fdt_path_offset(fdt, "/chosen");
+	if (node < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	cchar = fdt_getprop(fdt, node, "stdout-path", NULL);
+	if (cchar == NULL) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	node = -FDT_ERR_NOTFOUND;
+	if (strchr(cchar, (int)':') != NULL) {
+		const char *name;
+		char *str = (char *)cchar;
+		int len = 0;
+
+		while (strncmp(":", str, 1)) {
+			len++;
+			str++;
+		}
+
+		name = fdt_get_alias_namelen(fdt, cchar, len);
+
+		if (name != NULL) {
+			node = fdt_path_offset(fdt, name);
+		}
+	} else {
+		node = fdt_path_offset(fdt, cchar);
+	}
+
+	return node;
+}
+
+/*******************************************************************************
+ * This function gets DDR size information from the DT.
+ * Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else.
+ ******************************************************************************/
+uint32_t dt_get_ddr_size(void)
+{
+	int node;
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
+	if (node < 0) {
+		INFO("%s: Cannot read DDR node in DT\n", __func__);
+		return STM32MP1_DDR_SIZE_DFLT;
+	}
+
+	return fdt_read_uint32_default(node, "st,mem-size",
+				       STM32MP1_DDR_SIZE_DFLT);
+}
+
+/*******************************************************************************
+ * This function retrieves board model from DT
+ * Returns string taken from model node, NULL otherwise
+ ******************************************************************************/
+const char *dt_get_board_model(void)
+{
+	int node = fdt_path_offset(fdt, "/");
+
+	if (node < 0) {
+		return NULL;
+	}
+
+	return (const char *)fdt_getprop(fdt, node, "model", NULL);
+}
diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c
new file mode 100644
index 0000000..11eb0a3
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_gic.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <gicv2.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <utils.h>
+
+#include <stm32mp1_private.h>
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+static const interrupt_prop_t stm32mp1_interrupt_props[] = {
+	PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0),
+	PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
+};
+
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+
+static const gicv2_driver_data_t platform_gic_data = {
+	.gicd_base = STM32MP1_GICD_BASE,
+	.gicc_base = STM32MP1_GICC_BASE,
+	.interrupt_props = stm32mp1_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(stm32mp1_interrupt_props),
+	.target_masks = target_mask_array,
+	.target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+void stm32mp1_gic_init(void)
+{
+	gicv2_driver_init(&platform_gic_data);
+	gicv2_distif_init();
+
+	stm32mp1_gic_pcpu_init();
+}
+
+void stm32mp1_gic_pcpu_init(void)
+{
+	gicv2_pcpu_distif_init();
+	gicv2_set_pe_target_mask(plat_my_core_pos());
+	gicv2_cpuif_enable();
+}
diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S
new file mode 100644
index 0000000..b0ea0d8
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_helper.S
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <platform_def.h>
+#include <stm32_gpio.h>
+#include <stm32mp1_rcc.h>
+
+#define GPIO_BANK_G_ADDRESS	0x50008000
+#define GPIO_TX_PORT		11
+#define GPIO_TX_SHIFT		(GPIO_TX_PORT << 1)
+#define GPIO_TX_ALT_SHIFT	((GPIO_TX_PORT - GPIO_ALT_LOWER_LIMIT) << 2)
+#define STM32MP1_HSI_CLK	64000000
+
+	.globl	platform_mem_init
+	.globl	plat_report_exception
+	.globl	plat_get_my_entrypoint
+	.globl	plat_secondary_cold_boot_setup
+	.globl	plat_reset_handler
+	.globl	plat_is_my_cpu_primary
+	.globl	plat_my_core_pos
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_flush
+	.globl	plat_crash_console_putc
+	.globl	plat_panic_handler
+
+func platform_mem_init
+	/* Nothing to do, don't need to init SYSRAM */
+	bx	lr
+endfunc platform_mem_init
+
+func plat_report_exception
+	bx	lr
+endfunc plat_report_exception
+
+func plat_reset_handler
+	bx	lr
+endfunc plat_reset_handler
+
+	/* ------------------------------------------------------------------
+	 * unsigned long plat_get_my_entrypoint (void);
+	 *
+	 * Main job of this routine is to distinguish between a cold and warm
+	 * boot.
+	 *
+	 * Currently supports only cold boot
+	 * ------------------------------------------------------------------
+	 */
+func plat_get_my_entrypoint
+	mov	r0, #0
+	bx	lr
+endfunc plat_get_my_entrypoint
+
+	/* ---------------------------------------------
+	 * void plat_secondary_cold_boot_setup (void);
+	 *
+	 * Cold-booting secondary CPUs is not supported.
+	 * ---------------------------------------------
+	 */
+func plat_secondary_cold_boot_setup
+	b	.
+endfunc plat_secondary_cold_boot_setup
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_is_my_cpu_primary (void);
+	 *
+	 * Find out whether the current cpu is the primary cpu.
+	 * -----------------------------------------------------
+	 */
+func plat_is_my_cpu_primary
+	ldcopr	r0, MPIDR
+	ldr	r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+	and	r0, r1
+	cmp	r0, #STM32MP1_PRIMARY_CPU
+	moveq	r0, #1
+	movne	r0, #0
+	bx	lr
+endfunc plat_is_my_cpu_primary
+
+	/* -------------------------------------------
+	 *  int plat_stm32mp1_get_core_pos(int mpidr);
+	 *
+	 *  Return CorePos = (ClusterId * 4) + CoreId
+	 * -------------------------------------------
+	 */
+func plat_stm32mp1_get_core_pos
+	and	r1, r0, #MPIDR_CPU_MASK
+	and	r0, r0, #MPIDR_CLUSTER_MASK
+	add	r0, r1, r0, LSR #6
+	bx	lr
+endfunc plat_stm32mp1_get_core_pos
+
+	/* ------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 * ------------------------------------
+	 */
+func plat_my_core_pos
+	ldcopr	r0, MPIDR
+	b	plat_stm32mp1_get_core_pos
+endfunc plat_my_core_pos
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 *
+	 * Initialize the crash console without a C Runtime stack.
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	/* Enable GPIOs for UART4 TX */
+	ldr	r1, =(RCC_BASE + RCC_MP_AHB4ENSETR)
+	ldr	r2, [r1]
+	/* Configure GPIO G11 */
+	orr	r2, r2, #RCC_MP_AHB4ENSETR_GPIOGEN
+	str	r2, [r1]
+	ldr	r1, =GPIO_BANK_G_ADDRESS
+	/* Set GPIO mode alternate */
+	ldr	r2, [r1, #GPIO_MODE_OFFSET]
+	bic	r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT)
+	orr	r2, r2, #(GPIO_MODE_ALTERNATE << GPIO_TX_SHIFT)
+	str	r2, [r1, #GPIO_MODE_OFFSET]
+	/* Set GPIO speed low */
+	ldr	r2, [r1, #GPIO_SPEED_OFFSET]
+	bic	r2, r2, #(GPIO_SPEED_MASK << GPIO_TX_SHIFT)
+	str	r2, [r1, #GPIO_SPEED_OFFSET]
+	/* Set no-pull */
+	ldr	r2, [r1, #GPIO_PUPD_OFFSET]
+	bic	r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT)
+	str	r2, [r1, #GPIO_PUPD_OFFSET]
+	/* Set alternate AF6 */
+	ldr	r2, [r1, #GPIO_AFRH_OFFSET]
+	bic	r2, r2, #(GPIO_ALTERNATE_MASK << GPIO_TX_ALT_SHIFT)
+	orr	r2, r2, #(GPIO_ALTERNATE_6 << GPIO_TX_ALT_SHIFT)
+	str	r2, [r1, #GPIO_AFRH_OFFSET]
+
+	/* Enable UART clock, with HSI source */
+	ldr	r1, =(RCC_BASE + RCC_UART24CKSELR)
+	mov	r2, #RCC_UART24CKSELR_HSI
+	str	r2, [r1]
+	ldr	r1, =(RCC_BASE + RCC_MP_APB1ENSETR)
+	ldr	r2, [r1]
+	orr	r2, r2, #RCC_MP_APB1ENSETR_UART4EN
+	str	r2, [r1]
+
+	ldr	r0, =STM32MP1_DEBUG_USART_BASE
+	ldr	r1, =STM32MP1_HSI_CLK
+	ldr	r2, =STM32MP1_UART_BAUDRATE
+	b	console_core_init
+endfunc plat_crash_console_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush(void)
+	 *
+	 * Flush the crash console without a C Runtime stack.
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	ldr	r1, =STM32MP1_DEBUG_USART_BASE
+	b	console_core_flush
+endfunc plat_crash_console_flush
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(int c)
+	 *
+	 * Print a character on the crash console without a C Runtime stack.
+	 * Clobber list : r1 - r3
+	 *
+	 * In case of bootloading through uart, we keep console crash as this.
+	 * Characters could be sent to the programmer, but will be ignored.
+	 * No specific code in that case.
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_putc
+	ldr	r1, =STM32MP1_DEBUG_USART_BASE
+	b	console_core_putc
+endfunc plat_crash_console_putc
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
new file mode 100644
index 0000000..e24af0e
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <errno.h>
+#include <gic_common.h>
+#include <gicv2.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <platform.h>
+#include <psci.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_rcc.h>
+
+static uint32_t stm32_sec_entrypoint;
+static uint32_t cntfrq_core0;
+
+#define SEND_SECURE_IT_TO_CORE_1	0x20000U
+
+/*******************************************************************************
+ * STM32MP1 handler called when a CPU is about to enter standby.
+ * call by core 1 to enter in wfi
+ ******************************************************************************/
+static void stm32_cpu_standby(plat_local_state_t cpu_state)
+{
+	uint32_t interrupt = GIC_SPURIOUS_INTERRUPT;
+
+	assert(cpu_state == ARM_LOCAL_STATE_RET);
+
+	/*
+	 * Enter standby state
+	 * dsb is good practice before using wfi to enter low power states
+	 */
+	dsb();
+	while (interrupt == GIC_SPURIOUS_INTERRUPT) {
+		wfi();
+
+		/* Acknoledge IT */
+		interrupt = gicv2_acknowledge_interrupt();
+		/* If Interrupt == 1022 it will be acknowledged by non secure */
+		if ((interrupt != PENDING_G1_INTID) &&
+		    (interrupt != GIC_SPURIOUS_INTERRUPT)) {
+			gicv2_end_of_interrupt(interrupt);
+		}
+	}
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ * call by core  0 to activate core 1
+ ******************************************************************************/
+static int stm32_pwr_domain_on(u_register_t mpidr)
+{
+	unsigned long current_cpu_mpidr = read_mpidr_el1();
+	uint32_t tamp_clk_off = 0;
+	uint32_t bkpr_core1_addr =
+		tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
+	uint32_t bkpr_core1_magic =
+		tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
+
+	if (mpidr == current_cpu_mpidr) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	if ((stm32_sec_entrypoint < STM32MP1_SRAM_BASE) ||
+	    (stm32_sec_entrypoint > (STM32MP1_SRAM_BASE +
+				     (STM32MP1_SRAM_SIZE - 1)))) {
+		return PSCI_E_INVALID_ADDRESS;
+	}
+
+	if (!stm32mp1_clk_is_enabled(RTCAPB)) {
+		tamp_clk_off = 1;
+		if (stm32mp1_clk_enable(RTCAPB) != 0) {
+			panic();
+		}
+	}
+
+	cntfrq_core0 = read_cntfrq_el0();
+
+	/* Write entrypoint in backup RAM register */
+	mmio_write_32(bkpr_core1_addr, stm32_sec_entrypoint);
+
+	/* Write magic number in backup register */
+	mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER);
+
+	if (tamp_clk_off != 0U) {
+		if (stm32mp1_clk_disable(RTCAPB) != 0) {
+			panic();
+		}
+	}
+
+	/* Generate an IT to core 1 */
+	mmio_write_32(STM32MP1_GICD_BASE + GICD_SGIR,
+		      SEND_SECURE_IT_TO_CORE_1 | ARM_IRQ_SEC_SGI_0);
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void stm32_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	/* Nothing to do */
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+	/* Nothing to do, power domain is not disabled */
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ * call by core 1 just after wake up
+ ******************************************************************************/
+static void stm32_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	stm32mp1_gic_pcpu_init();
+
+	write_cntfrq_el0(cntfrq_core0);
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ ******************************************************************************/
+static void stm32_pwr_domain_suspend_finish(const psci_power_state_t
+					    *target_state)
+{
+	/* Nothing to do, power domain is not disabled */
+}
+
+static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t
+						  *target_state)
+{
+	ERROR("stm32mpu1 Power Down WFI: operation not handled.\n");
+	panic();
+}
+
+static void __dead2 stm32_system_off(void)
+{
+	ERROR("stm32mpu1 System Off: operation not handled.\n");
+	panic();
+}
+
+static void __dead2 stm32_system_reset(void)
+{
+	mmio_setbits_32(RCC_BASE + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPSYSRST);
+
+	/* Loop in case system reset is not immediately caught */
+	for ( ; ; ) {
+		;
+	}
+}
+
+static int stm32_validate_power_state(unsigned int power_state,
+				      psci_power_state_t *req_state)
+{
+	int pstate = psci_get_pstate_type(power_state);
+
+	if (pstate != 0) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	if (psci_get_pstate_pwrlvl(power_state)) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	if (psci_get_pstate_id(power_state)) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	req_state->pwr_domain_state[0] = ARM_LOCAL_STATE_RET;
+	req_state->pwr_domain_state[1] = ARM_LOCAL_STATE_RUN;
+
+	return PSCI_E_SUCCESS;
+}
+
+static int stm32_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+	/* The non-secure entry point must be in DDR */
+	if (entrypoint < STM32MP1_DDR_BASE) {
+		return PSCI_E_INVALID_ADDRESS;
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
+static int stm32_node_hw_state(u_register_t target_cpu,
+			       unsigned int power_level)
+{
+	/*
+	 * The format of 'power_level' is implementation-defined, but 0 must
+	 * mean a CPU. Only allow level 0.
+	 */
+	if (power_level != MPIDR_AFFLVL0) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	/*
+	 * From psci view the CPU 0 is always ON,
+	 * CPU 1 can be SUSPEND or RUNNING.
+	 * Therefore do not manage POWER OFF state and always return HW_ON.
+	 */
+
+	return (int)HW_ON;
+}
+
+/*******************************************************************************
+ * Export the platform handlers. The ARM Standard platform layer will take care
+ * of registering the handlers with PSCI.
+ ******************************************************************************/
+static const plat_psci_ops_t stm32_psci_ops = {
+	.cpu_standby = stm32_cpu_standby,
+	.pwr_domain_on = stm32_pwr_domain_on,
+	.pwr_domain_off = stm32_pwr_domain_off,
+	.pwr_domain_suspend = stm32_pwr_domain_suspend,
+	.pwr_domain_on_finish = stm32_pwr_domain_on_finish,
+	.pwr_domain_suspend_finish = stm32_pwr_domain_suspend_finish,
+	.pwr_domain_pwr_down_wfi = stm32_pwr_domain_pwr_down_wfi,
+	.system_off = stm32_system_off,
+	.system_reset = stm32_system_reset,
+	.validate_power_state = stm32_validate_power_state,
+	.validate_ns_entrypoint = stm32_validate_ns_entrypoint,
+	.get_node_hw_state = stm32_node_hw_state
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	stm32_sec_entrypoint = sec_entrypoint;
+	*psci_ops = &stm32_psci_ops;
+
+	return 0;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
new file mode 100644
index 0000000..e783c14
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_security.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <mmio.h>
+#include <stdint.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_dt.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_rcc.h>
+#include <tzc400.h>
+#include "platform_def.h"
+
+/*******************************************************************************
+ * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access
+ * and allow Non-Secure masters full access.
+ ******************************************************************************/
+static void init_tzc400(void)
+{
+	unsigned long long region_base, region_top;
+	unsigned long long ddr_base = STM32MP1_DDR_BASE;
+	unsigned long long ddr_size = (unsigned long long)dt_get_ddr_size();
+
+	tzc400_init(STM32MP1_TZC_BASE);
+
+	tzc400_disable_filters();
+
+	/* Region 1 set to cover all DRAM at 0xC000_0000. Apply the
+	 * same configuration to all filters in the TZC.
+	 */
+	region_base = ddr_base;
+	region_top = ddr_base + (ddr_size - 1U);
+	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
+			region_base,
+			region_top,
+			TZC_REGION_S_RDWR,
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) |
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) |
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) |
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) |
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) |
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) |
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) |
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) |
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID));
+
+	/* Raise an exception if a NS device tries to access secure memory */
+	tzc400_set_action(TZC_ACTION_ERR);
+
+	tzc400_enable_filters();
+}
+
+/*******************************************************************************
+ * Initialize the TrustZone Controller.
+ * Early initialization create only one region with full access to secure.
+ * This setting is used before and during DDR initialization.
+ ******************************************************************************/
+static void early_init_tzc400(void)
+{
+	uint32_t rstsr, rst_standby;
+
+	rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR);
+
+	/* No warning if return from (C)STANDBY */
+	rst_standby = rstsr &
+		(RCC_MP_RSTSCLRR_STDBYRSTF | RCC_MP_RSTSCLRR_CSTDBYRSTF);
+
+	if (stm32mp1_clk_is_enabled(TZC1) && (rst_standby == 0U)) {
+		WARN("TZC400 port 1 clock already enable\n");
+	}
+
+	if (stm32mp1_clk_is_enabled(TZC2) && (rst_standby == 0U)) {
+		WARN("TZC400 port 2 clock already enable\n");
+	}
+
+	if (stm32mp1_clk_enable(TZC1) != 0) {
+		ERROR("Cannot enable TZC1 clock\n");
+		panic();
+	}
+	if (stm32mp1_clk_enable(TZC2) != 0) {
+		ERROR("Cannot enable TZC2 clock\n");
+		panic();
+	}
+
+	tzc400_init(STM32MP1_TZC_BASE);
+
+	tzc400_disable_filters();
+
+	/*
+	 * Region 1 set to cover Non-Secure DRAM at 0x8000_0000. Apply the
+	 * same configuration to all filters in the TZC.
+	 */
+	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
+				STM32MP1_DDR_BASE,
+				STM32MP1_DDR_BASE +
+				(STM32MP1_DDR_MAX_SIZE - 1U),
+				TZC_REGION_S_RDWR,
+				TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID));
+
+	/* Raise an exception if a NS device tries to access secure memory */
+	tzc400_set_action(TZC_ACTION_ERR);
+
+	tzc400_enable_filters();
+}
+
+/*******************************************************************************
+ * Initialize the secure environment. At this moment only the TrustZone
+ * Controller is initialized.
+ ******************************************************************************/
+void stm32mp1_arch_security_setup(void)
+{
+	early_init_tzc400();
+}
+
+/*******************************************************************************
+ * Initialize the secure environment. At this moment only the TrustZone
+ * Controller is initialized.
+ ******************************************************************************/
+void stm32mp1_security_setup(void)
+{
+	init_tzc400();
+}
diff --git a/plat/st/stm32mp1/stm32mp1_stack_protector.c b/plat/st/stm32mp1/stm32mp1_stack_protector.c
new file mode 100644
index 0000000..c681300
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_stack_protector.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <platform.h>
+#include <stdint.h>
+
+#define RANDOM_CANARY_VALUE	2144346116U
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+	/*
+	 * Ideally, a random number should be returned instead of the
+	 * combination of a timer's value and a compile-time constant.
+	 */
+	return RANDOM_CANARY_VALUE ^ (u_register_t)read_cntpct_el0();
+}
+
diff --git a/plat/st/stm32mp1/stm32mp1_topology.c b/plat/st/stm32mp1/stm32mp1_topology.c
new file mode 100644
index 0000000..405aa33
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_topology.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+#include <platform.h>
+#include <psci.h>
+
+/* 1 cluster, all cores into */
+static const unsigned char stm32mp1_power_domain_tree_desc[] = {
+	PLATFORM_CLUSTER_COUNT,
+	PLATFORM_CORE_COUNT,
+};
+
+/* This function returns the platform topology */
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return stm32mp1_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster_id, cpu_id;
+	u_register_t mpidr_copy = mpidr;
+
+	mpidr_copy &= MPIDR_AFFINITY_MASK;
+
+	if ((mpidr_copy & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) {
+		return -1;
+	}
+
+	cluster_id = (mpidr_copy >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	cpu_id = (mpidr_copy >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+	if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+		return -1;
+	}
+
+	/*
+	 * Validate cpu_id by checking whether it represents a CPU in one
+	 * of the two clusters present on the platform.
+	 */
+	if (cpu_id >= PLATFORM_CORE_COUNT) {
+		return -1;
+	}
+
+	return (int)cpu_id;
+}
diff --git a/tools/stm32image/Makefile b/tools/stm32image/Makefile
new file mode 100644
index 0000000..80dfbec
--- /dev/null
+++ b/tools/stm32image/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MAKE_HELPERS_DIRECTORY := ../../make_helpers/
+include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
+include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+
+PROJECT := stm32image${BIN_EXT}
+OBJECTS := stm32image.o
+V := 0
+
+override CPPFLAGS += -D_GNU_SOURCE
+CFLAGS := -Wall -Werror -pedantic -std=c99
+ifeq (${DEBUG},1)
+  CFLAGS += -g -O0 -DDEBUG
+else
+  CFLAGS += -O2
+endif
+
+ifeq (${V},0)
+  Q := @
+else
+  Q :=
+endif
+
+CC := gcc
+
+.PHONY: all clean distclean
+
+all: ${PROJECT}
+
+${PROJECT}: ${OBJECTS} Makefile
+	@echo "  LD      $@"
+	${Q}${CC} ${OBJECTS} -o $@
+	@${ECHO_BLANK_LINE}
+	@echo "Built $@ successfully"
+	@${ECHO_BLANK_LINE}
+
+%.o: %.c %.h Makefile
+	@echo "  CC      $<"
+	${Q}${CC} -c ${CFLAGS} $< -o $@
+
+clean:
+	$(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
+
+distclean: clean
diff --git a/tools/stm32image/stm32image.c b/tools/stm32image/stm32image.c
new file mode 100644
index 0000000..2607928
--- /dev/null
+++ b/tools/stm32image/stm32image.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm/byteorder.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* Magic = 'S' 'T' 'M' 0x32 */
+#define HEADER_MAGIC		__be32_to_cpu(0x53544D32)
+#define VER_MAJOR		2
+#define VER_MINOR		1
+#define VER_VARIANT		0
+#define HEADER_VERSION_V1	0x1
+#define TF_BINARY_TYPE		0x0
+
+/* Default option : bit0 => no signature */
+#define HEADER_DEFAULT_OPTION	(__cpu_to_le32(0x00000001))
+
+struct stm32_header {
+	uint32_t magic_number;
+	uint8_t image_signature[64];
+	uint32_t image_checksum;
+	uint8_t  header_version[4];
+	uint32_t image_length;
+	uint32_t image_entry_point;
+	uint32_t reserved1;
+	uint32_t load_address;
+	uint32_t reserved2;
+	uint32_t version_number;
+	uint32_t option_flags;
+	uint32_t ecdsa_algorithm;
+	uint8_t ecdsa_public_key[64];
+	uint8_t padding[83];
+	uint8_t binary_type;
+};
+
+static struct stm32_header stm32image_header;
+
+static void stm32image_default_header(struct stm32_header *ptr)
+{
+	if (!ptr) {
+		return;
+	}
+
+	ptr->magic_number = HEADER_MAGIC;
+	ptr->header_version[VER_MAJOR] = HEADER_VERSION_V1;
+	ptr->option_flags = HEADER_DEFAULT_OPTION;
+	ptr->ecdsa_algorithm = 1;
+	ptr->version_number = 0;
+	ptr->binary_type = TF_BINARY_TYPE;
+}
+
+static uint32_t stm32image_checksum(void *start, uint32_t len)
+{
+	uint32_t csum = 0;
+	uint32_t hdr_len = sizeof(struct stm32_header);
+	uint8_t *p;
+
+	if (len < hdr_len) {
+		return 0;
+	}
+
+	p = (unsigned char *)start + hdr_len;
+	len -= hdr_len;
+
+	while (len > 0) {
+		csum += *p;
+		p++;
+		len--;
+	}
+
+	return csum;
+}
+
+static void stm32image_print_header(const void *ptr)
+{
+	struct stm32_header *stm32hdr = (struct stm32_header *)ptr;
+
+	printf("Image Type   : ST Microelectronics STM32 V%d.%d\n",
+	       stm32hdr->header_version[VER_MAJOR],
+	       stm32hdr->header_version[VER_MINOR]);
+	printf("Image Size   : %lu bytes\n",
+	       (unsigned long)__le32_to_cpu(stm32hdr->image_length));
+	printf("Image Load   : 0x%08x\n",
+	       __le32_to_cpu(stm32hdr->load_address));
+	printf("Entry Point  : 0x%08x\n",
+	       __le32_to_cpu(stm32hdr->image_entry_point));
+	printf("Checksum     : 0x%08x\n",
+	       __le32_to_cpu(stm32hdr->image_checksum));
+	printf("Option     : 0x%08x\n",
+	       __le32_to_cpu(stm32hdr->option_flags));
+	printf("Version	   : 0x%08x\n",
+	       __le32_to_cpu(stm32hdr->version_number));
+}
+
+static void stm32image_set_header(void *ptr, struct stat *sbuf, int ifd,
+				  uint32_t loadaddr, uint32_t ep, uint32_t ver)
+{
+	struct stm32_header *stm32hdr = (struct stm32_header *)ptr;
+
+	stm32image_default_header(stm32hdr);
+
+	stm32hdr->load_address = __cpu_to_le32(loadaddr);
+	stm32hdr->image_entry_point = __cpu_to_le32(ep);
+	stm32hdr->image_length = __cpu_to_le32((uint32_t)sbuf->st_size -
+					     sizeof(struct stm32_header));
+	stm32hdr->image_checksum = stm32image_checksum(ptr, sbuf->st_size);
+	stm32hdr->version_number = __cpu_to_le32(ver);
+}
+
+static int stm32image_create_header_file(char *srcname, char *destname,
+					 uint32_t loadaddr, uint32_t entry,
+					 uint32_t version)
+{
+	int src_fd, dest_fd;
+	struct stat sbuf;
+	unsigned char *ptr;
+
+	dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666);
+	if (dest_fd == -1) {
+		fprintf(stderr, "Can't open %s: %s\n", destname,
+			strerror(errno));
+		return -1;
+	}
+
+	src_fd = open(srcname, O_RDONLY);
+	if (src_fd == -1) {
+		fprintf(stderr, "Can't open %s: %s\n", srcname,
+			strerror(errno));
+		return -1;
+	}
+
+	if (fstat(src_fd, &sbuf) < 0) {
+		return -1;
+	}
+
+	ptr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, src_fd, 0);
+	if (ptr == MAP_FAILED) {
+		fprintf(stderr, "Can't read %s\n", srcname);
+		return -1;
+	}
+
+	memset(&stm32image_header, 0, sizeof(struct stm32_header));
+
+	if (write(dest_fd, &stm32image_header, sizeof(struct stm32_header)) !=
+	    sizeof(struct stm32_header)) {
+		fprintf(stderr, "Write error %s: %s\n", destname,
+			strerror(errno));
+		return -1;
+	}
+
+	if (write(dest_fd, ptr, sbuf.st_size) != sbuf.st_size) {
+		fprintf(stderr, "Write error on %s: %s\n", destname,
+			strerror(errno));
+		return -1;
+	}
+
+	munmap((void *)ptr, sbuf.st_size);
+	close(src_fd);
+
+	if (fstat(dest_fd, &sbuf) < 0) {
+		return -1;
+	}
+
+	ptr = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+		   dest_fd, 0);
+
+	if (ptr == MAP_FAILED) {
+		fprintf(stderr, "Can't read %s\n", srcname);
+		return -1;
+	}
+
+	stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr, entry, version);
+
+	stm32image_print_header(ptr);
+
+	munmap((void *)ptr, sbuf.st_size);
+	close(dest_fd);
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int opt, loadaddr = -1, entry = -1, err = 0, version = 0;
+	char *dest = NULL, *src = NULL;
+
+	while ((opt = getopt(argc, argv, ":s:d:l:e:v:")) != -1) {
+		switch (opt) {
+		case 's':
+			src = optarg;
+			break;
+		case 'd':
+			dest = optarg;
+			break;
+		case 'l':
+			loadaddr = strtol(optarg, NULL, 16);
+			break;
+		case 'e':
+			entry = strtol(optarg, NULL, 16);
+			break;
+		case 'v':
+			version = strtol(optarg, NULL, 10);
+			break;
+		default:
+			fprintf(stderr,
+				"Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point]\n",
+					argv[0]);
+			return -1;
+		}
+	}
+
+	if (!src) {
+		fprintf(stderr, "Missing -s option\n");
+		return -1;
+	}
+
+	if (!dest) {
+		fprintf(stderr, "Missing -d option\n");
+		return -1;
+	}
+
+	if (loadaddr == -1) {
+		fprintf(stderr, "Missing -l option\n");
+		return -1;
+	}
+
+	if (entry == -1) {
+		fprintf(stderr, "Missing -e option\n");
+		return -1;
+	}
+
+	err = stm32image_create_header_file(src, dest, loadaddr,
+					    entry, version);
+
+	return err;
+}