diff --git a/plat/renesas/rcar/bl2_plat_mem_params_desc.c b/plat/renesas/rcar/bl2_plat_mem_params_desc.c
index 112a1edcdddc36d875c6f16126f52a3bc933ab73..728eac622833a815a9c128b07abfc2e1f5b86dd6 100644
--- a/plat/renesas/rcar/bl2_plat_mem_params_desc.c
+++ b/plat/renesas/rcar/bl2_plat_mem_params_desc.c
@@ -8,6 +8,7 @@
 #include <desc_image_load.h>
 #include <platform.h>
 #include <platform_def.h>
+#include <xlat_tables_defs.h>
 
 #if (RCAR_BL33_EXECUTION_EL != 0) && (RCAR_BL33_EXECUTION_EL != 1)
 #error
@@ -19,6 +20,8 @@
 #define BL33_MODE MODE_EL2
 #endif
 
+extern uint64_t fdt_blob[PAGE_SIZE_4KB / sizeof(uint64_t)];
+
 static bl_mem_params_node_t bl2_mem_params_descs[] = {
 	{
 		.image_id = BL31_IMAGE_ID,
@@ -69,6 +72,7 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
 #ifdef RCAR_BL33_ARG0
 		.ep_info.args.arg0 = RCAR_BL33_ARG0,
 #endif
+		.ep_info.args.arg3 = (uintptr_t)fdt_blob,
 		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
 			image_info_t, 0),
 		.image_info.image_max_size =
diff --git a/plat/renesas/rcar/bl2_plat_setup.c b/plat/renesas/rcar/bl2_plat_setup.c
index 4f3329fdf6930716ed0e64729b77f9bd70f703f6..7567813ca69b8fbd95433f64b1f43597d01c6d9c 100644
--- a/plat/renesas/rcar/bl2_plat_setup.c
+++ b/plat/renesas/rcar/bl2_plat_setup.c
@@ -10,10 +10,12 @@
 #include <bl1.h>
 #include <console.h>
 #include <debug.h>
+#include <libfdt.h>
 #include <mmio.h>
 #include <platform.h>
 #include <platform_def.h>
 #include <string.h>
+#include <xlat_tables_defs.h>
 
 #include "avs_driver.h"
 #include "boot_init_dram.h"
@@ -85,6 +87,32 @@ CASSERT((PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t) + 0x100)
 
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
 
+/* FDT with DRAM configuration */
+uint64_t fdt_blob[PAGE_SIZE_4KB / sizeof(uint64_t)];
+static void *fdt = (void *)fdt_blob;
+
+static void unsigned_num_print(unsigned long long int unum, unsigned int radix,
+				char *string)
+{
+	/* Just need enough space to store 64 bit decimal integer */
+	char num_buf[20];
+	int i = 0;
+	unsigned int rem;
+
+	do {
+		rem = unum % radix;
+		if (rem < 0xa)
+			num_buf[i] = '0' + rem;
+		else
+			num_buf[i] = 'a' + (rem - 0xa);
+		i++;
+		unum /= radix;
+	} while (unum > 0U);
+
+	while (--i >= 0)
+		*string++ = num_buf[i];
+}
+
 #if (RCAR_LOSSY_ENABLE == 1)
 typedef struct bl2_lossy_info {
 	uint32_t magic;
@@ -92,13 +120,75 @@ typedef struct bl2_lossy_info {
 	uint32_t b0;
 } bl2_lossy_info_t;
 
+static void bl2_lossy_gen_fdt(uint32_t no, uint64_t start_addr,
+			      uint64_t end_addr, uint32_t format,
+			      uint32_t enable, int fcnlnode)
+{
+	const uint64_t fcnlsize = cpu_to_fdt64(end_addr - start_addr);
+	char nodename[40] = { 0 };
+	int ret, node;
+
+	/* Ignore undefined addresses */
+	if (start_addr == 0 && end_addr == 0)
+		return;
+
+	snprintf(nodename, sizeof(nodename), "lossy-decompression@");
+	unsigned_num_print(start_addr, 16, nodename + strlen(nodename));
+
+	node = ret = fdt_add_subnode(fdt, fcnlnode, nodename);
+	if (ret < 0) {
+		NOTICE("BL2: Cannot create FCNL node (ret=%i)\n", ret);
+		panic();
+	}
+
+	ret = fdt_setprop_string(fdt, node, "compatible",
+				 "renesas,lossy-decompression");
+	if (ret < 0) {
+		NOTICE("BL2: Cannot add FCNL compat string (ret=%i)\n", ret);
+		panic();
+	}
+
+	ret = fdt_appendprop_string(fdt, node, "compatible",
+				    "shared-dma-pool");
+	if (ret < 0) {
+		NOTICE("BL2: Cannot append FCNL compat string (ret=%i)\n", ret);
+		panic();
+	}
+
+	ret = fdt_setprop_u64(fdt, node, "reg", start_addr);
+	if (ret < 0) {
+		NOTICE("BL2: Cannot add FCNL reg prop (ret=%i)\n", ret);
+		panic();
+	}
+
+	ret = fdt_appendprop(fdt, node, "reg", &fcnlsize, sizeof(fcnlsize));
+	if (ret < 0) {
+		NOTICE("BL2: Cannot append FCNL reg size prop (ret=%i)\n", ret);
+		panic();
+	}
+
+	ret = fdt_setprop(fdt, node, "no-map", NULL, 0);
+	if (ret < 0) {
+		NOTICE("BL2: Cannot add FCNL no-map prop (ret=%i)\n", ret);
+		panic();
+	}
+
+	ret = fdt_setprop_u32(fdt, node, "renesas,formats", format);
+	if (ret < 0) {
+		NOTICE("BL2: Cannot add FCNL formats prop (ret=%i)\n", ret);
+		panic();
+	}
+}
+
 static void bl2_lossy_setting(uint32_t no, uint64_t start_addr,
 			      uint64_t end_addr, uint32_t format,
-			      uint32_t enable)
+			      uint32_t enable, int fcnlnode)
 {
 	bl2_lossy_info_t info;
 	uint32_t reg;
 
+	bl2_lossy_gen_fdt(no, start_addr, end_addr, format, enable, fcnlnode);
+
 	reg = format | (start_addr >> 20);
 	mmio_write_32(AXI_DCMPAREACRA0 + 0x8 * no, reg);
 	mmio_write_32(AXI_DCMPAREACRB0 + 0x8 * no, end_addr >> 20);
@@ -300,11 +390,207 @@ meminfo_t *bl2_plat_sec_mem_layout(void)
 	return &bl2_tzram_layout;
 }
 
+static void bl2_populate_compatible_string(void *fdt)
+{
+	uint32_t board_type;
+	uint32_t board_rev;
+	uint32_t reg;
+	int ret;
+
+	/* Populate compatible string */
+	rcar_get_board_type(&board_type, &board_rev);
+	switch (board_type) {
+	case BOARD_SALVATOR_X:
+		ret = fdt_setprop_string(fdt, 0, "compatible",
+					 "renesas,salvator-x");
+		break;
+	case BOARD_SALVATOR_XS:
+		ret = fdt_setprop_string(fdt, 0, "compatible",
+					 "renesas,salvator-xs");
+		break;
+	case BOARD_STARTER_KIT:
+		ret = fdt_setprop_string(fdt, 0, "compatible",
+					 "renesas,m3ulcb");
+		break;
+	case BOARD_STARTER_KIT_PRE:
+		ret = fdt_setprop_string(fdt, 0, "compatible",
+					 "renesas,h3ulcb");
+		break;
+	case BOARD_EBISU:
+	case BOARD_EBISU_4D:
+		ret = fdt_setprop_string(fdt, 0, "compatible",
+					 "renesas,ebisu");
+		break;
+	default:
+		NOTICE("BL2: Cannot set compatible string, board unsupported\n");
+		panic();
+	}
+
+	if (ret < 0) {
+		NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret);
+		panic();
+	}
+
+	reg = mmio_read_32(RCAR_PRR);
+	switch (reg & RCAR_PRODUCT_MASK) {
+	case RCAR_PRODUCT_H3:
+		ret = fdt_appendprop_string(fdt, 0, "compatible",
+					    "renesas,r8a7795");
+		break;
+	case RCAR_PRODUCT_M3:
+		ret = fdt_appendprop_string(fdt, 0, "compatible",
+					    "renesas,r8a7796");
+		break;
+	case RCAR_PRODUCT_M3N:
+		ret = fdt_appendprop_string(fdt, 0, "compatible",
+					    "renesas,r8a77965");
+		break;
+	case RCAR_PRODUCT_E3:
+		ret = fdt_appendprop_string(fdt, 0, "compatible",
+					    "renesas,r8a77990");
+		break;
+	default:
+		NOTICE("BL2: Cannot set compatible string, SoC unsupported\n");
+		panic();
+	}
+
+	if (ret < 0) {
+		NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret);
+		panic();
+	}
+}
+
+static void bl2_advertise_dram_entries(uint64_t dram_config[8])
+{
+	char nodename[32] = { 0 };
+	uint64_t start, size;
+	uint64_t fdtsize;
+	int ret, node, chan;
+
+	for (chan = 0; chan < 4; chan++) {
+		start = dram_config[2 * chan];
+		size = dram_config[2 * chan + 1];
+		if (!size)
+			continue;
+
+		NOTICE("BL2: CH%d: %llx - %llx, %lld GiB\n",
+			chan, start, start + size - 1, size >> 30);
+	}
+
+	/*
+	 * We add the DT nodes in reverse order here. The fdt_add_subnode()
+	 * adds the DT node before the first existing DT node, so we have
+	 * to add them in reverse order to get nodes sorted by address in
+	 * the resulting DT.
+	 */
+	for (chan = 3; chan >= 0; chan--) {
+		start = dram_config[2 * chan];
+		size = dram_config[2 * chan + 1];
+		if (!size)
+			continue;
+
+		/*
+		 * Channel 0 is mapped in 32bit space and the first
+		 * 128 MiB are reserved
+		 */
+		if (chan == 0) {
+			start = 0x48000000;
+			size -= 0x8000000;
+		}
+
+		fdtsize = cpu_to_fdt64(size);
+
+		snprintf(nodename, sizeof(nodename), "memory@");
+		unsigned_num_print(start, 16, nodename + strlen(nodename));
+		node = ret = fdt_add_subnode(fdt, 0, nodename);
+		if (ret < 0)
+			goto err;
+
+		ret = fdt_setprop_string(fdt, node, "device_type", "memory");
+		if (ret < 0)
+			goto err;
+
+		ret = fdt_setprop_u64(fdt, node, "reg", start);
+		if (ret < 0)
+			goto err;
+
+		ret = fdt_appendprop(fdt, node, "reg", &fdtsize,
+				     sizeof(fdtsize));
+		if (ret < 0)
+			goto err;
+	}
+
+	return;
+err:
+	NOTICE("BL2: Cannot add memory node to FDT (ret=%i)\n", ret);
+	panic();
+}
+
+static void bl2_advertise_dram_size(uint32_t product)
+{
+	uint64_t dram_config[8] = {
+		[0] = 0x400000000ULL,
+		[2] = 0x500000000ULL,
+		[4] = 0x600000000ULL,
+		[6] = 0x700000000ULL,
+	};
+
+	switch (product) {
+	case RCAR_PRODUCT_H3:
+#if (RCAR_DRAM_LPDDR4_MEMCONF == 0)
+		/* 4GB(1GBx4) */
+		dram_config[1] = 0x40000000ULL;
+		dram_config[3] = 0x40000000ULL;
+		dram_config[5] = 0x40000000ULL;
+		dram_config[7] = 0x40000000ULL;
+#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && \
+      (RCAR_DRAM_CHANNEL        == 5) && \
+      (RCAR_DRAM_SPLIT          == 2)
+		/* 4GB(2GBx2 2ch split) */
+		dram_config[1] = 0x80000000ULL;
+		dram_config[3] = 0x80000000ULL;
+#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && (RCAR_DRAM_CHANNEL == 15)
+		/* 8GB(2GBx4: default) */
+		dram_config[1] = 0x80000000ULL;
+		dram_config[3] = 0x80000000ULL;
+		dram_config[5] = 0x80000000ULL;
+		dram_config[7] = 0x80000000ULL;
+#endif /* RCAR_DRAM_LPDDR4_MEMCONF == 0 */
+		break;
+
+	case RCAR_PRODUCT_M3:
+		/* 4GB(2GBx2 2ch split) */
+		dram_config[1] = 0x80000000ULL;
+		dram_config[5] = 0x80000000ULL;
+		break;
+
+	case RCAR_PRODUCT_M3N:
+		/* 2GB(1GBx2) */
+		dram_config[1] = 0x80000000ULL;
+		break;
+
+	case RCAR_PRODUCT_E3:
+#if (RCAR_DRAM_DDR3L_MEMCONF == 0)
+		/* 1GB(512MBx2) */
+		dram_config[1] = 0x40000000ULL;
+#elif (RCAR_DRAM_DDR3L_MEMCONF == 1)
+		/* 2GB(512MBx4) */
+		dram_config[1] = 0x80000000ULL;
+#elif (RCAR_DRAM_DDR3L_MEMCONF == 2)
+		/* 4GB(1GBx4) */
+		dram_config[1] = 0x100000000ULL;
+#endif /* RCAR_DRAM_DDR3L_MEMCONF == 0 */
+		break;
+	}
+
+	bl2_advertise_dram_entries(dram_config);
+}
+
 void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
 				  u_register_t arg3, u_register_t arg4)
 {
 	uint32_t reg, midr, lcs, boot_dev, boot_cpu, sscg, type, rev;
-	uint32_t cut, product, product_cut, major, minor;
+	uint32_t product, product_cut, major, minor;
 	int32_t ret;
 	const char *str;
 	const char *unknown = "unknown";
@@ -331,6 +617,9 @@ void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
 #else
 	const char *boot_hyper160 = "HyperFlash(160MHz)";
 #endif
+#if (RCAR_LOSSY_ENABLE == 1)
+	int fcnlnode;
+#endif
 
 	reg = mmio_read_32(RCAR_MODEMR);
 	boot_dev = reg & MODEMR_BOOT_DEV_MASK;
@@ -374,7 +663,6 @@ void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
 	reg = mmio_read_32(RCAR_PRR);
 	product_cut = reg & (RCAR_PRODUCT_MASK | RCAR_CUT_MASK);
 	product = reg & RCAR_PRODUCT_MASK;
-	cut = reg & RCAR_CUT_MASK;
 
 	switch (product) {
 	case RCAR_PRODUCT_H3:
@@ -506,33 +794,6 @@ lcm_state:
 	bl2_tzram_layout.total_base = BL31_BASE;
 	bl2_tzram_layout.total_size = BL31_LIMIT - BL31_BASE;
 
-	if (product == RCAR_PRODUCT_H3 && cut >= RCAR_CUT_VER30) {
-#if (RCAR_DRAM_LPDDR4_MEMCONF == 0)
-		NOTICE("BL2: CH0: 0x400000000 - 0x440000000, 1 GiB\n");
-		NOTICE("BL2: CH1: 0x500000000 - 0x540000000, 1 GiB\n");
-		NOTICE("BL2: CH2: 0x600000000 - 0x640000000, 1 GiB\n");
-		NOTICE("BL2: CH3: 0x700000000 - 0x740000000, 1 GiB\n");
-#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && \
-      (RCAR_DRAM_CHANNEL        == 5) && \
-      (RCAR_DRAM_SPLIT          == 2)
-		NOTICE("BL2: CH0: 0x400000000 - 0x480000000, 2 GiB\n");
-		NOTICE("BL2: CH1: 0x500000000 - 0x580000000, 2 GiB\n");
-#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && (RCAR_DRAM_CHANNEL == 15)
-		NOTICE("BL2: CH0: 0x400000000 - 0x480000000, 2 GiB\n");
-		NOTICE("BL2: CH1: 0x500000000 - 0x580000000, 2 GiB\n");
-		NOTICE("BL2: CH2: 0x600000000 - 0x680000000, 2 GiB\n");
-		NOTICE("BL2: CH3: 0x700000000 - 0x780000000, 2 GiB\n");
-#endif
-	}
-
-	if (product == RCAR_PRODUCT_E3) {
-#if (RCAR_DRAM_DDR3L_MEMCONF == 0)
-		NOTICE("BL2: 0x400000000 - 0x440000000, 1 GiB\n");
-#elif (RCAR_DRAM_DDR3L_MEMCONF == 1)
-		NOTICE("BL2: 0x400000000 - 0x480000000, 2 GiB\n");
-#endif
-	}
-
 	if (boot_cpu == MODEMR_BOOT_CPU_CA57 ||
 	    boot_cpu == MODEMR_BOOT_CPU_CA53) {
 		ret = rcar_dram_init();
@@ -543,6 +804,19 @@ lcm_state:
 		rcar_qos_init();
 	}
 
+	/* Set up FDT */
+	ret = fdt_create_empty_tree(fdt, sizeof(fdt_blob));
+	if (ret) {
+		NOTICE("BL2: Cannot allocate FDT for U-Boot (ret=%i)\n", ret);
+		panic();
+	}
+
+	/* Add platform compatible string */
+	bl2_populate_compatible_string(fdt);
+
+	/* Print DRAM layout */
+	bl2_advertise_dram_size(product);
+
 	if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 ||
 	    boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) {
 		if (rcar_emmc_init() != EMMC_SUCCESS) {
@@ -591,14 +865,25 @@ lcm_state:
 	}
 #if (RCAR_LOSSY_ENABLE == 1)
 	NOTICE("BL2: Lossy Decomp areas\n");
+
+	fcnlnode = fdt_add_subnode(fdt, 0, "reserved-memory");
+	if (fcnlnode < 0) {
+		NOTICE("BL2: Cannot create reserved mem node (ret=%i)\n",
+			fcnlnode);
+		panic();
+	}
+
 	bl2_lossy_setting(0, LOSSY_ST_ADDR0, LOSSY_END_ADDR0,
-			  LOSSY_FMT0, LOSSY_ENA_DIS0);
+			  LOSSY_FMT0, LOSSY_ENA_DIS0, fcnlnode);
 	bl2_lossy_setting(1, LOSSY_ST_ADDR1, LOSSY_END_ADDR1,
-			  LOSSY_FMT1, LOSSY_ENA_DIS1);
+			  LOSSY_FMT1, LOSSY_ENA_DIS1, fcnlnode);
 	bl2_lossy_setting(2, LOSSY_ST_ADDR2, LOSSY_END_ADDR2,
-			  LOSSY_FMT2, LOSSY_ENA_DIS2);
+			  LOSSY_FMT2, LOSSY_ENA_DIS2, fcnlnode);
 #endif
 
+	fdt_pack(fdt);
+	NOTICE("BL2: FDT at %p\n", fdt);
+
 	if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 ||
 	    boot_dev == MODEMR_BOOT_DEV_EMMC_50X8)
 		rcar_io_emmc_setup();
diff --git a/plat/renesas/rcar/platform.mk b/plat/renesas/rcar/platform.mk
index f7d6216a84061816797e2ebb021d53f3a1dc7d98..0cc746d129a71fadf8f32fed73c785640cca631d 100644
--- a/plat/renesas/rcar/platform.mk
+++ b/plat/renesas/rcar/platform.mk
@@ -303,6 +303,7 @@ ERRATA_A57_813419  := 1
 include drivers/staging/renesas/rcar/ddr/ddr.mk
 include drivers/staging/renesas/rcar/qos/qos.mk
 include drivers/staging/renesas/rcar/pfc/pfc.mk
+include lib/libfdt/libfdt.mk
 
 PLAT_INCLUDES	:=	-Iinclude/common/tbbr			\
 			-Idrivers/staging/renesas/rcar/ddr	\
@@ -331,6 +332,7 @@ RCAR_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
 BL2_SOURCES	+=	${RCAR_GIC_SOURCES}				\
 			lib/cpus/aarch64/cortex_a53.S			\
 			lib/cpus/aarch64/cortex_a57.S			\
+			${LIBFDT_SRCS}					\
 			common/desc_image_load.c			\
 			plat/renesas/rcar/aarch64/platform_common.c	\
 			plat/renesas/rcar/aarch64/plat_helpers.S	\