Update u-boot from SPF11.1.CSU1 to SPF11.4.CS

Fixes up all the rejects:

    ./arch/arm/dts/Makefile
	Caused by an endif added by us to support booting with a single
	DTS.

    ./board/qca/arm/common/board_init.c
    ./board/qca/arm/common/cmd_bootqca.c

    ./board/qca/arm/common/fdt_fixup.c
	Caused by fixups added by us.

    ./drivers/net/ipq807x/ipq807x_uniphy.c
	Qcom a typo
	    if (condition);
	We fixed it by removing the semicolon
	They fixed it by removing the if and it's body
	Took their version

    ./include/configs/ipq807x.h
	CONFIG_SILENT_CONSOLE is conditionally set by us, so ignoring
	this change.

   ./lib/fdtdec.c
	Qcom added support for compressed DTBS if CONFIG_OF_COMBINE is
	defined.  We've removed this support previously, so dropping the whole
	change.

Change-Id: I2c2a834e81dfc0cd0f2157ef105ee55fe2abdee0
diff --git a/Kconfig b/Kconfig
index 00d5217..55b6d37 100644
--- a/Kconfig
+++ b/Kconfig
@@ -104,6 +104,9 @@
 config SUPPORT_SPL
 	bool
 
+config COMPRESSED_DTB_BASE
+	hex
+
 config SUPPORT_TPL
 	bool
 
diff --git a/Makefile b/Makefile
index dd3ae42..aa81aad 100644
--- a/Makefile
+++ b/Makefile
@@ -556,6 +556,12 @@
 include/config/auto.conf: ;
 endif # $(dot-config)
 
+ifndef DTBLDSCRIPT
+	ifeq ($(wildcard $(DTBLDSCRIPT)),)
+		DTBLDSCRIPT := $(srctree)/arch/$(ARCH)/dts/combined_dtb.lds
+	endif
+endif
+
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
 KBUILD_CFLAGS	+= -Os
 else
@@ -700,6 +706,9 @@
 u-boot-init := $(head-y)
 u-boot-main := $(libs-y)
 
+ifneq ($(CONFIG_COMPRESSED_DTB_BASE),)
+compressed_dtb-dirs := arch/$(ARCH)/dts/compressed_dtb
+endif
 
 # Add GCC lib
 ifeq ($(CONFIG_USE_PRIVATE_LIBGCC),y)
@@ -805,6 +814,17 @@
 LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE)
 endif
 
+
+ifneq ($(CONFIG_COMPRESSED_DTB_BASE),)
+LDFLAGS_dtb_combine += $(LDFLAGS_FINAL)
+COMPRESS_DTB_BASE = $(shell printf "0x%x" $$(( $(CONFIG_SYS_TEXT_BASE) - $(CONFIG_COMPRESSED_DTB_MAX_SIZE))))
+LDFLAGS_dtb_combine += -Ttext $(COMPRESS_DTB_BASE)
+
+# Normal objcopy without filter the sections
+quiet_cmd_nobjcopy = OBJCOPY $@
+cmd_nobjcopy = $(OBJCOPY) --gap-fill=0xff -O binary $< $@
+endif
+
 # Normally we fill empty space with 0xff
 quiet_cmd_objcopy = OBJCOPY $@
 cmd_objcopy = $(OBJCOPY) --gap-fill=0xff $(OBJCOPYFLAGS) \
@@ -891,6 +911,11 @@
 	$(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))
 	$(BOARD_SIZE_CHECK)
 
+ifneq ($(CONFIG_COMPRESSED_DTB_BASE),)
+dtb_combined.bin: dtb_combined  FORCE
+	$(call if_changed,nobjcopy)
+endif
+
 quiet_cmd_mkheader = MKHEADER $@
 cmd_mkheader = $(PYTHON) tools/mkheader.py $(CONFIG_SYS_TEXT_BASE) $(CONFIG_IPQ_APPSBL_IMG_TYPE) $< $@
 
@@ -1205,6 +1230,23 @@
       --start-group $(u-boot-main) --end-group                 \
       $(PLATFORM_LIBS) -Map u-boot.map
 
+ifneq ($(CONFIG_COMPRESSED_DTB_BASE),)
+# Rule to link combined_dtb.lds
+quiet_cmd_dtb_combined__ ?= LD      $@
+      cmd_dtb_combined__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_dtb_combine) -o dtb_combined \
+      -T combined_dtb.lds $(u-boot-init)                             \
+      --start-group arch/$(ARCH)/dts/built-in.o --end-group                 \
+      $(PLATFORM_LIBS) -Map dtb_combined.map
+
+combine_dtb_Linker: combined_dtb.lds
+	$(call if_changed,dtb_combined__)
+
+compress_dtb: combine_dtb_Linker dtb_combined.bin $(compressed_dtb-dirs)
+	cp arch/$(ARCH)/dts/compressed_dtb/dtbcombined.o arch/$(ARCH)/dts/built-in.o
+else
+compress_dtb:
+endif
+
 quiet_cmd_smap = GEN     common/system_map.o
 cmd_smap = \
 	smap=`$(call SYSTEM_MAP,u-boot) | \
@@ -1212,7 +1254,7 @@
 	$(CC) $(c_flags) -DSYSTEM_MAP="\"$${smap}\"" \
 		-c $(srctree)/common/system_map.c -o common/system_map.o
 
-u-boot:	$(u-boot-init) $(u-boot-main) u-boot.lds
+u-boot:	$(u-boot-init) $(u-boot-main) u-boot.lds compress_dtb
 	$(call if_changed,u-boot__)
 ifeq ($(CONFIG_KALLSYMS),y)
 	$(call cmd,smap)
@@ -1229,10 +1271,16 @@
 # make menuconfig etc.
 # Error messages still appears in the original language
 
+
 PHONY += $(u-boot-dirs)
 $(u-boot-dirs): prepare scripts
 	$(Q)$(MAKE) $(build)=$@
 
+ifneq ($(CONFIG_COMPRESSED_DTB_BASE),)
+$(compressed_dtb-dirs): prepare scripts
+	$(Q)$(MAKE) $(build)=$@
+endif
+
 tools: prepare
 # The "tools" are needed early
 $(filter-out tools, $(u-boot-dirs)): tools
@@ -1347,6 +1395,13 @@
 u-boot.lds: $(LDSCRIPT) prepare FORCE
 	$(call if_changed_dep,cpp_lds)
 
+quiet_cmd_cpp_dtb_lds = LDS     $@
+cmd_cpp_dtb_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi \
+		-D__ASSEMBLY__ -x assembler-with-cpp -P -o $@ $<
+
+combined_dtb.lds: $(DTBLDSCRIPT) prepare FORCE
+	$(call if_changed_dep,cpp_dtb_lds)
+
 spl/u-boot-spl.bin: spl/u-boot-spl
 	@:
 spl/u-boot-spl: tools prepare $(if $(CONFIG_OF_SEPARATE),dts/dt.dtb)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 20956d9..6efc192 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -883,6 +883,7 @@
 source "board/hisilicon/hikey/Kconfig"
 source "board/imx31_phycore/Kconfig"
 source "board/ipq40xx/Kconfig"
+source "board/ipq5018/Kconfig"
 source "board/ipq6018/Kconfig"
 source "board/ipq806x/Kconfig"
 source "board/ipq807x/Kconfig"
diff --git a/arch/arm/cpu/armv7/qca/common/scm.c b/arch/arm/cpu/armv7/qca/common/scm.c
index de2472d..5fbe668 100644
--- a/arch/arm/cpu/armv7/qca/common/scm.c
+++ b/arch/arm/cpu/armv7/qca/common/scm.c
@@ -450,8 +450,12 @@
 	if (is_scm_armv8())
 	{
 		struct qca_scm_desc desc = {0};
-
+#ifdef CONFIG_ARCH_IPQ5018
+		desc.arginfo = QCA_SCM_ARGS(2, SCM_READ_OP);
+		desc.args[1] = 0x800;
+#else
 		desc.arginfo = QCA_SCM_ARGS(1, SCM_READ_OP);
+#endif
 		desc.args[0] = *((unsigned int *)buf);
 
 		ret = scm_call_64(svc_id, cmd_id, &desc);
@@ -546,6 +550,85 @@
 
 	return ret;
 }
+
+#ifdef CONFIG_IPQ_BT_SUPPORT
+int qti_scm_otp(u32 peripheral)
+{
+	int ret;
+
+	if (is_scm_armv8())
+	{
+		struct qca_scm_desc desc = {0};
+
+		desc.arginfo = QCA_SCM_ARGS(1);
+		desc.args[0] = peripheral;
+
+		ret = scm_call_64(SCM_SVC_PIL, SCM_CMD_OTP, &desc);
+	}
+	else
+	{
+		u32 cmd = peripheral;
+
+		ret = scm_call(SCM_SVC_PIL, SCM_CMD_OTP, &cmd, sizeof(cmd),
+				NULL, 0);
+	}
+
+	return ret;
+}
+
+int qti_scm_pas_init_image(u32 peripheral, u32 addr)
+{
+	int ret;
+
+	if (is_scm_armv8())
+	{
+		struct qca_scm_desc desc = {0};
+
+		desc.arginfo = QCA_SCM_ARGS(2, SCM_VAL, SCM_IO_WRITE);
+		desc.args[0] = peripheral;
+		desc.args[1] = addr;
+
+		ret = scm_call_64(SCM_SVC_PIL, SCM_PAS_INIT_IMAGE_CMD, &desc);
+	}
+	else
+	{
+		struct {
+			u32 proc;
+			u32 image_addr;
+		} request;
+		request.proc = peripheral;
+		request.image_addr = addr;
+		ret = scm_call(SCM_SVC_PIL, SCM_PAS_INIT_IMAGE_CMD, &request,
+				sizeof(request), NULL, 0);
+	}
+
+	return ret;
+}
+
+int qti_pas_and_auth_reset(u32 peripheral)
+{
+	int ret;
+	u32 cmd = peripheral;
+
+	if (is_scm_armv8())
+	{
+		struct qca_scm_desc desc = {0};
+
+		desc.arginfo = QCA_SCM_ARGS(1);
+		desc.args[0] = peripheral;
+
+		ret = scm_call_64(SCM_SVC_PIL, SCM_PAS_AUTH_AND_RESET_CMD, &desc);
+	}
+	else
+	{
+		ret = scm_call(SCM_SVC_PIL, SCM_PAS_AUTH_AND_RESET_CMD, &cmd, sizeof(cmd),
+				NULL, 0);
+	}
+
+	return ret;
+}
+#endif
+
 #else
 int qca_scm_call(u32 svc_id, u32 cmd_id, void *buf, size_t len)
 {
@@ -570,6 +653,19 @@
 }
 #endif
 
+int qca_scm_call_crypto_v8(u32 svc_id, u32 cmd_id, u32 *addr, u32 val)
+{
+        int ret = 0;
+        struct qca_scm_desc desc = {0};
+
+        desc.arginfo = QCA_SCM_ARGS(2, SCM_RW_OP, SCM_VAL);
+
+        desc.args[0] = (u32)addr;
+        desc.args[1] = val;
+        ret = scm_call_64(svc_id, cmd_id, &desc);
+        return ret;
+}
+
 int qca_scm_call_write(u32 svc_id, u32 cmd_id, u32 *addr, u32 val)
 {
 	int ret = 0;
@@ -623,6 +719,18 @@
         return ret;
 }
 
+int qca_scm_crypto(int cmd_id, void *req_ptr, uint32_t req_size)
+{
+        int ret;
+        if (is_scm_armv8())
+                ret = qca_scm_call_crypto_v8(SCM_SVC_CRYPTO, cmd_id,
+                                         (u32 *)req_ptr, req_size);
+        else
+		ret = -ENOTSUPP;
+
+        return ret;
+}
+
 int qca_scm_dload(unsigned int magic_cookie)
 {
 	int ret;
diff --git a/arch/arm/cpu/armv7/qca/common/smem.c b/arch/arm/cpu/armv7/qca/common/smem.c
index 2f00e21..de0dd78 100644
--- a/arch/arm/cpu/armv7/qca/common/smem.c
+++ b/arch/arm/cpu/armv7/qca/common/smem.c
@@ -528,7 +528,7 @@
 
 	return 0; /* alt partition not available */
 }
-
+#ifdef CONFIG_CMD_NAND
 /*
  * get nand block size by device id.
  * dev_id is 0 for parallel nand.
@@ -542,16 +542,20 @@
 
 	return mtd->erasesize;
 }
-
+#endif
 /*
  * get flash block size based on partition name.
  */
 static inline uint32_t get_flash_block_size(char *name,
 					    qca_smem_flash_info_t *smem)
 {
+#ifdef CONFIG_CMD_NAND
 	return (get_which_flash_param(name) == 1) ?
 		get_nand_block_size(is_spi_nand_available())
 		: smem->flash_block_size;
+#else
+	return smem->flash_block_size;
+#endif
 }
 
 #define part_which_flash(p)    (((p)->attr & 0xff000000) >> 24)
@@ -559,9 +563,13 @@
 static inline uint32_t get_part_block_size(struct smem_ptn *p,
 					   qca_smem_flash_info_t *sfi)
 {
+#ifdef CONFIG_CMD_NAND
         return (part_which_flash(p) == 1) ?
 		get_nand_block_size(is_spi_nand_available())
 		: sfi->flash_block_size;
+#else
+	return sfi->flash_block_size;
+#endif
 }
 
 void qca_set_part_entry(char *name, qca_smem_flash_info_t *smem,
@@ -598,6 +606,52 @@
 }
 
 /*
+ * smem_getpart_from_offset - retreive partition start and size for given offset
+ * belongs to.
+ * @part_name: offset for which part start and size needed
+ * @start: location where the start offset is to be stored
+ * @size: location where the size is to be stored
+ *
+ * Returns 0 at success or -ENOENT otherwise.
+ */
+int smem_getpart_from_offset(uint32_t offset, uint32_t *start, uint32_t *size)
+{
+	unsigned i;
+	qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
+	struct smem_ptn *p;
+	uint32_t bsize;
+
+	for (i = 0; i < smem_ptable.len; i++) {
+		p = &smem_ptable.parts[i];
+		*start = p->start;
+		bsize = get_part_block_size(p, sfi);
+
+		if (p->size == (~0u)) {
+		/*
+		 * Partition size is 'till end of device', calculate
+		 * appropriately
+		 */
+#ifdef CONFIG_CMD_NAND
+			*size = (nand_info[get_device_id_by_part(p)].size /
+				 bsize) - p->start;
+#else
+			*size = 0;
+			bsize = bsize;
+#endif
+		} else {
+			*size = p->size;
+		}
+		*start = *start * bsize;
+		*size = *size * bsize;
+		if (*start <= offset && *start + *size > offset) {
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+
+}
+/*
  * smem_getpart - retreive partition start and size
  * @part_name: partition name
  * @start: location where the start offset is to be stored
@@ -631,8 +685,13 @@
 		 * Partition size is 'till end of device', calculate
 		 * appropriately
 		 */
+#ifdef CONFIG_CMD_NAND
 		*size = (nand_info[get_device_id_by_part(p)].size /
 			 bsize) - p->start;
+#else
+		*size = 0;
+		bsize = bsize;
+#endif
 	} else {
 		*size = p->size;
 	}
@@ -905,8 +964,12 @@
 			 * Partition size is 'till end of device', calculate
 			 * appropriately
 			 */
+#ifdef CONFIG_CMD_NAND
 			psize = (nand_info[get_device_id_by_part(p)].size
 					- (((loff_t)p->start) * bsize));
+#else
+			psize = 0;
+#endif
 		} else {
 			psize =  ((loff_t)p->size) * bsize;
 		}
@@ -977,8 +1040,12 @@
 				 * Partition size is 'till end of device', calculate
 				 * appropriately
 				 */
+#ifdef CONFIG_CMD_NAND
 				psize = nand_info[get_device_id_by_part(p)].size
 					- (((loff_t)p->start) * bsize);
+#else
+				psize = 0;
+#endif
 			} else {
 				psize = ((loff_t)p->size) * bsize;
 			}
@@ -1226,8 +1293,12 @@
 			 * Partition size is 'till end of device', calculate
 			 * appropriately
 			 */
+#ifdef CONFIG_CMD_NAND
 			psize = nand_info[get_device_id_by_part(p)].size
 				- (((loff_t)p->start) * bsize);
+#else
+			psize = 0;
+#endif
 		} else {
 			psize = ((loff_t)p->size) * bsize;
 		}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 675577c..83f6665 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -36,18 +36,17 @@
 	ipq807x-hk08.dtb \
 	ipq807x-hk09.dtb \
 	ipq807x-hk10.dtb \
+	ipq807x-hk14.dtb \
 	ipq807x-hk11-c1.dtb \
 	ipq807x-ac01.dtb \
-	ipq807x-ac02.dtb \
 	ipq807x-ac03.dtb \
 	ipq807x-ac04.dtb \
 	ipq807x-oak02.dtb \
-	ipq807x-oak03.dtb \
 	ipq807x-hk01-c2.dtb \
-	ipq807x-hk01-c3.dtb \
 	ipq807x-hk01-c4.dtb \
 	ipq807x-hk01-c5.dtb \
-	ipq807x-hk10-c2.dtb
+	ipq807x-hk10-c2.dtb \
+	ipq807x-db-hk02.dtb
 endif
 dtb-$(CONFIG_ARCH_IPQ806x) += ipq806x-ap148.dtb \
 	ipq806x-ap160.dtb \
@@ -71,10 +70,35 @@
 		ipq40xx-dk01-s1.dtb \
 		ipq40xx-dk06-c1.dtb
 
-dtb-$(CONFIG_ARCH_IPQ5018) += ipq5018-emulation.dtb
+ifneq ($(CONFIG_IPQ_TINY),y)
+dtb-$(CONFIG_ARCH_IPQ5018) += ipq5018-emulation.dtb \
+			ipq5018-mp02.1.dtb \
+			ipq5018-mp03.1-c2.dtb \
+			ipq5018-mp03.1-c3.dtb \
+			ipq5018-mp03.3.dtb \
+			ipq5018-mp03.3-c2.dtb \
+			ipq5018-mp03.3-c3.dtb \
+			ipq5018-mp03.4-c1.dtb \
+			ipq5018-mp03.4-c2.dtb \
+			ipq5018-mp03.6-c1.dtb \
+			ipq5018-mp03.6-c2.dtb \
+			ipq5018-mp03.5-c1.dtb \
+			ipq5018-mp03.5-c2.dtb \
+			ipq5018-db-mp02.1.dtb \
+			ipq5018-db-mp03.1.dtb \
+			ipq5018-db-mp03.1-c2.dtb \
+			ipq5018-db-mp03.3.dtb \
+			ipq5018-db-mp03.3-c2.dtb \
+			ipq5018-tb-mp04.dtb \
+			ipq5018-mp03.1.dtb
+else
+dtb-$(CONFIG_ARCH_IPQ5018) += ipq5018-db-mp02.1.dtb \
+				ipq5018-mp02.1.dtb \
+				ipq5018-mp03.1.dtb \
+				ipq5018-db-mp03.1.dtb
+endif
 
 dtb-$(CONFIG_ARCH_IPQ6018) += ipq6018-cp01-c1.dtb \
-			ipq6018-cp01-c3.dtb \
 			ipq6018-cp02-c1.dtb \
 			ipq6018-cp03-c1.dtb \
 			ipq6018-db-cp01.dtb \
diff --git a/arch/arm/dts/compressed_dtb/Makefile b/arch/arm/dts/compressed_dtb/Makefile
new file mode 100644
index 0000000..6bbae06
--- /dev/null
+++ b/arch/arm/dts/compressed_dtb/Makefile
@@ -0,0 +1,13 @@
+$(obj)/dtbcombined.S: $(obj)/../../../../dtb_combined.bin
+	gzip -k --best $(obj)/../../../../dtb_combined.bin
+	echo ".section .dtb.combine_blob,\"a\"" > $(obj)/dtbcombined.S
+	echo '.balign 16' >> $(obj)/dtbcombined.S
+	echo ".global __dtb_blob_begin" >> $(obj)/dtbcombined.S
+	echo "__dtb_blob_begin:" >> $(obj)/dtbcombined.S
+	echo '.incbin "$(obj)/../../../../dtb_combined.bin.gz"' >> $(obj)/dtbcombined.S
+	echo '.balign 16' >> $(obj)/dtbcombined.S
+	echo ".global __dtb_blob_end" >> $(obj)/dtbcombined.S
+	echo "__dtb_blob_end:" >> $(obj)/dtbcombined.S
+	echo ".word 0" >> $(obj)/dtbcombined.S
+
+obj-y := dtbcombined.o
diff --git a/arch/arm/dts/ipq5018-db-mp02.1.dts b/arch/arm/dts/ipq5018-db-mp02.1.dts
new file mode 100644
index 0000000..95f4e6a
--- /dev/null
+++ b/arch/arm/dts/ipq5018-db-mp02.1.dts
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "ipq5018-soc.dtsi"
+/ {
+	model ="QCA, IPQ5018/DB-MP02.1";
+	compatible = "qca,ipq5018", "qca,ipq5018-db-mp02.1";
+	machid = <0x1040003>;
+	config_name = "config@db-mp02.1";
+
+	aliases {
+		console = "/serial@78AF000";
+	};
+
+	console: serial@78AF000 {
+		status = "ok";
+		serial_gpio {
+			blsp0_mux_uart_rx {
+				gpio = <20>;
+				func = <0>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_mux_uart_tx {
+				gpio = <21>;
+				func = <0>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_rx {
+				gpio = <28>;
+				func = <3>;
+				pull = <GPIO_NO_PULL>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_tx {
+				gpio = <29>;
+				func = <3>;
+				pull = <GPIO_NO_PULL>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+		};
+	};
+
+	gmac_cfg {
+		ext_mdio_gpio = <36 37>;
+		gephy_led = <30>;
+
+		gmac1_cfg {
+			unit = <0>;
+			base = <0x39C00000>;
+			phy_address = <7>;
+		};
+		gmac2_cfg {
+			unit = <1>;
+			base = <0x39D00000>;
+			phy_address = <4>;
+			8033_gpio = <26>;
+		};
+	};
+
+};
diff --git a/arch/arm/dts/ipq5018-db-mp03.1-c2.dts b/arch/arm/dts/ipq5018-db-mp03.1-c2.dts
new file mode 100644
index 0000000..88bfab0
--- /dev/null
+++ b/arch/arm/dts/ipq5018-db-mp03.1-c2.dts
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "ipq5018-db-mp03.1.dts"
+/ {
+	model ="QCA, IPQ5018/DB-MP03.1-C2";
+	compatible = "qca,ipq5018", "qca,ipq5018-db-mp03.1-c2";
+	machid = <0x1040104>;
+	config_name = "config@db-mp03.1-c2";
+
+	mmc: sdhci@7804000 {
+		compatible = "qcom,sdhci-msm";
+		status = "okay";
+		mmc_gpio {
+			emmc_dat3 {
+				gpio = <4>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat2 {
+				gpio = <5>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat1 {
+				gpio = <6>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat0 {
+				gpio = <7>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_cmd{
+				gpio = <8>;
+				func = <1>;
+				pull = <GPIO_PULL_UP>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_clk{
+				gpio = <9>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/dts/ipq5018-db-mp03.1.dts b/arch/arm/dts/ipq5018-db-mp03.1.dts
new file mode 100644
index 0000000..aa2c3e9
--- /dev/null
+++ b/arch/arm/dts/ipq5018-db-mp03.1.dts
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "ipq5018-soc.dtsi"
+/ {
+	model ="QCA, IPQ5018/DB-MP03.1";
+	compatible = "qca,ipq5018", "qca,ipq5018-db-mp03.1";
+	machid = <0x1040004>;
+	config_name = "config@db-mp03.1";
+
+	aliases {
+		console = "/serial@78AF000";
+		mmc = "/sdhci@7804000";
+		i2c0 = "/i2c@78b7000";
+		gmac_gpio = "/gmac_gpio";
+		usb0 = "/xhci@8a00000";
+		pci0 = "/pci@a0000000";
+		nand = "/nand-controller@79B0000";
+	};
+
+	console: serial@78AF000 {
+		status = "ok";
+		serial_gpio {
+			blsp0_uart_rx {
+				gpio = <20>;
+				func = <1>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_tx {
+				gpio = <21>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "okay";
+		nand_gpio {
+			qspi_dat3 {
+				gpio = <4>;
+				func = <2>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat2 {
+				gpio = <5>;
+				func = <2>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat1 {
+				gpio = <6>;
+				func = <2>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat0 {
+				gpio = <7>;
+				func = <2>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_cs_n {
+				gpio = <8>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_clk {
+				gpio = <9>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci0: pci@a0000000 {
+		status = "ok";
+		perst_gpio = <15>;
+		mode = "fixed";
+		pci_gpio {
+			pci_rst {
+				gpio = <15>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci1: pci@a0000000 {
+		status = "ok";
+		pci_gpio {
+			pci_rst {
+				gpio = <18>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	usb0: xhci@8a00000 {
+		ssphy = <1>;
+		usb_gpio {
+			pwr_gpio {
+				gpio = <24>;
+				func = <0>;
+				pull = <GPIO_PULL_UP>;
+				oe = <GPIO_OE_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	gmac_cfg {
+		ext_mdio_gpio = <36 37>;
+		gephy_led = <46>;
+
+		gmac1_cfg {
+			unit = <0>;
+			base = <0x39C00000>;
+			phy_address = <7>;
+		};
+
+		gmac2_cfg {
+			unit = <1>;
+			base = <0x39D00000>;
+			mac_pwr = <0xaa545>;
+			s17c_switch_enable = <1>;
+			switch_port_count = <4>;
+			switch_phy_address = <0 1 2 3>;
+			switch_gpio = <39>;
+		};
+	};
+
+};
diff --git a/arch/arm/dts/ipq5018-db-mp03.3-c2.dts b/arch/arm/dts/ipq5018-db-mp03.3-c2.dts
new file mode 100644
index 0000000..db66c53
--- /dev/null
+++ b/arch/arm/dts/ipq5018-db-mp03.3-c2.dts
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "ipq5018-db-mp03.3.dts"
+/ {
+	model ="QCA, IPQ5018/DB-MP03.3-C2";
+	compatible = "qca,ipq5018", "qca,ipq5018-db-mp03.3-c2";
+	machid = <0x1040105>;
+	config_name = "config@db-mp03.3-c2";
+
+	mmc: sdhci@7804000 {
+		compatible = "qcom,sdhci-msm";
+		status = "okay";
+		mmc_gpio {
+			emmc_dat3 {
+				gpio = <4>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat2 {
+				gpio = <5>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat1 {
+				gpio = <6>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat0 {
+				gpio = <7>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_cmd{
+				gpio = <8>;
+				func = <1>;
+				pull = <GPIO_PULL_UP>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_clk{
+				gpio = <9>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/dts/ipq5018-db-mp03.3.dts b/arch/arm/dts/ipq5018-db-mp03.3.dts
new file mode 100644
index 0000000..443ebff
--- /dev/null
+++ b/arch/arm/dts/ipq5018-db-mp03.3.dts
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "ipq5018-soc.dtsi"
+/ {
+	model ="QCA, IPQ5018/DB-MP03.3";
+	compatible = "qca,ipq5018", "qca,ipq5018-db-mp03.3";
+	machid = <0x1040005>;
+	config_name = "config@db-mp03.3";
+
+	aliases {
+		console = "/serial@78AF000";
+		mmc = "/sdhci@7804000";
+		i2c0 = "/i2c@78b6000";
+		gmac_gpio = "/gmac_gpio";
+		usb0 = "/xhci@8a00000";
+		pci0 = "/pci@80000000";
+		pci1 = "/pci@a0000000";
+		nand = "/nand-controller@79B0000";
+	};
+
+	console: serial@78AF000 {
+		status = "ok";
+		serial_gpio {
+			blsp0_uart_rx {
+				gpio = <20>;
+				func = <1>;
+				pull = <GPIO_PULL_DOWN>;
+				oe = <GPIO_OE_DISABLE>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_tx {
+				gpio = <21>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OE_DISABLE>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "okay";
+		nand_gpio {
+			qspi_dat3 {
+				gpio = <4>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat2 {
+				gpio = <5>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat1 {
+				gpio = <6>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat0 {
+				gpio = <7>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_cs_n {
+				gpio = <8>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci0: pci@80000000 {
+		status = "ok";
+		perst_gpio = <18>;
+		mode = "fixed";
+		pci_gpio {
+			pci_rst {
+				gpio = <18>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci1: pci@a0000000 {
+		status = "ok";
+		perst_gpio = <15>;
+		mode = "fixed";
+		pci_gpio {
+			pci_rst {
+				gpio = <15>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	usb0: xhci@8a00000 {
+		usb_gpio {
+			pwr_gpio {
+				gpio = <24>;
+				func = <0>;
+				pull = <GPIO_PULL_UP>;
+				oe = <GPIO_OE_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	gmac_cfg {
+		ext_mdio_gpio = <36 37>;
+		gephy_led = <46>;
+
+		gmac1_cfg {
+			unit = <0>;
+			base = <0x39C00000>;
+			phy_address = <7>;
+			phy_external_link = <0>;
+			mac_pwr = <0xaa545>;
+			s17c_switch_enable = <1>;
+			switch_port_count = <4>;
+			switch_phy_address = <0 1 2 3>;
+		};
+		gmac2_cfg {
+			unit = <1>;
+			base = <0x39D00000>;
+			phy_address = <0x1c>;
+			napa_gpio = <39>;
+		};
+	};
+};
diff --git a/arch/arm/dts/ipq5018-emulation.dts b/arch/arm/dts/ipq5018-emulation.dts
new file mode 100644
index 0000000..b0fe1d4
--- /dev/null
+++ b/arch/arm/dts/ipq5018-emulation.dts
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "ipq5018-soc.dtsi"
+/ {
+	model ="QCA, IPQ5018-EMULATION";
+	compatible = "qca,ipq5018", "qca,ipq5018-emulation";
+	machid = <0x0F040000>;
+	config_name = "config@emulation-c2";
+
+	aliases {
+		console = "/serial@78AF000";
+		mmc = "/sdhci@7804000";
+		i2c0 = "/i2c@78b6000";
+		gmac_gpio = "/gmac_gpio";
+		usb0 = "/xhci@8a00000";
+		pci0 = "/pci@80000000";
+		nand = "/nand-controller@79B0000";
+	};
+
+	mmc: sdhci@7804000 {
+		compatible = "qcom,sdhci-msm";
+	};
+
+	console: serial@78AF000 {
+		status = "ok";
+		serial_gpio {
+			blsp0_uart_rx {
+				gpio = <20>;
+				func = <1>;
+				pull = <GPIO_PULL_DOWN>;
+				oe = <GPIO_OE_DISABLE>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_tx {
+				gpio = <21>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OE_DISABLE>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "okay";
+		nand_gpio {
+			qspi_dat3 {
+				gpio = <4>;
+				func = <2>;
+				oe = <GPIO_OE_DISABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat2 {
+				gpio = <5>;
+				func = <2>;
+				oe = <GPIO_OE_DISABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat1 {
+				gpio = <6>;
+				func = <2>;
+				oe = <GPIO_OE_DISABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat0 {
+				gpio = <7>;
+				func = <2>;
+				oe = <GPIO_OE_DISABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_cs_n {
+				gpio = <8>;
+				func = <2>;
+				oe = <GPIO_OE_DISABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci0: pci@80000000 {
+		status = "ok";
+		pci_gpio {
+			pci_rst {
+				gpio = <15>;
+				func = <0>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci1: pci@a0000000 {
+		status = "ok";
+		pci_gpio {
+			pci_rst {
+				gpio = <18>;
+				func = <0>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	timer {
+		gpt_freq_hz = <240000>;
+	};
+
+	gmac_cfg {
+		gmac_count = <2>;
+		ext_mdio_gpio = <1>;
+		gmac1_cfg {
+			unit = <0>;
+			base = <0x39C00000>;
+			phy_address = <7>;
+			phy_interface_mode = <2>;
+			phy_name = "IPQ MDIO0";
+		};
+
+		gmac2_cfg {
+			unit = <1>;
+			base = <0x39D00000>;
+			phy_address = <1>;
+			phy_interface_mode = <2>;
+			phy_name = "IPQ MDIO1";
+			mac_pwr0 = <0x00080000>;
+			mac_pwr1 = <0x00040000>;
+			s17c_switch_enable = <0>;
+		};
+       };
+
+	gmac_gpio{};
+
+	xhci@8a00000 {
+		qcom,emulation = <1>;
+	};
+
+};
diff --git a/arch/arm/dts/ipq5018-mp02.1.dts b/arch/arm/dts/ipq5018-mp02.1.dts
new file mode 100644
index 0000000..ff1d553
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp02.1.dts
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "ipq5018-soc.dtsi"
+/ {
+	model ="QCA, IPQ5018-MP02.1";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp02.1";
+	machid = <0x8040000>;
+	config_name = "config@mp02.1";
+
+	aliases {
+		console = "/serial@78AF000";
+	};
+
+	console: serial@78AF000 {
+		status = "ok";
+		serial_gpio {
+			blsp0_mux_uart_rx {
+				gpio = <20>;
+				func = <0>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_mux_uart_tx {
+				gpio = <21>;
+				func = <0>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_rx {
+				gpio = <28>;
+				func = <3>;
+				pull = <GPIO_NO_PULL>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_tx {
+				gpio = <29>;
+				func = <3>;
+				pull = <GPIO_NO_PULL>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+		};
+	};
+
+	gmac_cfg {
+		ext_mdio_gpio = <36 37>;
+		gephy_led = <30>;
+
+		gmac1_cfg {
+			unit = <0>;
+			base = <0x39C00000>;
+			phy_address = <7>;
+		};
+		gmac2_cfg {
+			unit = <1>;
+			base = <0x39D00000>;
+			phy_address = <4>;
+			8033_gpio = <26>;
+		};
+	};
+};
diff --git a/arch/arm/dts/ipq5018-mp03.1-c2.dts b/arch/arm/dts/ipq5018-mp03.1-c2.dts
new file mode 100644
index 0000000..b4a5270
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.1-c2.dts
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "ipq5018-mp03.1.dts"
+/ {
+	model ="QCA, IPQ5018-MP03.1-C2";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.1-c2";
+	machid = <0x8040101>;
+	config_name = "config@mp03.1-c2";
+
+	mmc: sdhci@7804000 {
+		compatible = "qcom,sdhci-msm";
+		status = "okay";
+		mmc_gpio {
+			emmc_dat3 {
+				gpio = <4>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat2 {
+				gpio = <5>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat1 {
+				gpio = <6>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat0 {
+				gpio = <7>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_cmd{
+				gpio = <8>;
+				func = <1>;
+				pull = <GPIO_PULL_UP>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_clk{
+				gpio = <9>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/dts/ipq5018-mp03.1-c3.dts b/arch/arm/dts/ipq5018-mp03.1-c3.dts
new file mode 100644
index 0000000..eb2e8ea
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.1-c3.dts
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "ipq5018-mp03.1.dts"
+/ {
+	model ="QCA, IPQ5018-MP03.1-C3";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.1-c3";
+	machid = <0x8040201>;
+	config_name = "config@mp03.1-c3";
+
+	gmac_cfg {
+		gmac2_cfg {
+			/delete-property/s17c_switch_enable;
+			/delete-property/switch_port_count;
+			/delete-property/switch_gpio;
+			/delete-property/mac_pwr;
+			/delete-property/switch_phy_address;
+			phy_address = <0x1c>;
+			napa_gpio = <39>;
+		};
+	};
+};
diff --git a/arch/arm/dts/ipq5018-mp03.1.dts b/arch/arm/dts/ipq5018-mp03.1.dts
new file mode 100644
index 0000000..fe9d12e
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.1.dts
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "ipq5018-soc.dtsi"
+/ {
+	model ="QCA, IPQ5018-MP03.1";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.1";
+	machid = <0x8040001>;
+	config_name = "config@mp03.1";
+
+	aliases {
+		console = "/serial@78AF000";
+		mmc = "/sdhci@7804000";
+		i2c0 = "/i2c@78b7000";
+		gmac_gpio = "/gmac_gpio";
+		usb0 = "/xhci@8a00000";
+		pci0 = "/pci@a0000000";
+		nand = "/nand-controller@79B0000";
+	};
+
+	console: serial@78AF000 {
+		status = "ok";
+		serial_gpio {
+			blsp0_uart_rx {
+				gpio = <20>;
+				func = <1>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_tx {
+				gpio = <21>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "okay";
+		nand_gpio {
+			qspi_dat3 {
+				gpio = <4>;
+				func = <2>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat2 {
+				gpio = <5>;
+				func = <2>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat1 {
+				gpio = <6>;
+				func = <2>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat0 {
+				gpio = <7>;
+				func = <2>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_cs_n {
+				gpio = <8>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_clk {
+				gpio = <9>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci0: pci@a0000000 {
+		status = "ok";
+		perst_gpio = <15>;
+		mode = "fixed";
+		pci_gpio {
+			pci_rst {
+				gpio = <15>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	usb0: xhci@8a00000 {
+		ssphy = <1>;
+		usb_pwr_gpio = <24>;
+		usb_gpio {
+			pwr_gpio {
+				gpio = <24>;
+				func = <0>;
+				pull = <GPIO_PULL_UP>;
+				oe = <GPIO_OE_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	gmac_cfg {
+		ext_mdio_gpio = <36 37>;
+		gephy_led = <46>;
+
+		gmac1_cfg {
+			unit = <0>;
+			base = <0x39C00000>;
+			phy_address = <7>;
+		};
+
+		gmac2_cfg {
+			unit = <1>;
+			base = <0x39D00000>;
+			mac_pwr = <0xaa545>;
+			s17c_switch_enable = <1>;
+			switch_port_count = <4>;
+			switch_phy_address = <0 1 2 3>;
+			switch_gpio = <39>;
+		};
+	};
+
+};
diff --git a/arch/arm/dts/ipq5018-mp03.3-c2.dts b/arch/arm/dts/ipq5018-mp03.3-c2.dts
new file mode 100644
index 0000000..3fc3681
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.3-c2.dts
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include "ipq5018-mp03.3.dts"
+/ {
+	model ="QCA, IPQ5018-MP03.3-C2";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.3-c2";
+	machid = <0x8040102>;
+	config_name = "config@mp03.3-c2";
+
+	mmc: sdhci@7804000 {
+		compatible = "qcom,sdhci-msm";
+		status = "okay";
+		mmc_gpio {
+			emmc_dat3 {
+				gpio = <4>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat2 {
+				gpio = <5>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat1 {
+				gpio = <6>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat0 {
+				gpio = <7>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_cmd{
+				gpio = <8>;
+				func = <1>;
+				pull = <GPIO_PULL_UP>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_clk{
+				gpio = <9>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/dts/ipq5018-mp03.3-c3.dts b/arch/arm/dts/ipq5018-mp03.3-c3.dts
new file mode 100644
index 0000000..b360a20
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.3-c3.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include "ipq5018-mp03.3.dts"
+/ {
+	model ="QCA, IPQ5018-MP03.3-C3";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.3-c3";
+	machid = <0x8040202>;
+	config_name = "config@mp03.3-c3";
+
+	/delete-node/ pci@a0000000;
+	/delete-node/ xhci@8a00000;
+};
diff --git a/arch/arm/dts/ipq5018-mp03.3.dts b/arch/arm/dts/ipq5018-mp03.3.dts
new file mode 100644
index 0000000..9254919
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.3.dts
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "ipq5018-soc.dtsi"
+/ {
+	model ="QCA, IPQ5018-MP03.3";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.3";
+	machid = <0x8040002>;
+	config_name = "config@mp03.3";
+
+	aliases {
+		console = "/serial@78AF000";
+		mmc = "/sdhci@7804000";
+		i2c0 = "/i2c@78b7000";
+		gmac_gpio = "/gmac_gpio";
+		usb0 = "/xhci@8a00000";
+		pci0 = "/pci@80000000";
+		pci1 = "/pci@a0000000";
+		nand = "/nand-controller@79B0000";
+	};
+
+	console: serial@78AF000 {
+		status = "ok";
+		serial_gpio {
+			blsp0_uart_rx {
+				gpio = <20>;
+				func = <1>;
+				pull = <GPIO_PULL_DOWN>;
+				oe = <GPIO_OE_DISABLE>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_tx {
+				gpio = <21>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OE_DISABLE>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "okay";
+		nand_gpio {
+			qspi_dat3 {
+				gpio = <4>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat2 {
+				gpio = <5>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat1 {
+				gpio = <6>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat0 {
+				gpio = <7>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_cs_n {
+				gpio = <8>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_clk {
+				gpio = <9>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci0: pci@80000000 {
+		status = "ok";
+		perst_gpio = <18>;
+		mode = "fixed";
+		pci_gpio {
+			pci_rst {
+				gpio = <18>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci1: pci@a0000000 {
+		status = "ok";
+		perst_gpio = <15>;
+		mode = "fixed";
+		pci_gpio {
+			pci_rst {
+				gpio = <15>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	usb0: xhci@8a00000 {
+		usb_pwr_gpio = <24>;
+		usb_gpio {
+			pwr_gpio {
+				gpio = <24>;
+				func = <0>;
+				pull = <GPIO_PULL_UP>;
+				oe = <GPIO_OE_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	gmac_cfg {
+		ext_mdio_gpio = <36 37>;
+		gephy_led = <46>;
+
+		gmac1_cfg {
+			unit = <0>;
+			base = <0x39C00000>;
+			phy_address = <7>;
+			phy_external_link = <0>;
+			mac_pwr = <0xaa545>;
+			s17c_switch_enable = <1>;
+			switch_port_count = <4>;
+			switch_phy_address = <0 1 2 3>;
+		};
+		gmac2_cfg {
+			unit = <1>;
+			base = <0x39D00000>;
+			phy_address = <0x1c>;
+			napa_gpio = <39>;
+		};
+
+	};
+
+};
diff --git a/arch/arm/dts/ipq5018-mp03.4-c1.dts b/arch/arm/dts/ipq5018-mp03.4-c1.dts
new file mode 100644
index 0000000..a122c46
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.4-c1.dts
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "ipq5018-mp03.3.dts"
+/ {
+	model ="QCA, IPQ5018-MP03.4-C1";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.4-c1";
+	machid = <0x8040005>;
+	config_name = "config@mp03.4-c1";
+};
diff --git a/arch/arm/dts/ipq5018-mp03.4-c2.dts b/arch/arm/dts/ipq5018-mp03.4-c2.dts
new file mode 100644
index 0000000..e9e0bc3
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.4-c2.dts
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "ipq5018-mp03.3-c2.dts"
+/ {
+	model ="QCA, IPQ5018-MP03.4-C2";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.4-c2";
+	machid = <0x8040105>;
+	config_name = "config@mp03.4-c2";
+};
diff --git a/arch/arm/dts/ipq5018-mp03.5-c1.dts b/arch/arm/dts/ipq5018-mp03.5-c1.dts
new file mode 100644
index 0000000..45ee452
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.5-c1.dts
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "ipq5018-soc.dtsi"
+/ {
+	model ="QCA, IPQ5018-MP03.5-C1";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.5-c1";
+	machid = <0x8040004>;
+	config_name = "config@mp03.5-c1";
+
+	aliases {
+		console = "/serial@78AF000";
+		mmc = "/sdhci@7804000";
+		i2c0 = "/i2c@78b6000";
+		gmac_gpio = "/gmac_gpio";
+		usb0 = "/xhci@8a00000";
+		pci0 = "/pci@80000000";
+		pci1 = "/pci@a0000000";
+		nand = "/nand-controller@79B0000";
+	};
+
+	console: serial@78AF000 {
+		status = "ok";
+		serial_gpio {
+			blsp0_uart_rx {
+				gpio = <20>;
+				func = <1>;
+				pull = <GPIO_PULL_DOWN>;
+				oe = <GPIO_OE_DISABLE>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_tx {
+				gpio = <21>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OE_DISABLE>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "okay";
+		nand_gpio {
+			qspi_dat3 {
+				gpio = <4>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat2 {
+				gpio = <5>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat1 {
+				gpio = <6>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat0 {
+				gpio = <7>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_cs_n {
+				gpio = <8>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_clk {
+				gpio = <9>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci0: pci@80000000 {
+		status = "ok";
+		perst_gpio = <18>;
+		mode = "fixed";
+		pci_gpio {
+			pci_rst {
+				gpio = <18>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci1: pci@a0000000 {
+		status = "ok";
+		perst_gpio = <15>;
+		mode = "fixed";
+		pci_gpio {
+			pci_rst {
+				gpio = <15>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	usb0: xhci@8a00000 {
+		usb_pwr_gpio = <24>;
+		usb_gpio {
+			pwr_gpio {
+				gpio = <24>;
+				func = <0>;
+				pull = <GPIO_PULL_UP>;
+				oe = <GPIO_OE_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	gmac_cfg {
+		ext_mdio_gpio = <36 37>;
+		gephy_led = <46>;
+
+		gmac1_cfg {
+			unit = <0>;
+			base = <0x39C00000>;
+			phy_address = <7>;
+		};
+		gmac2_cfg {
+			unit = <1>;
+			base = <0x39D00000>;
+			phy_address = <0x1c>;
+			napa_gpio = <39>;
+		};
+
+	};
+
+};
diff --git a/arch/arm/dts/ipq5018-mp03.5-c2.dts b/arch/arm/dts/ipq5018-mp03.5-c2.dts
new file mode 100644
index 0000000..d3390fb
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.5-c2.dts
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include "ipq5018-mp03.5-c1.dts"
+/ {
+	model ="QCA, IPQ5018-MP03.5-C2";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.5-c2";
+	machid = <0x8040104>;
+	config_name = "config@mp03.5-c2";
+
+	mmc: sdhci@7804000 {
+		compatible = "qcom,sdhci-msm";
+		status = "okay";
+		mmc_gpio {
+			emmc_dat3 {
+				gpio = <4>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat2 {
+				gpio = <5>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat1 {
+				gpio = <6>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat0 {
+				gpio = <7>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_cmd{
+				gpio = <8>;
+				func = <1>;
+				pull = <GPIO_PULL_UP>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_clk{
+				gpio = <9>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/dts/ipq5018-mp03.6-c1.dts b/arch/arm/dts/ipq5018-mp03.6-c1.dts
new file mode 100644
index 0000000..03456de
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.6-c1.dts
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "ipq5018-soc.dtsi"
+/ {
+	model ="QCA, IPQ5018-MP03.6-C1";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.6-c1";
+	machid = <0x8040003>;
+	config_name = "config@mp03.6-c1";
+
+	aliases {
+		console = "/serial@78AF000";
+		mmc = "/sdhci@7804000";
+		i2c0 = "/i2c@78b6000";
+		gmac_gpio = "/gmac_gpio";
+		usb0 = "/xhci@8a00000";
+		pci1 = "/pci@a0000000";
+		nand = "/nand-controller@79B0000";
+	};
+
+	console: serial@78AF000 {
+		status = "ok";
+		serial_gpio {
+			blsp0_uart_rx {
+				gpio = <20>;
+				func = <1>;
+				pull = <GPIO_PULL_DOWN>;
+				oe = <GPIO_OE_DISABLE>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_tx {
+				gpio = <21>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OE_DISABLE>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "okay";
+		nand_gpio {
+			qspi_dat3 {
+				gpio = <4>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat2 {
+				gpio = <5>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat1 {
+				gpio = <6>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_dat0 {
+				gpio = <7>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_cs_n {
+				gpio = <8>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			qspi_clk {
+				gpio = <9>;
+				func = <2>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci0: pci@80000000 {
+		status = "ok";
+		perst_gpio = <18>;
+		mode = "fixed";
+		pci_gpio {
+			pci_rst {
+				gpio = <18>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	pci1: pci@a0000000 {
+		status = "ok";
+		perst_gpio = <15>;
+		mode = "fixed";
+		pci_gpio {
+			pci_rst {
+				gpio = <15>;
+				func = <0>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OD_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	usb0: xhci@8a00000 {
+		usb_pwr_gpio = <24>;
+		usb_gpio {
+			pwr_gpio {
+				gpio = <24>;
+				func = <0>;
+				pull = <GPIO_PULL_UP>;
+				oe = <GPIO_OE_ENABLE>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	gmac_cfg {
+		ext_mdio_gpio = <36 37>;
+		gephy_led = <46>;
+
+		gmac1_cfg {
+			unit = <0>;
+			base = <0x39C00000>;
+			phy_address = <7>;
+		};
+		gmac2_cfg {
+			unit = <1>;
+			base = <0x39D00000>;
+			phy_address = <0x1c>;
+			napa_gpio = <39>;
+		};
+
+	};
+
+};
diff --git a/arch/arm/dts/ipq5018-mp03.6-c2.dts b/arch/arm/dts/ipq5018-mp03.6-c2.dts
new file mode 100644
index 0000000..a527e1b
--- /dev/null
+++ b/arch/arm/dts/ipq5018-mp03.6-c2.dts
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include "ipq5018-mp03.6-c1.dts"
+/ {
+	model ="QCA, IPQ5018-MP03.6-C2";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.6-c2";
+	machid = <0x8040103>;
+	config_name = "config@mp03.6-c2";
+
+	mmc: sdhci@7804000 {
+		compatible = "qcom,sdhci-msm";
+		status = "okay";
+		mmc_gpio {
+			emmc_dat3 {
+				gpio = <4>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat2 {
+				gpio = <5>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat1 {
+				gpio = <6>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_dat0 {
+				gpio = <7>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_cmd{
+				gpio = <8>;
+				func = <1>;
+				pull = <GPIO_PULL_UP>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+			emmc_clk{
+				gpio = <9>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				od_en = <GPIO_OD_DISABLE>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/dts/ipq5018-soc.dtsi b/arch/arm/dts/ipq5018-soc.dtsi
new file mode 100644
index 0000000..6579252
--- /dev/null
+++ b/arch/arm/dts/ipq5018-soc.dtsi
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "skeleton.dtsi"
+#include <dt-bindings/qcom/gpio-ipq5018.h>
+
+/ {
+
+	serial@78AF000 {
+		compatible = "qca,ipq-uartdm";
+		reg = <0x78af000 0x200>;
+		m_value = <0x24>;
+		n_value = <0xC31A>;
+		d_value = <0xC2F6>;
+		bit_rate = <0xff>;
+		status = "disabled";
+	};
+
+	timer {
+		gcnt_cntcv_lo = <0x4a2000>;
+		gcnt_cntcv_hi = <0x4a2004>;
+		gpt_freq_hz = <24000000>;
+		timer_load_val = <0x00FFFFFF 0xFFFFFFFF>;
+	};
+
+	spi {
+		compatible = "qcom,spi-qup-v2.7.0";
+		wr_pipe_0 = <4>;
+		rd_pipe_0 = <5>;
+		status = "ok";
+		spi_gpio {
+			blsp0_spi_clk {
+				gpio = <10>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OE_ENABLE>;
+				drvstr = <GPIO_2MA>;
+			};
+			blsp0_spi_mosi {
+				gpio = <11>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				oe = <GPIO_OE_ENABLE>;
+				drvstr = <GPIO_2MA>;
+			};
+			blsp0_spi_miso {
+				gpio = <12>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				drvstr = <GPIO_2MA>;
+			};
+			blsp0_spi_cs {
+				gpio = <13>;
+				func = <1>;
+				oe = <GPIO_OE_ENABLE>;
+				drvstr = <GPIO_2MA>;
+			};
+		};
+	};
+
+	nand: nand-controller@79B0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "qcom,qpic-nand-v2.1.1";
+		reg = <0x79B0000 0x10000>;
+		status = "disabled";
+	};
+
+	i2c0: i2c@78b7000 {
+		compatible = "qcom,qup-i2c";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x78b7000 0x600>;
+		clock-frequency  = <400000>;
+
+		i2c_gpio {
+			i2c_scl {
+				gpio = <25>;
+				func = <3>;
+				pull = <GPIO_NO_PULL>;
+				drvstr = <GPIO_8MA>;
+			};
+
+			i2c_sda{
+				gpio = <26>;
+				func = <3>;
+				pull = <GPIO_NO_PULL>;
+				drvstr = <GPIO_8MA>;
+			};
+		};
+	};
+
+	xhci@8a00000 {
+		compatible = "qca,dwc3-ipq";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x8a00000 0xe000>;
+	};
+
+	pci@80000000 {
+		compatible = "qcom,ipq5018-pcie";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x80000000 0xf1d
+			0x78000 0x3000
+			0x80000F20 0xa8
+			0x80001000 0x1000
+			0x80300000 0xd00000
+			0x80100000 0x100000
+			0x01875004 0x40
+			0x7e000 0x800>;
+		reg-names = "pci_dbi", "parf", "elbi","dm_iatu", "axi_bars",
+				"axi_conf", "pci_rst", "pci_phy";
+		gen3 = <1>;
+		lane = <1>;
+		status = "disabled";
+		skip_phy_int = <1>;
+	};
+
+	pci@a0000000 {
+		compatible = "qcom,ipq5018-pcie";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xa0000000 0xf1d
+			0x80000 0x3000
+			0xa0000F20 0xa8
+			0xa0001000 0x1000
+			0xa0300000 0xd00000
+			0xa0100000 0x100000
+			0x01876004 0x40
+			0x86000 0x1000>;
+		reg-names = "pci_dbi", "parf", "elbi","dm_iatu", "axi_bars",
+				"axi_conf", "pci_rst", "pci_phy";
+		gen3 = <1>;
+		lane = <2>;
+		status = "disabled";
+		skip_phy_int = <1>;
+	};
+};
diff --git a/arch/arm/dts/ipq5018-sod.dts b/arch/arm/dts/ipq5018-sod.dts
new file mode 100644
index 0000000..38402d8
--- /dev/null
+++ b/arch/arm/dts/ipq5018-sod.dts
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "skeleton.dtsi"
+#include <dt-bindings/qcom/gpio-ipq5018.h>
+/ {
+	model ="QCA, IPQ5018-MP03.1";
+	compatible = "qca,ipq5018", "qca,ipq5018-mp03.1";
+	machid = <0x8040001>;
+	config_name = "config@mp03.1";
+
+	serial@78AF000 {
+		compatible = "qca,ipq-uartdm";
+		reg = <0x78af000 0x200>;
+		m_value = <0x24>;
+		n_value = <0xC31A>;
+		d_value = <0xC2F6>;
+		bit_rate = <0xff>;
+		status = "ok";
+		serial_gpio {
+			blsp0_uart_rx {
+				gpio = <20>;
+				func = <1>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+			blsp0_uart_tx {
+				gpio = <21>;
+				func = <1>;
+				pull = <GPIO_NO_PULL>;
+				drvstr = <GPIO_8MA>;
+				od_en = <GPIO_OD_DISABLE>;
+			};
+		};
+	};
+
+	timer {
+		gcnt_cntcv_lo = <0x4a2000>;
+		gcnt_cntcv_hi = <0x4a2004>;
+		gpt_freq_hz = <24000000>;
+		timer_load_val = <0x00FFFFFF 0xFFFFFFFF>;
+	};
+
+	aliases {
+		console = "/serial@78AF000";
+	};
+
+
+};
diff --git a/arch/arm/dts/ipq5018-tb-mp04.dts b/arch/arm/dts/ipq5018-tb-mp04.dts
new file mode 100644
index 0000000..4f610c6
--- /dev/null
+++ b/arch/arm/dts/ipq5018-tb-mp04.dts
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "ipq5018-mp03.3.dts"
+/ {
+	model ="QCA, IPQ5018-TB-MP04";
+	compatible = "qca,ipq5018", "qca,ipq5018-tb-mp04";
+	machid = <0x1040006>;
+	config_name = "config@tb-mp04";
+};
diff --git a/arch/arm/dts/ipq6018-cp01-c3.dts b/arch/arm/dts/ipq6018-cp01-c3.dts
deleted file mode 100644
index 5ec79ae..0000000
--- a/arch/arm/dts/ipq6018-cp01-c3.dts
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-/dts-v1/;
-#include "ipq6018-soc.dtsi"
-/ {
-	machid = <0x8030002>;
-	config_name = "config@cp01-c3";
-
-	aliases {
-		console = "/serial@78B1000";
-		pci0 = "/pci@20000000";
-		usb0 = "/xhci@8a00000";
-		usb1 = "/xhci@7000000";
-		i2c1 = "/i2c@78ba000";
-		i2c0 = "/i2c@78b7000";
-	};
-	i2c0: i2c@78b7000 {
-		compatible = "qcom,qup-i2c";
-		#address-cells = <1>;
-		#size-cells = <0>;
-		reg = <0x78b7000 0x600>;
-		clock-frequency  = <400000>;
-
-		i2c_gpio {
-			gpio1 {
-				gpio = <42>;
-				func = <2>;
-				pull = <GPIO_PULL_UP>;
-				drvstr = <GPIO_8MA>;
-				oe = <GPIO_OE_ENABLE>;
-			};
-
-			gpio2 {
-				gpio = <43>;
-				func = <2>;
-				pull = <GPIO_PULL_UP>;
-				drvstr = <GPIO_8MA>;
-				oe = <GPIO_OE_ENABLE>;
-			};
-		};
-	};
-	ess-switch {
-		switch_mac_mode = <PORT_WRAPPER_PSGMII>;
-		switch_mac_mode1 = <PORT_WRAPPER_SGMII_PLUS>;
-		napa_gpio = <77>;
-		napa_gpio_cnt = <1>;
-		malibu_gpio = <75>;
-		malibu_gpio_cnt = <1>;
-		mdc_mdio_gpio = <64 65>;
-		port_phyinfo {
-			port@0 {
-				phy_address = <0>;
-				phy_type = <MALIBU_PHY_TYPE>;
-			};
-			port@1 {
-				phy_address = <1>;
-				phy_type = <MALIBU_PHY_TYPE>;
-			};
-			port@2 {
-				phy_address = <2>;
-				phy_type = <MALIBU_PHY_TYPE>;
-			};
-			port@3 {
-				phy_address = <3>;
-				phy_type = <MALIBU_PHY_TYPE>;
-			};
-			port@4 {
-				phy_address = <24>;
-				phy_type = <QCA8081_PHY_TYPE>;
-			};
-		};
-	};
-};
diff --git a/arch/arm/dts/ipq6018-soc.dtsi b/arch/arm/dts/ipq6018-soc.dtsi
index 17ce853..52f7e6a 100644
--- a/arch/arm/dts/ipq6018-soc.dtsi
+++ b/arch/arm/dts/ipq6018-soc.dtsi
@@ -22,6 +22,9 @@
 		reg = <0x78B1000 0x200>;
 		id = <4>;
 		bit_rate = <0xff>;
+		m_value = <36>;
+		n_value = <15625>;
+		d_value = <15625>;
 		serial_gpio {
 			gpio1 {
 				gpio = <44>;
diff --git a/arch/arm/dts/ipq807x-hk01-c3.dts b/arch/arm/dts/ipq807x-hk01-c3.dts
deleted file mode 100644
index 5c1050a..0000000
--- a/arch/arm/dts/ipq807x-hk01-c3.dts
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-/dts-v1/;
-#include "ipq807x-soc.dtsi"
-#include <dt-bindings/qcom/gpio-ipq807x.h>
-/ {
-	machid = <0x08010200>;
-	config_name = "config@hk01.c3";
-
-	aliases {
-		console = "/serial@78B3000";
-		uart2 = "/serial@78B0000";
-		i2c0 = "/i2c@78b6000";
-		pci0 = "/pci@20000000";
-		pci1 = "/pci@10000000";
-		mmc = "/sdhci@07824000";
-	};
-	ess-switch {
-		switch_mac_mode = <0x0>;
-		switch_mac_mode1 = <0xFF>;
-		switch_mac_mode2 = <0x2>;
-		aquantia_port = <5>;
-		aquantia_gpio = <44>;
-	};
-};
-
diff --git a/arch/arm/dts/ipq807x-hk01.dts b/arch/arm/dts/ipq807x-hk01.dts
index 7d0afcb..19eb620 100644
--- a/arch/arm/dts/ipq807x-hk01.dts
+++ b/arch/arm/dts/ipq807x-hk01.dts
@@ -16,7 +16,7 @@
 #include <dt-bindings/qcom/gpio-ipq807x.h>
 / {
 	machid = <0x08010000>;
-	config_name = "config@hk01";
+	config_name = "config@hk01", "config@hk01.c1";
 
 	aliases {
 		console = "/serial@78B3000";
diff --git a/arch/arm/dts/ipq807x-hk05.dts b/arch/arm/dts/ipq807x-hk05.dts
deleted file mode 100644
index 88a5a3d..0000000
--- a/arch/arm/dts/ipq807x-hk05.dts
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-/dts-v1/;
-#include "ipq807x-soc.dtsi"
-#include <dt-bindings/qcom/gpio-ipq807x.h>
-/ {
-	machid = <0x080100002>;
-	config_name = "config@hk05";
-
-	aliases {
-		console = "/serial@78B3000";
-		i2c0 = "/i2c@78b6000";
-		pci0 = "/pci@20000000";
-		pci1 = "/pci@10000000";
-	};
-};
-
diff --git a/arch/arm/dts/ipq807x-hk10.dts b/arch/arm/dts/ipq807x-hk10.dts
index c9d3f7d..7c47d22 100644
--- a/arch/arm/dts/ipq807x-hk10.dts
+++ b/arch/arm/dts/ipq807x-hk10.dts
@@ -28,9 +28,11 @@
 	ess-switch {
 		switch_mac_mode = <0x0>;
 		switch_mac_mode1 = <0x2>;
-		switch_mac_mode2 = <0x6>;
+		switch_mac_mode2 = <0x7>;
 		aquantia_port = <4>;
 		aquantia_gpio = <44>;
+		sfp_port = <5>;
+		sfp_gpio = <59>;
 		port_phyinfo {
 			port@0 {
 				phy_address = <0>;
@@ -52,6 +54,10 @@
 				phy_address = <7>;
 				phy_type = <3>;
 			};
+			port@5 {
+				phy_address = <30>;
+				phy_type = <5>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/dts/ipq807x-ac02.dts b/arch/arm/dts/ipq807x-hk14.dts
similarity index 74%
rename from arch/arm/dts/ipq807x-ac02.dts
rename to arch/arm/dts/ipq807x-hk14.dts
index d9b186c..581af01 100644
--- a/arch/arm/dts/ipq807x-ac02.dts
+++ b/arch/arm/dts/ipq807x-hk14.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 - 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016 - 2020, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,8 +15,8 @@
 #include "ipq807x-soc.dtsi"
 #include <dt-bindings/qcom/gpio-ipq807x.h>
 / {
-	machid = <0x0801000A>;
-	config_name = "config@ac02";
+	machid = <0x08010012>;
+	config_name = "config@hk14";
 
 	aliases {
 		console = "/serial@78B3000";
@@ -24,11 +24,11 @@
 		pci0 = "/pci@20000000";
 	};
 	ess-switch {
-		switch_mac_mode = <0x0>;
-		switch_mac_mode1 = <0x6>;
-		switch_mac_mode2 = <0x6>;
-		napa_gpio = <25 44>;
-		napa_gpio_cnt = <2>;
+		switch_mac_mode = <0x5>;
+		switch_mac_mode1 = <0xFF>;
+		switch_mac_mode2 = <0x2>;
+		aquantia_port = <5>;
+		aquantia_gpio = <44>;
 		port_phyinfo {
 			port@0 {
 				phy_address = <0>;
@@ -47,13 +47,14 @@
 				phy_type = <1>;
 			};
 			port@4 {
-				phy_address = <24>;
-				phy_type = <2>;
+				phy_address = <4>;
+				phy_type = <1>;
 			};
 			port@5 {
-				phy_address = <28>;
-				phy_type = <2>;
+				phy_address = <7>;
+				phy_type = <3>;
 			};
+
 		};
 	};
 };
diff --git a/arch/arm/dts/ipq807x-oak03.dts b/arch/arm/dts/ipq807x-oak03.dts
deleted file mode 100644
index b594972..0000000
--- a/arch/arm/dts/ipq807x-oak03.dts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2016 - 2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-/dts-v1/;
-#include "ipq807x-soc.dtsi"
-#include <dt-bindings/qcom/gpio-ipq807x.h>
-/ {
-	machid = <0x0801000D>;
-	config_name = "config@oak03";
-
-	aliases {
-		console = "/serial@78B3000";
-		uart2 = "/serial@78B0000";
-		i2c0 = "/i2c@78b6000";
-		pci0 = "/pci@20000000";
-		pci1 = "/pci@10000000";
-		mmc = "/sdhci@07824000";
-	};
-	ess-switch {
-		switch_mac_mode = <0x0>;
-		switch_mac_mode1 = <0xFF>;
-		switch_mac_mode2 = <0x2>;
-		aquantia_port = <5>;
-		aquantia_gpio = <44>;
-	};
-
-};
-
diff --git a/arch/arm/include/asm/arch-ipq5018/athrs17_phy.h b/arch/arm/include/asm/arch-ipq5018/athrs17_phy.h
new file mode 100644
index 0000000..cf73988
--- /dev/null
+++ b/arch/arm/include/asm/arch-ipq5018/athrs17_phy.h
@@ -0,0 +1,607 @@
+/*
+ * Copyright (c) 2015-2016, 2020 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ATHRS17_PHY_H
+#define _ATHRS17_PHY_H
+
+/*****************/
+/* PHY Registers */
+/*****************/
+#define ATHR_PHY_CONTROL                 0
+#define ATHR_PHY_STATUS                  1
+#define ATHR_PHY_ID1                     2
+#define ATHR_PHY_ID2                     3
+#define ATHR_AUTONEG_ADVERT              4
+#define ATHR_LINK_PARTNER_ABILITY        5
+#define ATHR_AUTONEG_EXPANSION           6
+#define ATHR_NEXT_PAGE_TRANSMIT          7
+#define ATHR_LINK_PARTNER_NEXT_PAGE      8
+#define ATHR_1000BASET_CONTROL           9
+#define ATHR_1000BASET_STATUS            10
+#define ATHR_PHY_SPEC_CONTROL            16
+#define ATHR_PHY_SPEC_STATUS             17
+#define ATHR_DEBUG_PORT_ADDRESS          29
+#define ATHR_DEBUG_PORT_DATA             30
+
+/* ATHR_PHY_CONTROL fields */
+#define ATHR_CTRL_SOFTWARE_RESET                    0x8000
+#define ATHR_CTRL_SPEED_LSB                         0x2000
+#define ATHR_CTRL_AUTONEGOTIATION_ENABLE            0x1000
+#define ATHR_CTRL_RESTART_AUTONEGOTIATION           0x0200
+#define ATHR_CTRL_SPEED_FULL_DUPLEX                 0x0100
+#define ATHR_CTRL_SPEED_MSB                         0x0040
+
+#define ATHR_RESET_DONE(phy_control)                   \
+	(((phy_control) & (ATHR_CTRL_SOFTWARE_RESET)) == 0)
+
+/* Phy status fields */
+#define ATHR_STATUS_AUTO_NEG_DONE                   0x0020
+
+#define ATHR_AUTONEG_DONE(ip_phy_status)                   \
+	(((ip_phy_status) &                                \
+	(ATHR_STATUS_AUTO_NEG_DONE)) ==                    \
+	(ATHR_STATUS_AUTO_NEG_DONE))
+
+/* Link Partner ability */
+#define ATHR_LINK_100BASETX_FULL_DUPLEX       0x0100
+#define ATHR_LINK_100BASETX                   0x0080
+#define ATHR_LINK_10BASETX_FULL_DUPLEX        0x0040
+#define ATHR_LINK_10BASETX                    0x0020
+
+/* Advertisement register. */
+#define ATHR_ADVERTISE_NEXT_PAGE              0x8000
+#define ATHR_ADVERTISE_ASYM_PAUSE             0x0800
+#define ATHR_ADVERTISE_PAUSE                  0x0400
+#define ATHR_ADVERTISE_100FULL                0x0100
+#define ATHR_ADVERTISE_100HALF                0x0080
+#define ATHR_ADVERTISE_10FULL                 0x0040
+#define ATHR_ADVERTISE_10HALF                 0x0020
+
+#define ATHR_ADVERTISE_ALL (ATHR_ADVERTISE_ASYM_PAUSE | ATHR_ADVERTISE_PAUSE | \
+		ATHR_ADVERTISE_10HALF | ATHR_ADVERTISE_10FULL | \
+		ATHR_ADVERTISE_100HALF | ATHR_ADVERTISE_100FULL)
+
+/* 1000BASET_CONTROL */
+#define ATHR_ADVERTISE_1000FULL               0x0200
+
+/* Phy Specific status fields */
+#define ATHER_STATUS_LINK_MASK                0xC000
+#define ATHER_STATUS_LINK_SHIFT               14
+#define ATHER_STATUS_FULL_DEPLEX              0x2000
+#define ATHR_STATUS_LINK_PASS                 0x0400
+#define ATHR_STATUS_RESOVLED                  0x0800
+
+/*phy debug port  register */
+#define ATHER_DEBUG_SERDES_REG                5
+
+/* Serdes debug fields */
+#define ATHER_SERDES_BEACON                   0x0100
+
+/* S17 CSR Registers */
+
+#define S17_ENABLE_CPU_BROADCAST             (1 << 26)
+
+#define S17_PHY_LINK_CHANGE_REG              0x4
+#define S17_PHY_LINK_UP                      0x400
+#define S17_PHY_LINK_DOWN                    0x800
+#define S17_PHY_LINK_DUPLEX_CHANGE           0x2000
+#define S17_PHY_LINK_SPEED_CHANGE            0x4000
+#define S17_PHY_LINK_INTRS                   (PHY_LINK_UP | PHY_LINK_DOWN | PHY_LINK_DUPLEX_CHANGE | PHY_LINK_SPEED_CHANGE)
+
+#define S17_MASK_CTRL_REG               0x0000
+#define S17_P0PAD_MODE_REG              0x0004
+#define S17_P5PAD_MODE_REG              0x0008
+#define S17_P6PAD_MODE_REG              0x000c
+#define S17_PWS_REG                     0x0010
+#define S17_GLOBAL_INT0_REG             0x0020
+#define S17_GLOBAL_INT1_REG             0x0024
+#define S17_GLOBAL_INTMASK0             0x0028
+#define S17_GLOBAL_INTMASK1             0x002c
+#define S17_MODULE_EN_REG               0x0030
+#define S17_MIB_REG                     0x0034
+#define S17_INTF_HIADDR_REG             0x0038
+#define S17_MDIO_CTRL_REG               0x003c
+#define S17_BIST_CTRL_REG               0x0040
+#define S17_BIST_REC_REG                0x0044
+#define S17_SERVICE_REG                 0x0048
+#define S17_LED_CTRL0_REG               0x0050
+#define S17_LED_CTRL1_REG               0x0054
+#define S17_LED_CTRL2_REG               0x0058
+#define S17_LED_CTRL3_REG               0x005c
+#define S17_MACADDR0_REG                0x0060
+#define S17_MACADDR1_REG                0x0064
+#define S17_MAX_FRAME_SIZE_REG          0x0078
+#define S17_P0STATUS_REG                0x007c
+#define S17_P1STATUS_REG                0x0080
+#define S17_P2STATUS_REG                0x0084
+#define S17_P3STATUS_REG                0x0088
+#define S17_P4STATUS_REG                0x008c
+#define S17_P5STATUS_REG                0x0090
+#define S17_P6STATUS_REG                0x0094
+#define S17_HDRCTRL_REG                 0x0098
+#define S17_P0HDRCTRL_REG               0x009c
+#define S17_P1HDRCTRL_REG               0x00A0
+#define S17_P2HDRCTRL_REG               0x00a4
+#define S17_P3HDRCTRL_REG               0x00a8
+#define S17_P4HDRCTRL_REG               0x00ac
+#define S17_P5HDRCTRL_REG               0x00b0
+#define S17_P6HDRCTRL_REG               0x00b4
+#define S17_SGMII_CTRL_REG              0x00e0
+#define S17_MAC_PWR_REG                 0x00e4
+#define S17_EEE_CTRL_REG                0x0100
+
+/* ACL Registers */
+#define S17_ACL_FUNC0_REG               0x0400
+#define S17_ACL_FUNC1_REG               0x0404
+#define S17_ACL_FUNC2_REG               0x0408
+#define S17_ACL_FUNC3_REG               0x040c
+#define S17_ACL_FUNC4_REG               0x0410
+#define S17_ACL_FUNC5_REG               0x0414
+#define S17_PRIVATE_IP_REG              0x0418
+#define S17_P0VLAN_CTRL0_REG            0x0420
+#define S17_P0VLAN_CTRL1_REG            0x0424
+#define S17_P1VLAN_CTRL0_REG            0x0428
+#define S17_P1VLAN_CTRL1_REG            0x042c
+#define S17_P2VLAN_CTRL0_REG            0x0430
+#define S17_P2VLAN_CTRL1_REG            0x0434
+#define S17_P3VLAN_CTRL0_REG            0x0438
+#define S17_P3VLAN_CTRL1_REG            0x043c
+#define S17_P4VLAN_CTRL0_REG            0x0440
+#define S17_P4VLAN_CTRL1_REG            0x0444
+#define S17_P5VLAN_CTRL0_REG            0x0448
+#define S17_P5VLAN_CTRL1_REG            0x044c
+#define S17_P6VLAN_CTRL0_REG            0x0450
+#define S17_P6VLAN_CTRL1_REG            0x0454
+
+/* Table Lookup Registers */
+#define S17_ATU_DATA0_REG               0x0600
+#define S17_ATU_DATA1_REG               0x0604
+#define S17_ATU_DATA2_REG               0x0608
+#define S17_ATU_FUNC_REG                0x060C
+#define S17_VTU_FUNC0_REG               0x0610
+#define S17_VTU_FUNC1_REG               0x0614
+#define S17_ARL_CTRL_REG                0x0618
+#define S17_GLOFW_CTRL0_REG             0x0620
+#define S17_GLOFW_CTRL1_REG             0x0624
+#define S17_GLOLEARN_LIMIT_REG          0x0628
+#define S17_TOS_PRIMAP_REG0             0x0630
+#define S17_TOS_PRIMAP_REG1             0x0634
+#define S17_TOS_PRIMAP_REG2             0x0638
+#define S17_TOS_PRIMAP_REG3             0x063c
+#define S17_TOS_PRIMAP_REG4             0x0640
+#define S17_TOS_PRIMAP_REG5             0x0644
+#define S17_TOS_PRIMAP_REG6             0x0648
+#define S17_TOS_PRIMAP_REG7             0x064c
+#define S17_VLAN_PRIMAP_REG0            0x0650
+#define S17_LOOP_CHECK_REG              0x0654
+#define S17_P0LOOKUP_CTRL_REG           0x0660
+#define S17_P0PRI_CTRL_REG              0x0664
+#define S17_P0LEARN_LMT_REG             0x0668
+#define S17_P1LOOKUP_CTRL_REG           0x066c
+#define S17_P1PRI_CTRL_REG              0x0670
+#define S17_P1LEARN_LMT_REG             0x0674
+#define S17_P2LOOKUP_CTRL_REG           0x0678
+#define S17_P2PRI_CTRL_REG              0x067c
+#define S17_P2LEARN_LMT_REG             0x0680
+#define S17_P3LOOKUP_CTRL_REG           0x0684
+#define S17_P3PRI_CTRL_REG              0x0688
+#define S17_P3LEARN_LMT_REG             0x068c
+#define S17_P4LOOKUP_CTRL_REG           0x0690
+#define S17_P4PRI_CTRL_REG              0x0694
+#define S17_P4LEARN_LMT_REG             0x0698
+#define S17_P5LOOKUP_CTRL_REG           0x069c
+#define S17_P5PRI_CTRL_REG              0x06a0
+#define S17_P5LEARN_LMT_REG             0x06a4
+#define S17_P6LOOKUP_CTRL_REG           0x06a8
+#define S17_P6PRI_CTRL_REG              0x06ac
+#define S17_P6LEARN_LMT_REG             0x06b0
+#define S17_GLO_TRUNK_CTRL0_REG         0x0700
+#define S17_GLO_TRUNK_CTRL1_REG         0x0704
+#define S17_GLO_TRUNK_CTRL2_REG         0x0708
+
+/* Queue Management Registers */
+#define S17_PORT0_HOL_CTRL0             0x0970
+#define S17_PORT0_HOL_CTRL1             0x0974
+#define S17_PORT1_HOL_CTRL0             0x0978
+#define S17_PORT1_HOL_CTRL1             0x097c
+#define S17_PORT2_HOL_CTRL0             0x0980
+#define S17_PORT2_HOL_CTRL1             0x0984
+#define S17_PORT3_HOL_CTRL0             0x0988
+#define S17_PORT3_HOL_CTRL1             0x098c
+#define S17_PORT4_HOL_CTRL0             0x0990
+#define S17_PORT4_HOL_CTRL1             0x0994
+#define S17_PORT5_HOL_CTRL0             0x0998
+#define S17_PORT5_HOL_CTRL1             0x099c
+#define S17_PORT6_HOL_CTRL0             0x09a0
+#define S17_PORT6_HOL_CTRL1             0x09a4
+
+/* Port flow control registers */
+#define S17_P0_FLCTL_REG                0x09b0
+#define S17_P1_FLCTL_REG                0x09b4
+#define S17_P2_FLCTL_REG                0x09b8
+#define S17_P3_FLCTL_REG                0x09bc
+#define S17_P4_FLCTL_REG                0x09c0
+#define S17_P5_FLCTL_REG                0x09c4
+
+/* Packet Edit registers */
+#define S17_PKT_EDIT_CTRL               0x0c00
+#define S17_P0Q_REMAP_REG0              0x0c40
+#define S17_P0Q_REMAP_REG1              0x0c44
+#define S17_P1Q_REMAP_REG0              0x0c48
+#define S17_P2Q_REMAP_REG0              0x0c4c
+#define S17_P3Q_REMAP_REG0              0x0c50
+#define S17_P4Q_REMAP_REG0              0x0c54
+#define S17_P5Q_REMAP_REG0              0x0c58
+#define S17_P5Q_REMAP_REG1              0x0c5c
+#define S17_P6Q_REMAP_REG0              0x0c60
+#define S17_P6Q_REMAP_REG1              0x0c64
+#define S17_ROUTER_VID0                 0x0c70
+#define S17_ROUTER_VID1                 0x0c74
+#define S17_ROUTER_VID2                 0x0c78
+#define S17_ROUTER_VID3                 0x0c7c
+#define S17_ROUTER_EG_VLAN_MODE         0x0c80
+
+/* L3 Registers */
+#define S17_HROUTER_CTRL_REG            0x0e00
+#define S17_HROUTER_PBCTRL0_REG         0x0e04
+#define S17_HROUTER_PBCTRL1_REG         0x0e08
+#define S17_HROUTER_PBCTRL2_REG         0x0e0c
+#define S17_WCMP_HASH_TABLE0_REG        0x0e10
+#define S17_WCMP_HASH_TABLE1_REG        0x0e14
+#define S17_WCMP_HASH_TABLE2_REG        0x0e18
+#define S17_WCMP_HASH_TABLE3_REG        0x0e1c
+#define S17_WCMP_NHOP_TABLE0_REG        0x0e20
+#define S17_WCMP_NHOP_TABLE1_REG        0x0e24
+#define S17_WCMP_NHOP_TABLE2_REG        0x0e28
+#define S17_WCMP_NHOP_TABLE3_REG        0x0e2c
+#define S17_ARP_ENTRY_CTRL_REG          0x0e30
+#define S17_ARP_USECNT_REG              0x0e34
+#define S17_HNAT_CTRL_REG               0x0e38
+#define S17_NAPT_ENTRY_CTRL0_REG        0x0e3c
+#define S17_NAPT_ENTRY_CTRL1_REG        0x0e40
+#define S17_NAPT_USECNT_REG             0x0e44
+#define S17_ENTRY_EDIT_DATA0_REG        0x0e48
+#define S17_ENTRY_EDIT_DATA1_REG        0x0e4c
+#define S17_ENTRY_EDIT_DATA2_REG        0x0e50
+#define S17_ENTRY_EDIT_DATA3_REG        0x0e54
+#define S17_ENTRY_EDIT_CTRL_REG         0x0e58
+#define S17_HNAT_PRIVATE_IP_REG         0x0e5c
+
+/* MIB counters */
+#define S17_MIB_PORT0                   0x1000
+#define S17_MIB_PORT1                   0x1100
+#define S17_MIB_PORT2                   0x1200
+#define S17_MIB_PORT3                   0x1300
+#define S17_MIB_PORT4                   0x1400
+#define S17_MIB_PORT5                   0x1500
+#define S17_MIB_PORT6                   0x1600
+
+#define S17_MIB_COUNTER_ENABLE		(1 << 0)
+#define S17_MIB_NON_CLEAR		(1 << 20)
+
+#define S17_MIB_RXBROAD                 0x0
+#define S17_MIB_RXPAUSE                 0x4
+#define S17_MIB_RXMULTI                 0x8
+#define S17_MIB_RXFCSERR                0xC
+#define S17_MIB_RXALIGNERR              0x10
+#define S17_MIB_RXUNDERSIZE             0x14
+#define S17_MIB_RXFRAG                  0x18
+#define S17_MIB_RX64B                   0x1C
+#define S17_MIB_RX128B                  0x20
+#define S17_MIB_RX256B                  0x24
+#define S17_MIB_RX512B                  0x28
+#define S17_MIB_RX1024B                 0x2C
+#define S17_MIB_RX1518B                 0x30
+#define S17_MIB_RXMAXB                  0x34
+#define S17_MIB_RXTOOLONG               0x38
+#define S17_MIB_RXBYTE1                 0x3C
+#define S17_MIB_RXBYTE2                 0x40
+#define S17_MIB_RXOVERFLOW              0x4C
+#define S17_MIB_FILTERED                0x50
+#define S17_MIB_TXBROAD                 0x54
+#define S17_MIB_TXPAUSE                 0x58
+#define S17_MIB_TXMULTI                 0x5C
+#define S17_MIB_TXUNDERRUN              0x60
+#define S17_MIB_TX64B                   0x64
+#define S17_MIB_TX128B                  0x68
+#define S17_MIB_TX256B                  0x6c
+#define S17_MIB_TX512B                  0x70
+#define S17_MIB_TX1024B                 0x74
+#define S17_MIB_TX1518B                 0x78
+#define S17_MIB_TXMAXB                  0x7C
+#define S17_MIB_TXOVERSIZE              0x80
+#define S17_MIB_TXBYTE1                 0x84
+#define S17_MIB_TXBYTE2                 0x88
+#define S17_MIB_TXCOL                   0x8C
+#define S17_MIB_TXABORTCOL              0x90
+#define S17_MIB_TXMULTICOL              0x94
+#define S17_MIB_TXSINGLECOL             0x98
+#define S17_MIB_TXEXCDEFER              0x9C
+#define S17_MIB_TXDEFER                 0xA0
+#define S17_MIB_TXLATECOL               0xA4
+
+/* Register fields */
+#define S17_CHIPID_V1_0                 0x1201
+#define S17_CHIPID_V1_1                 0x1202
+
+#define S17_MASK_CTRL_SOFT_RET		(1 << 31)
+
+#define S17_GLOBAL_INT0_ACL_INI_INT        (1<<29)
+#define S17_GLOBAL_INT0_LOOKUP_INI_INT     (1<<28)
+#define S17_GLOBAL_INT0_QM_INI_INT         (1<<27)
+#define S17_GLOBAL_INT0_MIB_INI_INT        (1<<26)
+#define S17_GLOBAL_INT0_OFFLOAD_INI_INT    (1<<25)
+#define S17_GLOBAL_INT0_HARDWARE_INI_DONE  (1<<24)
+
+#define S17_GLOBAL_INITIALIZED_STATUS 				\
+			(					\
+			S17_GLOBAL_INT0_ACL_INI_INT | 		\
+			S17_GLOBAL_INT0_LOOKUP_INI_INT | 	\
+			S17_GLOBAL_INT0_QM_INI_INT | 		\
+			S17_GLOBAL_INT0_MIB_INI_INT | 		\
+			S17_GLOBAL_INT0_OFFLOAD_INI_INT |	\
+			S17_GLOBAL_INT0_HARDWARE_INI_DONE	\
+			)
+
+#define S17_MAC0_MAC_MII_RXCLK_SEL      (1 << 0)
+#define S17_MAC0_MAC_MII_TXCLK_SEL      (1 << 1)
+#define S17_MAC0_MAC_MII_EN             (1 << 2)
+#define S17_MAC0_MAC_GMII_RXCLK_SEL     (1 << 4)
+#define S17_MAC0_MAC_GMII_TXCLK_SEL     (1 << 5)
+#define S17_MAC0_MAC_GMII_EN            (1 << 6)
+#define S17_MAC0_SGMII_EN               (1 << 7)
+#define S17_MAC0_PHY_MII_RXCLK_SEL      (1 << 8)
+#define S17_MAC0_PHY_MII_TXCLK_SEL      (1 << 9)
+#define S17_MAC0_PHY_MII_EN             (1 << 10)
+#define S17_MAC0_PHY_MII_PIPE_SEL       (1 << 11)
+#define S17_MAC0_PHY_GMII_RXCLK_SEL     (1 << 12)
+#define S17_MAC0_PHY_GMII_TXCLK_SEL     (1 << 13)
+#define S17_MAC0_PHY_GMII_EN            (1 << 14)
+#define S17_MAC0_RGMII_RXCLK_SHIFT      20
+#define S17_MAC0_RGMII_TXCLK_SHIFT      22
+#define S17_MAC0_RGMII_RXCLK_DELAY      (1 << 24)
+#define S17_MAC0_RGMII_TXCLK_DELAY      (1 << 25)
+#define S17_MAC0_RGMII_EN               (1 << 26)
+
+#define S17_MAC5_MAC_MII_RXCLK_SEL      (1 << 0)
+#define S17_MAC5_MAC_MII_TXCLK_SEL      (1 << 1)
+#define S17_MAC5_MAC_MII_EN             (1 << 2)
+#define S17_MAC5_PHY_MII_RXCLK_SEL      (1 << 8)
+#define S17_MAC5_PHY_MII_TXCLK_SEL      (1 << 9)
+#define S17_MAC5_PHY_MII_EN             (1 << 10)
+#define S17_MAC5_PHY_MII_PIPE_SEL       (1 << 11)
+#define S17_MAC5_RGMII_RXCLK_SHIFT      20
+#define S17_MAC5_RGMII_TXCLK_SHIFT      22
+#define S17_MAC5_RGMII_RXCLK_DELAY      (1 << 24)
+#define S17_MAC5_RGMII_TXCLK_DELAY      (1 << 25)
+#define S17_MAC5_RGMII_EN               (1 << 26)
+
+#define S17_MAC6_MAC_MII_RXCLK_SEL      (1 << 0)
+#define S17_MAC6_MAC_MII_TXCLK_SEL      (1 << 1)
+#define S17_MAC6_MAC_MII_EN             (1 << 2)
+#define S17_MAC6_MAC_GMII_RXCLK_SEL     (1 << 4)
+#define S17_MAC6_MAC_GMII_TXCLK_SEL     (1 << 5)
+#define S17_MAC6_MAC_GMII_EN            (1 << 6)
+#define S17_MAC6_SGMII_EN               (1 << 7)
+#define S17_MAC6_PHY_MII_RXCLK_SEL      (1 << 8)
+#define S17_MAC6_PHY_MII_TXCLK_SEL      (1 << 9)
+#define S17_MAC6_PHY_MII_EN             (1 << 10)
+#define S17_MAC6_PHY_MII_PIPE_SEL       (1 << 11)
+#define S17_MAC6_PHY_GMII_RXCLK_SEL     (1 << 12)
+#define S17_MAC6_PHY_GMII_TXCLK_SEL     (1 << 13)
+#define S17_MAC6_PHY_GMII_EN            (1 << 14)
+#define S17_PHY4_GMII_EN                (1 << 16)
+#define S17_PHY4_RGMII_EN               (1 << 17)
+#define S17_PHY4_MII_EN                 (1 << 18)
+#define S17_MAC6_RGMII_RXCLK_SHIFT      20
+#define S17_MAC6_RGMII_TXCLK_SHIFT      22
+#define S17_MAC6_RGMII_RXCLK_DELAY      (1 << 24)
+#define S17_MAC6_RGMII_TXCLK_DELAY      (1 << 25)
+#define S17_MAC6_RGMII_EN               (1 << 26)
+
+#define S17_SPEED_10M                   (0 << 0)
+#define S17_SPEED_100M                  (1 << 0)
+#define S17_SPEED_1000M                 (2 << 0)
+#define S17_TXMAC_EN                    (1 << 2)
+#define S17_RXMAC_EN                    (1 << 3)
+#define S17_TX_FLOW_EN                  (1 << 4)
+#define S17_RX_FLOW_EN                  (1 << 5)
+#define S17_DUPLEX_FULL                 (1 << 6)
+#define S17_DUPLEX_HALF                 (0 << 6)
+#define S17_TX_HALF_FLOW_EN             (1 << 7)
+#define S17_LINK_EN                     (1 << 9)
+#define S17_FLOW_LINK_EN                (1 << 12)
+#define S17_PORT_STATUS_DEFAULT         (S17_SPEED_1000M | S17_TXMAC_EN | \
+                                        S17_RXMAC_EN | S17_TX_FLOW_EN | \
+                                        S17_RX_FLOW_EN | S17_DUPLEX_FULL | \
+                                        S17_TX_HALF_FLOW_EN)
+
+#define S17_PORT_STATUS_AZ_DEFAULT      (S17_SPEED_1000M | S17_TXMAC_EN | \
+                                        S17_RXMAC_EN | S17_TX_FLOW_EN | \
+                                        S17_RX_FLOW_EN | S17_DUPLEX_FULL)
+
+
+#define S17_HDRLENGTH_SEL               (1 << 16)
+#define S17_HDR_VALUE                   0xAAAA
+
+#define S17_TXHDR_MODE_NO               0
+#define S17_TXHDR_MODE_MGM              1
+#define S17_TXHDR_MODE_ALL              2
+#define S17_RXHDR_MODE_NO               (0 << 2)
+#define S17_RXHDR_MODE_MGM              (1 << 2)
+#define S17_RXHDR_MODE_ALL              (2 << 2)
+
+#define S17_CPU_PORT_EN                 (1 << 10)
+#define S17_PPPOE_REDIR_EN              (1 << 8)
+#define S17_MIRROR_PORT_SHIFT           4
+#define S17_IGMP_COPY_EN                (1 << 3)
+#define S17_RIP_COPY_EN                 (1 << 2)
+#define S17_EAPOL_REDIR_EN              (1 << 0)
+
+#define S17_IGMP_JOIN_LEAVE_DP_SHIFT    24
+#define S17_BROAD_DP_SHIFT              16
+#define S17_MULTI_FLOOD_DP_SHIFT        8
+#define S17_UNI_FLOOD_DP_SHIFT          0
+#define S17_IGMP_JOIN_LEAVE_DPALL       (0x7f << S17_IGMP_JOIN_LEAVE_DP_SHIFT)
+#define S17_BROAD_DPALL                 (0x7f << S17_BROAD_DP_SHIFT)
+#define S17_MULTI_FLOOD_DPALL           (0x7f << S17_MULTI_FLOOD_DP_SHIFT)
+#define S17_UNI_FLOOD_DPALL             (0x7f << S17_UNI_FLOOD_DP_SHIFT)
+
+#define S17_PWS_CHIP_AR8327		(1 << 30)
+#define S17c_PWS_SERDES_ANEG_DISABLE	(1 << 7)
+
+/* S17_PHY_CONTROL fields */
+#define S17_CTRL_SOFTWARE_RESET                    0x8000
+#define S17_CTRL_SPEED_LSB                         0x2000
+#define S17_CTRL_AUTONEGOTIATION_ENABLE            0x1000
+#define S17_CTRL_RESTART_AUTONEGOTIATION           0x0200
+#define S17_CTRL_SPEED_FULL_DUPLEX                 0x0100
+#define S17_CTRL_SPEED_MSB                         0x0040
+
+/* For EEE_CTRL_REG */
+#define S17_LPI_DISABLE_P1              (1 << 4)
+#define S17_LPI_DISABLE_P2              (1 << 6)
+#define S17_LPI_DISABLE_P3              (1 << 8)
+#define S17_LPI_DISABLE_P4              (1 << 10)
+#define S17_LPI_DISABLE_P5              (1 << 12)
+#define S17_LPI_DISABLE_ALL             0x1550
+
+/* For MMD register control */
+#define S17_MMD_FUNC_ADDR               (0 << 14)
+#define S17_MMD_FUNC_DATA               (1 << 14)
+#define S17_MMD_FUNC_DATA_2             (2 << 14)
+#define S17_MMD_FUNC_DATA_3             (3 << 14)
+
+/* For phyInfo_t azFeature */
+#define S17_8023AZ_PHY_ENABLED                  (1 << 0)
+#define S17_8023AZ_PHY_LINKED                   (1 << 1)
+
+/* Queue Management registe fields */
+#define S17_HOL_CTRL0_LAN		0x2a008888 /* egress priority 8, eg_portq = 0x2a */
+#define S17_HOL_CTRL0_WAN		0x2a666666 /* egress priority 6, eg_portq = 0x2a */
+#define S17_HOL_CTRL1_DEFAULT		0xc6	   /* enable HOL control */
+
+/* Packet Edit register fields */
+#define S17_ROUTER_EG_UNMOD             0x0	/* unmodified */
+#define S17_ROUTER_EG_WOVLAN            0x1	/* without VLAN */
+#define S17_ROUTER_EG_WVLAN             0x2	/* with VLAN */
+#define S17_ROUTER_EG_UNTOUCH           0x3	/* untouched */
+#define S17_ROUTER_EG_MODE_DEFAULT      0x01111111 /* all ports without VLAN */
+
+#define S17_RESET_DONE(phy_control)                   \
+	(((phy_control) & (S17_CTRL_SOFTWARE_RESET)) == 0)
+
+/* Phy status fields */
+#define S17_STATUS_AUTO_NEG_DONE                   0x0020
+
+#define S17_AUTONEG_DONE(ip_phy_status)                   \
+	(((ip_phy_status) &                               \
+	(S17_STATUS_AUTO_NEG_DONE)) ==                    \
+	(S17_STATUS_AUTO_NEG_DONE))
+
+/* Link Partner ability */
+#define S17_LINK_100BASETX_FULL_DUPLEX       0x0100
+#define S17_LINK_100BASETX                   0x0080
+#define S17_LINK_10BASETX_FULL_DUPLEX        0x0040
+#define S17_LINK_10BASETX                    0x0020
+
+/* Advertisement register. */
+#define S17_ADVERTISE_NEXT_PAGE              0x8000
+#define S17_ADVERTISE_ASYM_PAUSE             0x0800
+#define S17_ADVERTISE_PAUSE                  0x0400
+#define S17_ADVERTISE_100FULL                0x0100
+#define S17_ADVERTISE_100HALF                0x0080
+#define S17_ADVERTISE_10FULL                 0x0040
+#define S17_ADVERTISE_10HALF                 0x0020
+
+#define S17_ADVERTISE_ALL (S17_ADVERTISE_ASYM_PAUSE | S17_ADVERTISE_PAUSE | \
+			S17_ADVERTISE_10HALF | S17_ADVERTISE_10FULL | \
+			S17_ADVERTISE_100HALF | S17_ADVERTISE_100FULL)
+
+/* 1000BASET_CONTROL */
+#define S17_ADVERTISE_1000FULL               0x0200
+
+/* Phy Specific status fields */
+#define S17_STATUS_LINK_MASK                 0xC000
+#define S17_STATUS_LINK_SHIFT                14
+#define S17_STATUS_FULL_DEPLEX               0x2000
+#define S17_STATUS_LINK_PASS                 0x0400
+#define S17_STATUS_RESOLVED                  0x0800
+#define S17_STATUS_LINK_10M                  0
+#define S17_STATUS_LINK_100M                 1
+#define S17_STATUS_LINK_1000M                2
+
+#define S17_GLOBAL_INT_PHYMASK               (1 << 15)
+
+#define S17_PHY_LINK_UP                      0x400
+#define S17_PHY_LINK_DOWN                    0x800
+#define S17_PHY_LINK_DUPLEX_CHANGE           0x2000
+#define S17_PHY_LINK_SPEED_CHANGE            0x4000
+
+/* For Port flow control registers */
+#define S17_PORT_FLCTL_XON_DEFAULT           (0x3a << 16)
+#define S17_PORT_FLCTL_XOFF_DEFAULT          (0x4a)
+
+/* Module enable Register */
+#define S17_MODULE_L3_EN                     (1 << 2)
+#define S17_MODULE_ACL_EN                    (1 << 1)
+#define S17_MODULE_MIB_EN                    (1 << 0)
+
+/* MIB Function Register 1 */
+#define S17_MIB_FUNC_ALL                     (3 << 24)
+#define S17_MIB_CPU_KEEP                     (1 << 20)
+#define S17_MIB_BUSY                         (1 << 17)
+#define S17_MIB_AT_HALF_EN                   (1 << 16)
+#define S17_MIB_TIMER_DEFAULT                0x100
+
+#define S17_MAC_MAX                          7
+
+/* MAC power selector bit definitions */
+#define S17_RGMII0_1_8V                       (1 << 19)
+#define S17_RGMII1_1_8V                       (1 << 18)
+
+/* SGMII_CTRL bit definitions */
+#define S17c_SGMII_EN_LCKDT		      (1 << 0)
+#define S17c_SGMII_EN_PLL		      (1 << 1)
+#define S17c_SGMII_EN_RX		      (1 << 2)
+#define S17c_SGMII_EN_TX		      (1 << 3)
+#define S17c_SGMII_EN_SD		      (1 << 4)
+#define S17c_SGMII_BW_HIGH		      (1 << 6)
+#define S17c_SGMII_SEL_CLK125M		      (1 << 7)
+#define S17c_SGMII_TXDR_CTRL_600mV	      (1 << 10)
+#define S17c_SGMII_CDR_BW_8		      (3 << 13)
+#define S17c_SGMII_DIS_AUTO_LPI_25M	      (1 << 16)
+#define S17c_SGMII_MODE_CTRL_SGMII_PHY	      (1 << 22)
+#define S17c_SGMII_PAUSE_SG_TX_EN_25M	      (1 << 24)
+#define S17c_SGMII_ASYM_PAUSE_25M	      (1 << 25)
+#define S17c_SGMII_PAUSE_25M		      (1 << 26)
+#define S17c_SGMII_HALF_DUPLEX_25M	      (1 << 30)
+#define S17c_SGMII_FULL_DUPLEX_25M	      (1 << 31)
+
+#ifndef BOOL
+#define BOOL    int
+#endif
+
+/*add feature define here*/
+
+#ifdef CONFIG_AR7242_S17_PHY
+#undef HEADER_REG_CONF
+#undef HEADER_EN
+#endif
+int athrs17_init_switch(void);
+void athrs17_reg_init(ipq_gmac_board_cfg_t *gmac_cfg);
+void athrs17_reg_init_lan(ipq_gmac_board_cfg_t *gmac_cfg);
+void athrs17_vlan_config(void);
+#endif
+
+
diff --git a/arch/arm/include/asm/arch-ipq5018/clk.h b/arch/arm/include/asm/arch-ipq5018/clk.h
new file mode 100644
index 0000000..4e553d4
--- /dev/null
+++ b/arch/arm/include/asm/arch-ipq5018/clk.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015-2016, 2018-2020 The Linux Foundation. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef IPQ5018_CLK_H
+#define IPQ5018_CLK_H
+
+#define CLK_ENABLE	0x1
+/* I2C clocks configuration */
+#ifdef CONFIG_IPQ5018_I2C
+
+#define GCC_BLSP1_QUP3_I2C_APPS_CFG_RCGR		0x1804004
+#define GCC_BLSP1_QUP3_I2C_APPS_CFG_RCGR_SRC_SEL	(1 << 8)
+#define GCC_BLSP1_QUP3_I2C_APPS_CFG_RCGR_SRC_DIV	(0x1F << 0)
+
+#define GCC_BLSP1_QUP3_I2C_APPS_CMD_RCGR	0x1804000
+#define GCC_BLSP1_QUP3_I2C_APPS_CBCR		0x1804010
+
+#define CMD_UPDATE	0x1
+#define ROOT_EN		0x2
+
+
+void i2c_clock_config(void);
+#endif
+
+#ifdef CONFIG_IPQ_BT_SUPPORT
+#define GCC_BTSS_LPO_CBCR			0x181C004
+void enable_btss_lpo_clk(void);
+#endif
+
+#endif /*IPQ5018_CLK_H*/
diff --git a/arch/arm/include/asm/arch-ipq5018/ipq5018_gmac.h b/arch/arm/include/asm/arch-ipq5018/ipq5018_gmac.h
new file mode 100644
index 0000000..f93bca4
--- /dev/null
+++ b/arch/arm/include/asm/arch-ipq5018/ipq5018_gmac.h
@@ -0,0 +1,640 @@
+/*
+ * Copyright (c) 2019-2020  The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _IPQ5018_GMAC_H
+#define _IPQ5018_GMAC_H
+#include <common.h>
+#include <net.h>
+#include <configs/ipq5018.h>
+
+#define QCA808X_MII_ADDR_C45			(1<<30)
+#define QCA808X_REG_C45_ADDRESS(dev_type, reg_num) \
+						(QCA808X_MII_ADDR_C45 | \
+						((dev_type & 0x1f) << 16) | \
+						(reg_num & 0xffff))
+#define MPGE_PHY_MMD1_DAC			0x8100
+#define MPGE_PHY_MMD1_NUM			0x1
+#define MPGE_PHY_MMD1_DAC_MASK			0xff00
+#define PHY_DAC(val)				(val<<8)
+#define MPGE_PHY_DEBUG_EDAC			0x4380
+
+#define LINK_UP					0x400
+#define LINK(_data)				(_data & LINK_UP)? "Up" : "Down"
+#define DUPLEX(_data)				(_data & 0x2000)?\
+						"Full duplex" : "Half duplex"
+#define SPEED(_data)				((_data & 0xC000) >> 12)
+#define SPEED_1000M				(1 << 3)
+#define SPEED_100M				(1 << 2)
+
+#define GEPHY					0x004DD0C0
+#define S17C_VERSION				0x1302
+#define QCA_8337				0x004DD036
+
+#define CONFIG_MACRESET_TIMEOUT			(3 * CONFIG_SYS_HZ)
+#define CONFIG_MDIO_TIMEOUT			(3 * CONFIG_SYS_HZ)
+#define CONFIG_PHYRESET_TIMEOUT			(3 * CONFIG_SYS_HZ)
+#define CONFIG_AUTONEG_TIMEOUT			(5 * CONFIG_SYS_HZ)
+/* MAC configuration register definitions */
+#define FRAMEBURSTENABLE			(1 << 21)
+#define MII_PORTSELECT				(1 << 15)
+#define FES_100					(1 << 14)
+#define DISABLERXOWN				(1 << 13)
+#define FULLDPLXMODE				(1 << 11)
+#define RXENABLE				(1 << 2)
+#define TXENABLE				(1 << 3)
+#define DW_DMA_BASE_OFFSET			(0x1000)
+
+/* Poll demand definitions */
+#define POLL_DATA				(0x0)
+
+/* Descriptior related definitions */
+#define MAC_MAX_FRAME_SZ			(1600)
+
+/*
+ * txrx_status definitions
+ */
+
+/* tx status bits definitions */
+#define DESC_TXSTS_OWNBYDMA			(1 << 31)
+#define DESC_TXSTS_TXINT			(1 << 30)
+#define DESC_TXSTS_TXLAST			(1 << 29)
+#define DESC_TXSTS_TXFIRST			(1 << 28)
+#define DESC_TXSTS_TXCRCDIS			(1 << 27)
+
+#define DESC_TXSTS_TXPADDIS			(1 << 26)
+#define DESC_TXSTS_TXCHECKINSCTRL		(3 << 22)
+#define DESC_TXSTS_TXRINGEND			(1 << 21)
+#define DESC_TXSTS_TXCHAIN			(1 << 20)
+#define DESC_TXSTS_MSK				(0x1FFFF << 0)
+
+/* rx status bits definitions */
+#define DESC_RXSTS_OWNBYDMA			(1 << 31)
+#define DESC_RXSTS_DAFILTERFAIL			(1 << 30)
+#define DESC_RXSTS_FRMLENMSK			(0x3FFF << 16)
+#define DESC_RXSTS_FRMLENSHFT			(16)
+
+#define DESC_RXSTS_ERROR			(1 << 15)
+#define DESC_RXSTS_RXTRUNCATED			(1 << 14)
+#define DESC_RXSTS_SAFILTERFAIL			(1 << 13)
+#define DESC_RXSTS_RXIPC_GIANTFRAME		(1 << 12)
+#define DESC_RXSTS_RXDAMAGED			(1 << 11)
+#define DESC_RXSTS_RXVLANTAG			(1 << 10)
+#define DESC_RXSTS_RXFIRST			(1 << 9)
+#define DESC_RXSTS_RXLAST			(1 << 8)
+#define DESC_RXSTS_RXIPC_GIANT			(1 << 7)
+#define DESC_RXSTS_RXCOLLISION			(1 << 6)
+#define DESC_RXSTS_RXFRAMEETHER			(1 << 5)
+#define DESC_RXSTS_RXWATCHDOG			(1 << 4)
+#define DESC_RXSTS_RXMIIERROR			(1 << 3)
+#define DESC_RXSTS_RXDRIBBLING			(1 << 2)
+#define DESC_RXSTS_RXCRC			(1 << 1)
+
+/*
+ * dmamac_cntl definitions
+ */
+
+/* tx control bits definitions */
+#if defined(CONFIG_DW_ALTDESCRIPTOR)
+
+#define DESC_TXCTRL_SIZE1MASK			(0x1FFF << 0)
+#define DESC_TXCTRL_SIZE1SHFT			(0)
+#define DESC_TXCTRL_SIZE2MASK			(0x1FFF << 16)
+#define DESC_TXCTRL_SIZE2SHFT			(16)
+
+#else
+
+#define DESC_TXCTRL_TXINT			(1 << 31)
+#define DESC_TXCTRL_TXLAST			(1 << 30)
+#define DESC_TXCTRL_TXFIRST			(1 << 29)
+#define DESC_TXCTRL_TXCHECKINSCTRL		(3 << 27)
+#define DESC_TXCTRL_TXCRCDIS			(1 << 26)
+#define DESC_TXCTRL_TXRINGEND			(1 << 25)
+#define DESC_TXCTRL_TXCHAIN			(1 << 24)
+
+#define DESC_TXCTRL_SIZE1MASK			(0x7FF << 0)
+#define DESC_TXCTRL_SIZE1SHFT			(0)
+#define DESC_TXCTRL_SIZE2MASK			(0x7FF << 11)
+#define DESC_TXCTRL_SIZE2SHFT			(11)
+
+#endif
+
+/* rx control bits definitions */
+#if defined(CONFIG_DW_ALTDESCRIPTOR)
+
+#define DESC_RXCTRL_RXINTDIS			(1 << 31)
+#define DESC_RXCTRL_RXRINGEND			(1 << 15)
+#define DESC_RXCTRL_RXCHAIN			(1 << 14)
+
+#define DESC_RXCTRL_SIZE1MASK			(0x1FFF << 0)
+#define DESC_RXCTRL_SIZE1SHFT			(0)
+#define DESC_RXCTRL_SIZE2MASK			(0x1FFF << 16)
+#define DESC_RXCTRL_SIZE2SHFT			(16)
+
+#else
+
+#define DESC_RXCTRL_RXINTDIS			(1 << 31)
+#define DESC_RXCTRL_RXRINGEND			(1 << 25)
+#define DESC_RXCTRL_RXCHAIN			(1 << 24)
+
+#define DESC_RXCTRL_SIZE1MASK			(0x7FF << 0)
+#define DESC_RXCTRL_SIZE1SHFT			(0)
+#define DESC_RXCTRL_SIZE2MASK			(0x7FF << 11)
+#define DESC_RXCTRL_SIZE2SHFT			(11)
+
+#endif
+
+/* Speed specific definitions */
+#define NETDEV_TX_BUSY				(1)
+
+/* Duplex mode specific definitions */
+#define HALF_DUPLEX				(1)
+#define FULL_DUPLEX				(2)
+
+/* Bus mode register definitions */
+#define FIXEDBURST				(1 << 16)
+#define PRIORXTX_41				(3 << 14)
+#define PRIORXTX_31				(2 << 14)
+#define PRIORXTX_21				(1 << 14)
+#define PRIORXTX_11				(0 << 14)
+#define BURST_1					(1 << 8)
+#define BURST_2					(2 << 8)
+#define BURST_4					(4 << 8)
+#define BURST_8					(8 << 8)
+#define BURST_16				(16 << 8)
+#define BURST_32				(32 << 8)
+#define RXHIGHPRIO				(1 << 1)
+#define DMAMAC_SRST				(1 << 0)
+#define DMA_ARB					(1 << 1)
+#define DESC_SKIP_LEN_0				(0 << 2)
+#define DMA_INT_DISABLE				(0 << 0)
+/* Operation mode definitions */
+#define STOREFORWARD				(1 << 21)
+#define FLUSHTXFIFO				(1 << 20)
+#define TXSTART					(1 << 13)
+#define TXSECONDFRAME				(1 << 2)
+#define RXSTART					(1 << 1)
+#define RX_THRESHOLD_128			(3 << 3)
+#define OP_SECOND_FRAME				(1 << 2)
+
+/* GMAC config definitions */
+#define FES_PORT_SPEED				(1 << 14)
+#define MII_PORT_SELECT				(1 << 15)
+#define SGMII_PORT_SELECT			(0 << 15)
+#define FRAME_BURST_ENABLE			(1 << 21)
+#define JABBER_DISABLE				(1 << 22)
+#define JUMBO_FRAME_ENABLE			(1 << 20)
+#define HALF_DUPLEX_ENABLE			(0 << 11)
+#define FULL_DUPLEX_ENABLE			(1 << 11)
+#define TX_ENABLE				(1 << 3)
+#define RX_ENABLE				(1 << 2)
+#define RX_IPC_OFFLOAD				(1 << 10)
+
+/* GMAC Fram filter definitions */
+#define GMAC_FRAME_RX_ALL			(1 << 31)
+#define PROMISCUOUS_MODE_ON			(1 << 0)
+#define DISABLE_BCAST_FRAMES			(1 << 5)
+
+/* DMA Flow control definitions */
+#define FULL_3KB				(1 << 10)
+#define HW_FLW_CNTL_ENABLE			(1 << 8)
+
+/* GMAC Flow control definitions */
+#define RX_FLW_CNTL_ENABLE			(1 << 2)
+#define TX_FLW_CNTL_ENABLE			(1 << 1)
+
+
+/* Descriptor definitions */
+#define TX_END_OF_RING				(1 << 21)
+#define RX_END_OF_RING				(1 << 15)
+
+#define NO_OF_TX_DESC				8
+#define NO_OF_RX_DESC				PKTBUFSRX
+#define MAX_WAIT				1000
+
+#define CACHE_LINE_SIZE				(CONFIG_SYS_CACHELINE_SIZE)
+
+#define VLAN_ETH_FRAME_LEN			1518
+#define ETH_ZLEN				60
+#define ETH_HLEN				12
+#define ETH_FCS_LEN				4
+#define VLAN_HLEN				4
+#define NET_IP_ALIGN				2
+
+#define ETHERNET_EXTRA				(NET_IP_ALIGN + 2 * CACHE_LINE_SIZE)
+#define ETH_MAX_FRAME_LEN			(VLAN_ETH_FRAME_LEN + \
+						 ETH_FCS_LEN + \
+						 ((4 - NET_IP_ALIGN) & 0x3))
+typedef struct
+{
+	volatile u32 status;		/* Status */
+	volatile u32 length;		/* Buffer 1 and Buffer 2 length */
+	volatile u32 buffer1;		/* Network Buffer 1 pointer (Dma-able) */
+	volatile u32 data1;		/* This holds virtual address of buffer1, not used by DMA */
+	/* Following is used only by driver */
+	volatile u32 extstatus;		/* Extended status of a Rx Descriptor */
+	volatile u32 reserved1;		/* Reserved word */
+	volatile u32 timestamplow;	/* Lower 32 bits of the 64 bit timestamp value */
+	volatile u32 timestamphigh;	/* Higher 32 bits of the 64 bit timestamp value */
+} ipq_gmac_desc_t ;
+
+#define IPQ5018_GMAC_PORT	2
+#define IPQ5018_PHY_MAX		1
+
+struct ipq_eth_dev {
+	uint			phy_address;
+	uint			no_of_phys;
+	uint			interface;
+	uint			sw_configured;
+	uint			speed;
+	uint			duplex;
+	uint			phy_configured;
+	uint			mac_unit;
+	uint			phy_type;
+	uint			mac_ps;
+	uint			ipq_swith;
+	uint			phy_external_link;
+	int			link_printed;
+	u32			padding;
+	ipq_gmac_desc_t		*desc_tx[NO_OF_TX_DESC];
+	ipq_gmac_desc_t		*desc_rx[NO_OF_RX_DESC];
+	uint			next_tx;
+	uint			next_rx;
+	int			txdesc_count;
+	int			rxdesc_count;
+	struct eth_mac_regs	*mac_regs_p;
+	struct eth_dma_regs	*dma_regs_p;
+	struct eth_device *dev;
+	struct phy_ops		*ops;
+	const char phy_name[MDIO_NAME_LEN];
+	struct ipq_forced_mode *forced_params;
+	ipq_gmac_board_cfg_t	*gmac_board_cfg;
+} __attribute__ ((aligned(8)));
+
+struct eth_mac_regs {
+	u32 conf;		/* 0x00 */
+	u32 framefilt;		/* 0x04 */
+	u32 hashtablehigh;	/* 0x08 */
+	u32 hashtablelow;	/* 0x0c */
+	u32 miiaddr;		/* 0x10 */
+	u32 miidata;		/* 0x14 */
+	u32 flowcontrol;	/* 0x18 */
+	u32 vlantag;		/* 0x1c */
+	u32 version;		/* 0x20 */
+	u8 reserved_1[20];	/* 0x24 -- 0x37 */
+	u32 intreg;		/* 0x38 */
+	u32 intmask;		/* 0x3c */
+	u32 macaddr0hi;		/* 0x40 */
+	u32 macaddr0lo;		/* 0x44 */
+};
+
+struct eth_dma_regs {
+	u32 busmode;		/* 0x00 */
+	u32 txpolldemand;	/* 0x04 */
+	u32 rxpolldemand;	/* 0x08 */
+	u32 rxdesclistaddr;	/* 0x0c */
+	u32 txdesclistaddr;	/* 0x10 */
+	u32 status;		/* 0x14 */
+	u32 opmode;		/* 0x18 */
+	u32 intenable;		/* 0x1c */
+	u8 reserved[40];	/* 0x20 -- 0x47 */
+	u32 currhosttxdesc;	/* 0x48 */
+	u32 currhostrxdesc;	/* 0x4c */
+	u32 currhosttxbuffaddr;	/* 0x50 */
+	u32 currhostrxbuffaddr;	/* 0x54 */
+};
+
+void gmac_reset(void);
+void gmacsec_reset(void);
+void ipq_gmac_common_init(ipq_gmac_board_cfg_t *cfg);
+int ipq_gmac_init(ipq_gmac_board_cfg_t *cfg);
+
+enum DmaDescriptorStatus {	/* status word of DMA descriptor */
+	DescOwnByDma		= 0x80000000,	/* (OWN)Descriptor is owned by DMA engine		31	RW	*/
+
+	DescDAFilterFail	= 0x40000000,	/* (AFM)Rx - DA Filter Fail for the rx frame		30		*/
+
+	DescFrameLengthMask	= 0x3FFF0000,	/* (FL)Receive descriptor frame length			29:16		*/
+	DescFrameLengthShift	= 16,
+
+	DescError		= 0x00008000,	/* (ES)Error summary bit - OR of the follo. bits:	15		*/
+						/* DE || OE || IPC || LC || RWT || RE || CE */
+	DescRxTruncated		= 0x00004000,	/* (DE)Rx - no more descriptors for receive frame	14		*/
+	DescSAFilterFail	= 0x00002000,	/* (SAF)Rx - SA Filter Fail for the received frame	13		*/
+	DescRxLengthError	= 0x00001000,	/* (LE)Rx - frm size not matching with len field	12		*/
+	DescRxDamaged		= 0x00000800,	/* (OE)Rx - frm was damaged due to buffer overflow	11		*/
+	DescRxVLANTag		= 0x00000400,	/* (VLAN)Rx - received frame is a VLAN frame		10		*/
+	DescRxFirst		= 0x00000200,	/* (FS)Rx - first descriptor of the frame		 9		*/
+	DescRxLast		= 0x00000100,	/* (LS)Rx - last descriptor of the frame		 8		*/
+	DescRxLongFrame		= 0x00000080,	/* (Giant Frame)Rx - frame is longer than 1518/1522	 7		*/
+	DescRxCollision		= 0x00000040,	/* (LC)Rx - late collision occurred during reception	 6		*/
+	DescRxFrameEther	= 0x00000020,	/* (FT)Rx - Frame type - Ethernet, otherwise 802.3	 5		*/
+	DescRxWatchdog		= 0x00000010,	/* (RWT)Rx - watchdog timer expired during reception	 4		*/
+	DescRxMiiError		= 0x00000008,	/* (RE)Rx - error reported by MII interface		 3		*/
+	DescRxDribbling		= 0x00000004,	/* (DE)Rx - frame contains non int multiple of 8 bits	 2		*/
+	DescRxCrc		= 0x00000002,	/* (CE)Rx - CRC error					 1		*/
+
+	DescRxEXTsts		= 0x00000001,	/* Extended Status Available (RDES4)			 0		*/
+
+	DescTxIntEnable		= 0x40000000,	/* (IC)Tx - interrupt on completion			30		*/
+	DescTxLast		= 0x20000000,	/* (LS)Tx - Last segment of the frame			29		*/
+	DescTxFirst		= 0x10000000,	/* (FS)Tx - First segment of the frame			28		*/
+	DescTxDisableCrc	= 0x08000000,	/* (DC)Tx - Add CRC disabled (first segment only)	27		*/
+	DescTxDisablePadd	= 0x04000000,	/* (DP)disable padding, added by - reyaz		26		*/
+
+	DescTxCisMask		= 0x00c00000,	/* Tx checksum offloading control mask			23:22		*/
+	DescTxCisBypass		= 0x00000000,	/* Checksum bypass							*/
+	DescTxCisIpv4HdrCs	= 0x00400000,	/* IPv4 header checksum							*/
+	DescTxCisTcpOnlyCs	= 0x00800000,	/* TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present*/
+	DescTxCisTcpPseudoCs	= 0x00c00000,	/* TCP/UDP/ICMP checksum fully in hardware including pseudo header	*/
+
+	TxDescEndOfRing		= 0x00200000,	/* (TER)End of descriptors ring				21		*/
+	TxDescChain		= 0x00100000,	/* (TCH)Second buffer address is chain address		20		*/
+
+	DescRxChkBit0		= 0x00000001,	/* () Rx - Rx Payload Checksum Error			 0		*/
+	DescRxChkBit7		= 0x00000080,	/* (IPC CS ERROR)Rx - Ipv4 header checksum error	 7		*/
+	DescRxChkBit5		= 0x00000020,	/* (FT)Rx - Frame type - Ethernet, otherwise 802.3	 5		*/
+
+	DescRxTSavail		= 0x00000080,	/* Time stamp available					 7		*/
+	DescRxFrameType		= 0x00000020,	/* (FT)Rx - Frame type - Ethernet, otherwise 802.3	 5		*/
+
+	DescTxIpv4ChkError	= 0x00010000,	/* (IHE) Tx Ip header error				16		*/
+	DescTxTimeout		= 0x00004000,	/* (JT)Tx - Transmit jabber timeout			14		*/
+	DescTxFrameFlushed	= 0x00002000,	/* (FF)Tx - DMA/MTL flushed the frame due to SW flush	13		*/
+	DescTxPayChkError	= 0x00001000,	/* (PCE) Tx Payload checksum Error			12		*/
+	DescTxLostCarrier	= 0x00000800,	/* (LC)Tx - carrier lost during tramsmission		11		*/
+	DescTxNoCarrier		= 0x00000400,	/* (NC)Tx - no carrier signal from the tranceiver	10		*/
+	DescTxLateCollision	= 0x00000200,	/* (LC)Tx - transmission aborted due to collision	 9		*/
+	DescTxExcCollisions	= 0x00000100,	/* (EC)Tx - transmission aborted after 16 collisions	 8		*/
+	DescTxVLANFrame		= 0x00000080,	/* (VF)Tx - VLAN-type frame				 7		*/
+
+	DescTxCollMask		= 0x00000078,	/* (CC)Tx - Collision count				6:3		*/
+	DescTxCollShift		= 3,
+
+	DescTxExcDeferral	= 0x00000004,	/* (ED)Tx - excessive deferral				 2		*/
+	DescTxUnderflow		= 0x00000002,	/* (UF)Tx - late data arrival from the memory		 1		*/
+	DescTxDeferred		= 0x00000001,	/* (DB)Tx - frame transmision deferred			 0		*/
+
+	/*
+	 * This explains the RDES1/TDES1 bits layout
+	 * ------------------------------------------------------------------------
+	 * RDES1/TDES1 | Control Bits | Byte Count Buffer 2 | Byte Count Buffer 1 |
+	 * ------------------------------------------------------------------------
+	 */
+	/* DmaDescriptorLength	length word of DMA descriptor	*/
+
+
+	RxDisIntCompl		= 0x80000000,	/* (Disable Rx int on completion) 			31		*/
+	RxDescEndOfRing		= 0x00008000,	/* (TER)End of descriptors ring				15		*/
+	RxDescChain		= 0x00004000,	/* (TCH)Second buffer address is chain address		14		*/
+
+	/*  DescSize2Mask	= 0x1FFF0000, */	/* (TBS2) Buffer 2 size				28:16		*/
+	/* DescSize2Shift	= 16, */
+	DescSize1Mask		= 0x00001FFF,	/* (TBS1) Buffer 1 size					12:0		*/
+	DescSize1Shift		= 0,
+
+
+	/*
+	 * This explains the RDES4 Extended Status bits layout
+	 * ----------------------------------------------------------------------
+	 * RDES4	|		Extended Status				|
+	 * ----------------------------------------------------------------------
+	 */
+	DescRxPtpAvail		= 0x00004000,	/* PTP snapshot available				14		*/
+	DescRxPtpVer		= 0x00002000,	/* When set indicates IEEE1584 Version 2 (else Ver1)	13		*/
+	DescRxPtpFrameType	= 0x00001000,	/* PTP frame type Indicates PTP sent over ethernet	12		*/
+	DescRxPtpMessageType	= 0x00000F00,	/* Message Type						11:8		*/
+	DescRxPtpNo		= 0x00000000,	/* 0000 => No PTP message received					*/
+	DescRxPtpSync		= 0x00000100,	/* 0001 => Sync (all clock types) received				*/
+	DescRxPtpFollowUp	= 0x00000200,	/* 0010 => Follow_Up (all clock types) received				*/
+	DescRxPtpDelayReq	= 0x00000300,	/* 0011 => Delay_Req (all clock types) received				*/
+	DescRxPtpDelayResp	= 0x00000400,	/* 0100 => Delay_Resp (all clock types) received			*/
+	DescRxPtpPdelayReq	= 0x00000500,	/* 0101 => Pdelay_Req (in P to P tras clk) or Announce in Ord and Bound clk */
+	DescRxPtpPdelayResp	= 0x00000600,	/* 0110 => Pdealy_Resp(in P to P trans clk) or Management in Ord and Bound clk */
+	DescRxPtpPdelayRespFP	= 0x00000700,	/* 0111 => Pdealy_Resp_Follow_Up (in P to P trans clk) or Signaling in Ord and Bound clk */
+	DescRxPtpIPV6		= 0x00000080,	/* Received Packet is in IPV6 Packet			 7		*/
+	DescRxPtpIPV4		= 0x00000040,	/* Received Packet is in IPV4 Packet			 6		*/
+
+	DescRxChkSumBypass	= 0x00000020,	/* When set indicates checksum offload engine		 5
+						 * is bypassed								*/
+	DescRxIpPayloadError	= 0x00000010,	/* When set indicates 16bit IP payload CS is in error	 4		*/
+	DescRxIpHeaderError	= 0x00000008,	/* When set indicates 16bit IPV4 header CS is in	 3
+						 * error or IP datagram version is not consistent
+						 * with Ethernet type value						*/
+	DescRxIpPayloadType	= 0x00000007,	/* Indicate the type of payload encapsulated		2:0
+						 * in IPdatagram processed by COE (Rx)					*/
+	DescRxIpPayloadUnknown	= 0x00000000,	/* Unknown or didnot process IP payload					*/
+	DescRxIpPayloadUDP	= 0x00000001,	/* UDP									*/
+	DescRxIpPayloadTCP	= 0x00000002,	/* TCP									*/
+	DescRxIpPayloadICMP	= 0x00000003,	/* ICMP									*/
+
+};
+
+/**********************************************************
+ * GMAC DMA registers
+ * For Pci based system address is BARx + GmaDmaBase
+ * For any other system translation is done accordingly
+ **********************************************************/
+
+enum DmaRegisters
+{
+	DmaBusMode	= 0x0000,	/* CSR0	- Bus Mode Register			*/
+	DmaTxPollDemand	= 0x0004,	/* CSR1	- Transmit Poll Demand Register		*/
+	DmaRxPollDemand	= 0x0008,	/* CSR2	- Receive Poll Demand Register		*/
+	DmaRxBaseAddr	= 0x000C,	/* CSR3	- Receive Descriptor list base address	*/
+	DmaTxBaseAddr	= 0x0010,	/* CSR4	- Transmit Descriptor list base address	*/
+	DmaStatus	= 0x0014,	/* CSR5	- Dma status Register			*/
+	DmaControl	= 0x0018,	/* CSR6	- Dma Operation Mode Register		*/
+	DmaInterrupt	= 0x001C,	/* CSR7	- Interrupt enable			*/
+	DmaMissedFr	= 0x0020,	/* CSR8	- Missed Frame & Buffer overflow Counter*/
+	DmaTxCurrDesc	= 0x0048,	/*	- Current host Tx Desc Register		*/
+	DmaRxCurrDesc	= 0x004C,	/*	- Current host Rx Desc Register		*/
+	DmaTxCurrAddr	= 0x0050,	/* CSR20- Current host transmit buffer address	*/
+	DmaRxCurrAddr	= 0x0054,	/* CSR21- Current host receive buffer address	*/
+};
+
+/**********************************************************
+ * DMA Engine registers Layout
+ **********************************************************/
+
+/* DmaBusMode			= 0x0000,	CSR0 - Bus Mode */
+enum DmaBusModeReg
+{						/* Bit description					Bits	R/W	Reset value */
+	DmaFixedBurstEnable	= 0x00010000,	/* (FB)Fixed Burst SINGLE, INCR4, INCR8 or INCR16	16	RW		*/
+	DmaFixedBurstDisable	= 0x00000000,	/*		SINGLE, INCR				 0			*/
+	DmaTxPriority		= 0x08000000,
+
+	DmaTxPriorityRatio11	= 0x00000000,	/* (PR)TX:RX DMA priority ratio 1:1			15:14	RW	00	*/
+	DmaTxPriorityRatio21	= 0x00004000,	/* (PR)TX:RX DMA priority ratio 2:1						*/
+	DmaTxPriorityRatio31	= 0x00008000,	/* (PR)TX:RX DMA priority ratio 3:1						*/
+	DmaTxPriorityRatio41	= 0x0000C000,	/* (PR)TX:RX DMA priority ratio 4:1						*/
+
+	DmaBurstLengthx8	= 0x01000000,	/* When set mutiplies the PBL by 8			24	RW	 0	*/
+
+	DmaBurstLength256	= 0x01002000,	/*(DmaBurstLengthx8 | DmaBurstLength32) = 256	[24]	13:8			*/
+	DmaBurstLength128	= 0x01001000,	/*(DmaBurstLengthx8 | DmaBurstLength16) = 128	[24]	13:8			*/
+	DmaBurstLength64	= 0x01000800,	/*(DmaBurstLengthx8 | DmaBurstLength8) = 64	[24]	13:8			*/
+	DmaBurstLength32	= 0x00002000,	/* (PBL) programmable Dma burst length = 32		13:8	RW		*/
+	DmaBurstLength16	= 0x00001000,	/* Dma burst length = 16							*/
+	DmaBurstLength8		= 0x00000800,	/* Dma burst length = 8								*/
+	DmaBurstLength4		= 0x00000400,	/* Dma burst length = 4								*/
+	DmaBurstLength2		= 0x00000200,	/* Dma burst length = 2								*/
+	DmaBurstLength1		= 0x00000100,	/* Dma burst length = 1								*/
+	DmaBurstLength0		= 0x00000000,	/* Dma burst length = 0							00	*/
+
+	DmaDescriptor8Words	= 0x00000080,	/* Enh Descriptor works 1 => 8 word descriptor		 7		0	*/
+	DmaDescriptor4Words	= 0x00000000,	/* Enh Descriptor works 0 => 4 word descriptor		 7		0	*/
+
+	DmaDescriptorSkip16	= 0x00000040,	/* (DSL)Descriptor skip length (no.of dwords)		6:2	RW		*/
+	DmaDescriptorSkip8	= 0x00000020,	/* between two unchained descriptors						*/
+	DmaDescriptorSkip4	= 0x00000010,
+	DmaDescriptorSkip2	= 0x00000008,
+	DmaDescriptorSkip1	= 0x00000004,
+	DmaDescriptorSkip0	= 0x00000000,
+
+	DmaArbitRr		= 0x00000000,	/* (DA) DMA RR arbitration				 1	RW	0	*/
+	DmaArbitPr		= 0x00000002,	/* Rx has priority over Tx							*/
+
+	DmaResetOn		= 0x00000001,	/* (SWR)Software Reset DMA engine			 0	RW		*/
+	DmaResetOff		= 0x00000000,	/*							 0			*/
+};
+
+/* DmaStatus			= 0x0014,	CSR5 - Dma status Register */
+enum DmaStatusReg
+{
+	/* Bit 28 27 and 26 indicate whether the interrupt due to PMT GMACMMC or GMAC LINE Remaining bits are DMA interrupts	*/
+	GmacPmtIntr		= 0x10000000,	/* (GPI)Gmac subsystem interrupt			28	RO	0	*/
+	GmacMmcIntr		= 0x08000000,	/* (GMI)Gmac MMC subsystem interrupt			27	RO	0	*/
+	GmacLineIntfIntr	= 0x04000000,	/* Line interface interrupt				26	RO	0	*/
+
+	DmaErrorBit2		= 0x02000000,	/* (EB)Error bits 0-data buffer, 1-desc. access		25	RO	0	*/
+	DmaErrorBit1		= 0x01000000,	/* (EB)Error bits 0-write trnsf, 1-read transfr		24	RO	0	*/
+	DmaErrorBit0		= 0x00800000,	/* (EB)Error bits 0-Rx DMA, 1-Tx DMA			23	RO	0	*/
+
+	DmaTxState		= 0x00700000,	/* (TS)Transmit process state				22:20	RO		*/
+	DmaTxStopped		= 0x00000000,	/* Stopped - Reset or Stop Tx Command issued				000	*/
+	DmaTxFetching		= 0x00100000,	/* Running - fetching the Tx descriptor						*/
+	DmaTxWaiting		= 0x00200000,	/* Running - waiting for status							*/
+	DmaTxReading		= 0x00300000,	/* Running - reading the data from host memory					*/
+	DmaTxSuspended		= 0x00600000,	/* Suspended - Tx Descriptor unavailabe						*/
+	DmaTxClosing		= 0x00700000,	/* Running - closing Rx descriptor						*/
+
+	DmaRxState		= 0x000E0000,	/* (RS)Receive process state				19:17	RO		*/
+	DmaRxStopped		= 0x00000000,	/* Stopped - Reset or Stop Rx Command issued				000	*/
+	DmaRxFetching		= 0x00020000,	/* Running - fetching the Rx descriptor						*/
+	DmaRxWaiting		= 0x00060000,	/* Running - waiting for packet							*/
+	DmaRxSuspended		= 0x00080000,	/* Suspended - Rx Descriptor unavailable					*/
+	DmaRxClosing		= 0x000A0000,	/* Running - closing descriptor							*/
+	DmaRxQueuing		= 0x000E0000,	/* Running - queuing the recieve frame into host memory				*/
+
+	DmaIntNormal		= 0x00010000,	/* (NIS)Normal interrupt summary			16	RW	0	*/
+	DmaIntAbnormal		= 0x00008000,	/* (AIS)Abnormal interrupt summary			15	RW	0	*/
+
+	DmaIntEarlyRx		= 0x00004000,	/* Early receive interrupt (Normal)				RW	0	*/
+	DmaIntBusError		= 0x00002000,	/* Fatal bus error (Abnormal)					RW	0	*/
+	DmaIntEarlyTx		= 0x00000400,	/* Early transmit interrupt (Abnormal)				RW	0	*/
+	DmaIntRxWdogTO		= 0x00000200,	/* Receive Watchdog Timeout (Abnormal)				RW	0	*/
+	DmaIntRxStopped		= 0x00000100,	/* Receive process stopped (Abnormal)				RW	0	*/
+	DmaIntRxNoBuffer	= 0x00000080,	/* Receive buffer unavailable (Abnormal)			RW	0	*/
+	DmaIntRxCompleted	= 0x00000040,	/* Completion of frame reception (Normal)			RW	0	*/
+	DmaIntTxUnderflow	= 0x00000020,	/* Transmit underflow (Abnormal)				RW	0	*/
+	DmaIntRcvOverflow	= 0x00000010,	/* Receive Buffer overflow interrupt				RW	0	*/
+	DmaIntTxJabberTO	= 0x00000008,	/* Transmit Jabber Timeout (Abnormal)				RW	0	*/
+	DmaIntTxNoBuffer	= 0x00000004,	/* Transmit buffer unavailable (Normal)				RW	0	*/
+	DmaIntTxStopped		= 0x00000002,	/* Transmit process stopped (Abnormal)				RW	0	*/
+	DmaIntTxCompleted	= 0x00000001,	/* Transmit completed (Normal)					RW	0	*/
+};
+
+/* DmaControl			= 0x0018,	CSR6 - Dma Operation Mode Register */
+enum DmaControlReg
+{
+	DmaDisableDropTcpCs	= 0x04000000,	/* (DT) Dis. drop. of tcp/ip CS error frames		26	RW	0	*/
+
+	DmaStoreAndForward	= 0x00200000,	/* (SF)Store and forward				21	RW	0	*/
+	DmaFlushTxFifo		= 0x00100000,	/* (FTF)Tx FIFO controller is reset to default		20	RW	0	*/
+
+	DmaTxThreshCtrl		= 0x0001C000,	/* (TTC)Controls thre Threh of MTL tx Fifo		16:14	RW		*/
+	DmaTxThreshCtrl16	= 0x0001C000,	/* (TTC)Controls thre Threh of MTL tx Fifo 16		16:14	RW		*/
+	DmaTxThreshCtrl24	= 0x00018000,	/* (TTC)Controls thre Threh of MTL tx Fifo 24		16:14	RW		*/
+	DmaTxThreshCtrl32	= 0x00014000,	/* (TTC)Controls thre Threh of MTL tx Fifo 32		16:14	RW		*/
+	DmaTxThreshCtrl40	= 0x00010000,	/* (TTC)Controls thre Threh of MTL tx Fifo 40		16:14	RW		*/
+	DmaTxThreshCtrl256	= 0x0000c000,	/* (TTC)Controls thre Threh of MTL tx Fifo 256		16:14	RW		*/
+	DmaTxThreshCtrl192	= 0x00008000,	/* (TTC)Controls thre Threh of MTL tx Fifo 192		16:14	RW		*/
+	DmaTxThreshCtrl128	= 0x00004000,	/* (TTC)Controls thre Threh of MTL tx Fifo 128		16:14	RW		*/
+	DmaTxThreshCtrl64	= 0x00000000,	/* (TTC)Controls thre Threh of MTL tx Fifo 64		16:14	RW	000	*/
+
+	DmaTxStart		= 0x00002000,	/* (ST)Start/Stop transmission				13	RW	0	*/
+
+	DmaRxFlowCtrlDeact	= 0x00401800,	/* (RFD)Rx flow control deact. threhold		  [22]	12:11	RW		*/
+	DmaRxFlowCtrlDeact1K	= 0x00000000,	/* (RFD)Rx flow control deact. threhold (1kbytes) [22]	12:11	RW	00	*/
+	DmaRxFlowCtrlDeact2K	= 0x00000800,	/* (RFD)Rx flow control deact. threhold (2kbytes) [22]	12:11	RW		*/
+	DmaRxFlowCtrlDeact3K	= 0x00001000,	/* (RFD)Rx flow control deact. threhold (3kbytes) [22]	12:11	RW		*/
+	DmaRxFlowCtrlDeact4K	= 0x00001800,	/* (RFD)Rx flow control deact. threhold (4kbytes) [22]	12:11	RW		*/
+	DmaRxFlowCtrlDeact5K	= 0x00400000,	/* (RFD)Rx flow control deact. threhold (4kbytes) [22]	12:11	RW		*/
+	DmaRxFlowCtrlDeact6K	= 0x00400800,	/* (RFD)Rx flow control deact. threhold (4kbytes) [22]	12:11	RW		*/
+	DmaRxFlowCtrlDeact7K	= 0x00401000,	/* (RFD)Rx flow control deact. threhold (4kbytes) [22]	12:11	RW		*/
+
+	DmaRxFlowCtrlAct	= 0x00800600,	/* (RFA)Rx flow control Act. threshold		  [23]	10:09	RW		*/
+	DmaRxFlowCtrlAct1K	= 0x00000000,	/* (RFA)Rx flow control Act. threshold (1kbytes)  [23]	10:09	RW	00	*/
+	DmaRxFlowCtrlAct2K	= 0x00000200,	/* (RFA)Rx flow control Act. threshold (2kbytes)  [23]	10:09	RW		*/
+	DmaRxFlowCtrlAct3K	= 0x00000400,	/* (RFA)Rx flow control Act. threshold (3kbytes)  [23]	10:09	RW		*/
+	DmaRxFlowCtrlAct4K	= 0x00000600,	/* (RFA)Rx flow control Act. threshold (4kbytes)  [23]	10:09	RW		*/
+	DmaRxFlowCtrlAct5K	= 0x00800000,	/* (RFA)Rx flow control Act. threshold (5kbytes)  [23]	10:09	RW		*/
+	DmaRxFlowCtrlAct6K	= 0x00800200,	/* (RFA)Rx flow control Act. threshold (6kbytes)  [23]	10:09	RW		*/
+	DmaRxFlowCtrlAct7K	= 0x00800400,	/* (RFA)Rx flow control Act. threshold (7kbytes)  [23]	10:09	RW		*/
+
+	DmaRxThreshCtrl		= 0x00000018,	/* (RTC)Controls thre Threh of MTL rx Fifo		4:3	RW		*/
+	DmaRxThreshCtrl64	= 0x00000000,	/* (RTC)Controls thre Threh of MTL tx Fifo 64		4:3	RW		*/
+	DmaRxThreshCtrl32	= 0x00000008,	/* (RTC)Controls thre Threh of MTL tx Fifo 32		4:3	RW		*/
+	DmaRxThreshCtrl96	= 0x00000010,	/* (RTC)Controls thre Threh of MTL tx Fifo 96		4:3	RW		*/
+	DmaRxThreshCtrl128	= 0x00000018,	/* (RTC)Controls thre Threh of MTL tx Fifo 128		4:3	RW		*/
+
+	DmaEnHwFlowCtrl		= 0x00000100,	/* (EFC)Enable HW flow control				8	RW		*/
+	DmaDisHwFlowCtrl	= 0x00000000,	/* Disable HW flow control						0	*/
+
+	DmaFwdErrorFrames	= 0x00000080,	/* (FEF)Forward error frames				7	RW	0	*/
+	DmaFwdUnderSzFrames	= 0x00000040,	/* (FUF)Forward undersize frames			6	RW	0	*/
+	DmaTxSecondFrame	= 0x00000004,	/* (OSF)Operate on second frame				4	RW	0	*/
+	DmaRxStart		= 0x00000002,	/* (SR)Start/Stop reception				1	RW	0	*/
+};
+
+/* GmacFlowControl		= 0x0018,	Flow control Register Layout */
+enum GmacFlowControlReg
+{
+	GmacPauseTimeMask	= 0xFFFF0000,	/* (PT) PAUSE TIME field in the control frame	31:16	RW	0000	*/
+	GmacPauseTimeShift	= 16,
+	DmaDisableFlushRxFrames = 0x01000000,
+
+	GmacPauseLowThresh	= 0x00000030,
+	GmacPauseLowThresh3	= 0x00000030,	/* (PLT)thresh for pause tmr 256 slot time	5:4	RW		*/
+	GmacPauseLowThresh2	= 0x00000020,	/*			     144 slot time				*/
+	GmacPauseLowThresh1	= 0x00000010,	/*			      28 slot time				*/
+	GmacPauseLowThresh0	= 0x00000000,	/*			       4 slot time			000	*/
+
+	GmacUnicastPauseFrame	= 0x00000008,
+	GmacUnicastPauseFrameOn	= 0x00000008,	/* (UP)Detect pause frame with unicast addr.	3	RW		*/
+	GmacUnicastPauseFrameOff = 0x00000000,	/* Detect only pause frame with multicast addr.			0	*/
+
+	GmacRxFlowControl	= 0x00000004,
+	GmacRxFlowControlEnable	= 0x00000004,	/* (RFE)Enable Rx flow control			2	RW		*/
+	GmacRxFlowControlDisable = 0x00000000,	/* Disable Rx flow control					0	*/
+
+	GmacTxFlowControl	= 0x00000002,
+	GmacTxFlowControlEnable	= 0x00000002,	/* (TFE)Enable Tx flow control			1	RW		*/
+	GmacTxFlowControlDisable = 0x00000000,	/* Disable flow control						0	*/
+
+	GmacFlowControlBackPressure = 0x00000001,
+	GmacSendPauseFrame	= 0x00000001,	/* (FCB/PBA)send pause frm/Apply back pressure	0	RW	0	*/
+};
+
+#endif
+
diff --git a/arch/arm/include/asm/arch-ipq6018/clk.h b/arch/arm/include/asm/arch-ipq6018/clk.h
index 5d545d4..e33a064 100644
--- a/arch/arm/include/asm/arch-ipq6018/clk.h
+++ b/arch/arm/include/asm/arch-ipq6018/clk.h
@@ -14,6 +14,8 @@
 #ifndef IPQ6018_CLK_H
 #define IPQ6018_CLK_H
 
+#include <asm/arch-qca-common/uart.h>
+
 /* I2C clocks configuration */
 #ifdef CONFIG_IPQ6018_I2C
 
@@ -31,4 +33,42 @@
 void i2c_clock_config(void);
 #endif
 
+#define GCC_BLSP1_UART1_BCR	0x1802038
+#define GCC_BLSP1_UART2_BCR	0x1803028
+#define GCC_BLSP1_UART3_BCR	0x1804028
+#define GCC_BLSP1_UART4_BCR	0x1805028
+#define GCC_BLSP1_UART5_BCR	0x1806028
+#define GCC_BLSP1_UART6_BCR	0x1807028
+
+#define GCC_BLSP1_UART_BCR(id)	((id < 1) ? \
+				(GCC_BLSP1_UART1_BCR):\
+				(GCC_BLSP1_UART1_BCR + (0x1000 * id) - 0x10))
+
+#define GCC_BLSP1_UART_APPS_CBCR(id)		(GCC_BLSP1_UART_BCR(id) + 0x04)
+#define GCC_BLSP1_UART_APPS_CMD_RCGR(id)	(GCC_BLSP1_UART_BCR(id) + 0x0C)
+#define GCC_BLSP1_UART_APPS_CFG_RCGR(id)	(GCC_BLSP1_UART_BCR(id) + 0x10)
+#define GCC_BLSP1_UART_APPS_M(id)	    	(GCC_BLSP1_UART_BCR(id) + 0x14)
+#define GCC_BLSP1_UART_APPS_N(id)	    	(GCC_BLSP1_UART_BCR(id) + 0x18)
+#define GCC_BLSP1_UART_APPS_D(id)	    	(GCC_BLSP1_UART_BCR(id) + 0x1C)
+
+#define GCC_UART_CFG_RCGR_MODE_MASK	0x3000
+#define GCC_UART_CFG_RCGR_SRCSEL_MASK	0x0700
+#define GCC_UART_CFG_RCGR_SRCDIV_MASK	0x001F
+
+#define GCC_UART_CFG_RCGR_MODE_SHIFT	12
+#define GCC_UART_CFG_RCGR_SRCSEL_SHIFT	8
+#define GCC_UART_CFG_RCGR_SRCDIV_SHIFT	0
+
+#define UART_RCGR_SRC_SEL	0x1
+#define UART_RCGR_SRC_DIV	0x0
+#define UART_RCGR_MODE		0x2
+#define UART_CMD_RCGR_UPDATE	0x1
+#define UART_CBCR_CLK_ENABLE	0x1
+
+#define NOT_2D(two_d)		(~two_d)
+#define NOT_N_MINUS_M(n,m)	(~(n - m))
+#define CLOCK_UPDATE_TIMEOUT_US	1000
+
+int uart_clock_config(struct ipq_serial_platdata *plat);
+
 #endif /*IPQ6018_CLK_H*/
diff --git a/arch/arm/include/asm/arch-qca-common/qca_common.h b/arch/arm/include/asm/arch-qca-common/qca_common.h
index 534abc6..9f39f7e 100644
--- a/arch/arm/include/asm/arch-qca-common/qca_common.h
+++ b/arch/arm/include/asm/arch-qca-common/qca_common.h
@@ -107,6 +107,7 @@
 int bring_sec_core_up(unsigned int cpuid, unsigned int entry, unsigned int arg);
 int is_secondary_core_off(unsigned int cpuid);
 int smem_read_cpu_count(void);
+int get_soc_hw_version(void);
 
 struct dumpinfo_t{
 	char name[16]; /* use only file name in 8.3 format */
diff --git a/arch/arm/include/asm/arch-qca-common/qpic_nand.h b/arch/arm/include/asm/arch-qca-common/qpic_nand.h
index 642c3bd..5a5c7b2 100644
--- a/arch/arm/include/asm/arch-qca-common/qpic_nand.h
+++ b/arch/arm/include/asm/arch-qca-common/qpic_nand.h
@@ -112,6 +112,7 @@
 #define NAND_FLASH_SPI_CFG		NAND_REG(0x70C0)
 #define NAND_SPI_NUM_ADDR_CYCLES	NAND_REG(0x70C4)
 #define NAND_SPI_BUSY_CHECK_WAIT_CNT	NAND_REG(0x70C8)
+#define NAND_QSPI_MSTR_CONFIG           NAND_REG(0x7f60)
 
 /* Register mask & shift value used in SPI transfer mode */
 #define SPI_TRANSFER_MODE_1X		0x1
@@ -280,6 +281,7 @@
  */
 #define FLASH_SPI_NAND_FR_ADDR		0xB0
 #define FLASH_SPI_NAND_FR_ECC_ENABLE	(1 << 4)
+#define FLASH_SPI_NAND_FR_BUFF_ENABLE	(1 << 3)
 #define FLASH_SPI_NAND_FR_QUAD_ENABLE	0x1
 /* According to GigaDevice data sheet Status Register(0xC0) is:
  *  _________________________________________________
@@ -559,6 +561,7 @@
 	QCA_QPIC_V2_1_1,
 };
 
+extern unsigned int qpic_frequency, qpic_phase;
 
 /* result type */
 typedef enum {
diff --git a/arch/arm/include/asm/arch-qca-common/scm.h b/arch/arm/include/asm/arch-qca-common/scm.h
index 4bbe13f..fa7024e 100644
--- a/arch/arm/include/asm/arch-qca-common/scm.h
+++ b/arch/arm/include/asm/arch-qca-common/scm.h
@@ -21,6 +21,7 @@
 #define SCM_SVC_SSD			0x7
 #define SCM_SVC_FUSE			0x8
 #define SCM_SVC_PWR			0x9
+#define SCM_SVC_CRYPTO			0xA
 #define SCM_SVC_CP			0xC
 #define SCM_SVC_DCVS			0xD
 #define SCM_SVC_TZSCHEDULER		0xFC
@@ -33,6 +34,12 @@
 #define SCM_SVC_ID_SHIFT		0xA
 #define IS_CALL_AVAIL_CMD		0x1
 
+#ifdef CONFIG_IPQ_BT_SUPPORT
+#define SCM_PAS_INIT_IMAGE_CMD		0x1
+#define SCM_PAS_AUTH_AND_RESET_CMD	0x5
+#define SCM_CMD_OTP  			0x15
+#endif
+
 /* scm_v8 */
 #define SCM_VAL				0x0
 #define SCM_IO_READ			0x1
@@ -117,6 +124,7 @@
 int qca_scm_usb_mode_write(u32, u32);
 int qca_scm_call_write(u32, u32, u32 *, u32);
 int qca_scm_call_read(u32, u32, u32 *, u32 *);
+int qca_scm_crypto(int, void *, u32);
 int qca_scm_sdi(void);
 int qca_scm_dload(u32);
 int qca_scm_fuseipq(u32, u32, void *, size_t);
@@ -128,6 +136,11 @@
 #ifdef CONFIG_IPQ_TZT
 int qca_scm(u32 svc_id, u32 cmd_id, u32 ownr_id, u32 *addr, u32 len);
 #endif
+#ifdef CONFIG_IPQ_BT_SUPPORT
+int qti_scm_otp(u32 peripheral);
+int qti_scm_pas_init_image(u32 peripheral, u32 addr);
+int qti_pas_and_auth_reset(u32 peripheral);
+#endif
 #define MAX_QCA_SCM_RETS		3
 #define MAX_QCA_SCM_ARGS		10
 #define SCM_READ_OP			1
diff --git a/arch/arm/include/asm/arch-qca-common/smem.h b/arch/arm/include/asm/arch-qca-common/smem.h
index 3eaf6da..17b2ae5 100644
--- a/arch/arm/include/asm/arch-qca-common/smem.h
+++ b/arch/arm/include/asm/arch-qca-common/smem.h
@@ -61,6 +61,7 @@
 			uint32_t *flash_block_size,
 			uint32_t *flash_density);
 int smem_getpart(char *name, uint32_t *start, uint32_t *size);
+int smem_getpart_from_offset(uint32_t offset, uint32_t *start, uint32_t *size);
 int getpart_offset_size(char *part_name, uint32_t *offset, uint32_t *size);
 unsigned int smem_get_board_machtype(void);
 uint32_t get_nand_block_size(uint8_t dev_id);
diff --git a/arch/arm/include/asm/arch-qca-common/uart.h b/arch/arm/include/asm/arch-qca-common/uart.h
index f1c6474..cf9e839 100644
--- a/arch/arm/include/asm/arch-qca-common/uart.h
+++ b/arch/arm/include/asm/arch-qca-common/uart.h
@@ -88,6 +88,7 @@
 	int m_value;
 	int n_value;
 	int d_value;
+	int gpio_node;
 
 };
 
diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h
index 0b35248..c92b76b 100644
--- a/arch/arm/include/asm/mach-types.h
+++ b/arch/arm/include/asm/mach-types.h
@@ -1142,7 +1142,18 @@
 #define MACH_TYPE_IPQ40XX_AP_DK04_1_C6  0x8010501
 #define MACH_TYPE_IPQ6018_AP_CP01_C1  	0x8030000
 #define MACH_TYPE_IPQ6018_AP_CP01_C2  	0x8030001
+#define MACH_TYPE_IPQ6018_AP_CP01_C3  	0x8030002
 #define MACH_TYPE_IPQ6018_AP_CP01_C4    0x8030003
+#define MACH_TYPE_IPQ5018_AP_MP02_1	0x8040000
+#define MACH_TYPE_IPQ5018_DB_MP02_1	0X1040003
+#define MACH_TYPE_IPQ807x_AP_HK01_C1    0x8010000
+#define MACH_TYPE_IPQ807x_AP_HK01_C3    0x8010200
+#define MACH_TYPE_IPQ807x_AP_AC01	0x8010009
+#define MACH_TYPE_IPQ807x_AP_AC02	0x801000A
+#define MACH_TYPE_IPQ807x_AP_OAK03	0x801000D
+#define MACH_TYPE_IPQ807x_AP_HK01_C6    0x8010500
+#define MACH_TYPE_IPQ807x_AP_HK12_C1	0x8010013
+#define MACH_TYPE_IPQ807x_AP_HK10_C2	0x801010E
 
 #ifdef CONFIG_ARCH_EBSA110
 # ifdef machine_arch_type
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index f3db7b5..7a0fb58 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -6,7 +6,8 @@
 #
 
 lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _ashldi3.o _ashrdi3.o _divsi3.o \
-			_lshrdi3.o _modsi3.o _udivsi3.o _umodsi3.o div0.o
+			_lshrdi3.o _modsi3.o _udivsi3.o _umodsi3.o div0.o \
+			_uldivmod.o
 
 ifdef CONFIG_CPU_V7M
 obj-y	+= vectors_m.o crt0.o
diff --git a/board/ipq5018/Kconfig b/board/ipq5018/Kconfig
new file mode 100644
index 0000000..e1a56bc
--- /dev/null
+++ b/board/ipq5018/Kconfig
@@ -0,0 +1,54 @@
+if ARCH_IPQ5018
+
+config SYS_CPU
+       default "ipq5018"
+
+config SYS_BOARD
+       default "ipq5018"
+
+config SYS_VENDOR
+       default "qca/arm"
+
+config SYS_CONFIG_NAME
+       default "ipq5018"
+
+config IPQ5018_I2C
+	bool "Enable i2c support for ipq5018"
+
+config USB_XHCI_IPQ
+	bool "Enable usb support for ipq5018"
+
+config PCI_IPQ
+	bool "Enable pci support for ipq5018"
+
+config MMC_FLASH
+	bool "Enable MMC flash support for ipq5018"
+
+config IPQ_TZT
+	bool "Enable TZ test command for ipq5018"
+
+config UBI_WRITE
+	bool "Enable ubi volume write command for ipq5018"
+
+config QPIC_SERIAL
+	bool "Enable QPIC serial spi nand  for ipq5018"
+
+config IPQ_TINY
+	bool "Enable Tiny support for ipq5018"
+
+config IPQ_MTD_NOR
+	bool "Register nor in MTD framework for ipq5018"
+
+config IPQ_TINY_SPI_NOR
+	bool "This config helps to update spi-nor related updated in ipq5018"
+
+config NAND_FLASH
+	bool "Enable NAND driver for ipq5018"
+
+config GEPHY
+	bool "Enable Internel GEPHY for ipq5018"
+
+config ART_COMPRESSED
+	bool "Enable uncompress support for ipq5018"
+
+endif
diff --git a/board/qca/arm/common/board_init.c b/board/qca/arm/common/board_init.c
index c4d932b..c0d994c 100644
--- a/board/qca/arm/common/board_init.c
+++ b/board/qca/arm/common/board_init.c
@@ -25,10 +25,11 @@
 #include <cp_board.h>
 #include <blkdev.h>
 DECLARE_GLOBAL_DATA_PTR;
-
+#ifdef CONFIG_ENV_IS_IN_NAND
 extern int nand_env_device;
 extern env_t *nand_env_ptr;
 extern char *nand_env_name_spec;
+#endif
 extern char *sf_env_name_spec;
 extern int nand_saveenv(void);
 extern int sf_saveenv(void);
@@ -144,12 +145,16 @@
 
 #ifndef CONFIG_ENV_IS_NOWHERE
 	switch (sfi->flash_type) {
+#ifdef CONFIG_ENV_IS_IN_NAND
 	case SMEM_BOOT_NAND_FLASH:
 	case SMEM_BOOT_QSPI_NAND_FLASH:
 		nand_env_device = CONFIG_NAND_FLASH_INFO_IDX;
 		break;
+#endif
 	case SMEM_BOOT_SPI_FLASH:
+#ifdef CONFIG_ENV_IS_IN_NAND
 		nand_env_device = CONFIG_SPI_FLASH_INFO_IDX;
+#endif
 		break;
 	case SMEM_BOOT_MMC_FLASH:
 	case SMEM_BOOT_NO_FLASH:
@@ -182,10 +187,12 @@
 		break;
 #ifdef CONFIG_QCA_MMC
 	case SMEM_BOOT_MMC_FLASH:
-	case SMEM_BOOT_NO_FLASH:
 		board_env_range = CONFIG_ENV_SIZE_MAX;
 		break;
 #endif
+	case SMEM_BOOT_NO_FLASH:
+		board_env_range = CONFIG_ENV_SIZE_MAX;
+		break;
 	default:
 		printf("BUG: unsupported flash type : %d\n", sfi->flash_type);
 		BUG();
@@ -202,14 +209,22 @@
 		env_name_spec = mmc_env_name_spec;
 #endif
 	} else {
+#ifdef CONFIG_ENV_IS_IN_NAND
 		saveenv = nand_saveenv;
 		env_ptr = nand_env_ptr;
 		env_name_spec = nand_env_name_spec;
+#else
+		saveenv = sf_saveenv;
+		env_name_spec = sf_env_name_spec;
+
+#endif
 	}
 #endif
-	ret = ipq_board_usb_init();
-	if (ret < 0) {
-		printf("WARN: ipq_board_usb_init failed\n");
+	if (sfi->flash_type != SMEM_BOOT_NO_FLASH) {
+		ret = ipq_board_usb_init();
+		if (ret < 0) {
+			printf("WARN: ipq_board_usb_init failed\n");
+		}
 	}
 
 	aquantia_phy_reset_init();
@@ -345,11 +360,17 @@
 }
 #endif
 
+__weak int get_soc_hw_version(void)
+{
+	return 0;
+}
+
 int board_late_init(void)
 {
 	unsigned int machid;
 	uint32_t flash_type;
 	uint32_t soc_ver_major, soc_ver_minor;
+	uint32_t soc_hw_version;
 	int ret;
 	char *s = NULL;
 
@@ -377,6 +398,10 @@
 		setenv_ulong("soc_version_major", (unsigned long)soc_ver_major);
 		setenv_ulong("soc_version_minor", (unsigned long)soc_ver_minor);
 	}
+
+	soc_hw_version = get_soc_hw_version();
+	if (soc_hw_version)
+		setenv_hex("soc_hw_version", (unsigned long)soc_hw_version);
 #ifdef CONFIG_FLASH_PROTECT
 	board_flash_protect();
 #endif
diff --git a/board/qca/arm/common/cmd_bootqca.c b/board/qca/arm/common/cmd_bootqca.c
index 245786b..418e837 100644
--- a/board/qca/arm/common/cmd_bootqca.c
+++ b/board/qca/arm/common/cmd_bootqca.c
@@ -204,40 +204,54 @@
 	 * or board name based config is used.
 	 */
 
+#ifdef CONFIG_ARCH_IPQ806x
 	int soc_version = 0;
+#endif
+	int i, strings_count;
 	const char *config = getenv("config_name");
 
 	if (config) {
 		printf("Manual device tree config selected!\n");
 		strlcpy(dtb_config_name, config, sizeof(dtb_config_name));
-	} else {
-		config = fdt_getprop(gd->fdt_blob, 0, "config_name", NULL);
+		if (fit_conf_get_node((void *)addr, dtb_config_name) >= 0) {
+			snprintf(rcmd, rcmd_size, "bootm 0x%x#%s\n",
+				 addr, dtb_config_name);
+			return 0;
+		}
 
-		if(config == NULL) {
+	} else {
+		strings_count = fdt_count_strings(gd->fdt_blob, 0, "config_name");
+
+		if (!strings_count) {
 			printf("Failed to get config_name\n");
 			return -1;
 		}
 
-		snprintf((char *)dtb_config_name,
-			 sizeof(dtb_config_name), "%s", config);
+		for (i = 0; i < strings_count; i++) {
+			fdt_get_string_index(gd->fdt_blob, 0, "config_name",
+					   i, &config);
 
-		ipq_smem_get_socinfo_version((uint32_t *)&soc_version);
+			snprintf((char *)dtb_config_name,
+				 sizeof(dtb_config_name), "%s", config);
+
 #ifdef CONFIG_ARCH_IPQ806x
-		if(SOCINFO_VERSION_MAJOR(soc_version) >= 2) {
-			snprintf(dtb_config_name + strlen("config@"),
-				 sizeof(dtb_config_name) - strlen("config@"),
-				 "v%d.0-%s",
-				 SOCINFO_VERSION_MAJOR(soc_version),
-				 config + strlen("config@"));
-		}
+			ipq_smem_get_socinfo_version((uint32_t *)&soc_version);
+			if(SOCINFO_VERSION_MAJOR(soc_version) >= 2) {
+				snprintf(dtb_config_name + strlen("config@"),
+					 sizeof(dtb_config_name) - strlen("config@"),
+					 "v%d.0-%s",
+					 SOCINFO_VERSION_MAJOR(soc_version),
+					 config + strlen("config@"));
+			}
 #endif
+			if (fit_conf_get_node((void *)addr, dtb_config_name) >= 0) {
+				snprintf(rcmd, rcmd_size, "bootm 0x%x#%s\n",
+					 addr, dtb_config_name);
+				return 0;
+			}
+		}
 	}
 
-	if (fit_conf_get_node((void *)addr, dtb_config_name) >= 0) {
-		snprintf(rcmd, rcmd_size, "bootm 0x%x#%s\n",
-			 addr, dtb_config_name);
-		return 0;
-	}
 	printf("Config not available\n");
 	snprintf(rcmd, rcmd_size, "bootm 0x%x\n", addr);
 	return 0;
@@ -473,6 +487,7 @@
 	kernel_img_info.kernel_load_addr = request;
 
 	if (ipq_fs_on_nand) {
+#ifdef CONFIG_CMD_UBI
 		/*
 		 * The kernel will be available inside a UBI volume
 		 */
@@ -513,6 +528,7 @@
 
 		kernel_img_info.kernel_load_size =
 			(unsigned int)ubi_get_volume_size("kernel");
+#endif
 #ifdef CONFIG_QCA_MMC
 	} else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH ||
 			((sfi->flash_type == SMEM_BOOT_SPI_FLASH) &&
diff --git a/board/qca/arm/common/cmd_runmulticore.c b/board/qca/arm/common/cmd_runmulticore.c
index e9e51a7..b175162 100644
--- a/board/qca/arm/common/cmd_runmulticore.c
+++ b/board/qca/arm/common/cmd_runmulticore.c
@@ -58,6 +58,16 @@
 	bring_secondary_core_down(state);
 }
 
+static void disable_console(void)
+{
+	gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
+}
+
+static void enable_console(void)
+{
+	gd->flags &= ~(GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE);
+}
+
 int do_runmulticore(cmd_tbl_t *cmdtp,
 			   int flag, int argc, char *const argv[])
 {
@@ -109,6 +119,7 @@
 	for (i = 1; i < argc; i++) {
 		printf("Scheduling Core %d\n", i);
 		delay = 0;
+		disable_console();
 		ret = bring_sec_core_up(i, (unsigned int)secondary_cpu_init,
 				(unsigned int)&(core[i - 1]));
 		if (ret) {
@@ -121,6 +132,7 @@
 		if (!(core[i - 1].cpu_up)) {
 			panic("Can't bringup core %d\n",i);
 		}
+		enable_console();
 
 		core_status |= (BIT(i - 1));
 		core_on_status |= (BIT(i - 1));
diff --git a/board/qca/arm/common/cmd_tzt.c b/board/qca/arm/common/cmd_tzt.c
index 4dc8d84..10e943f 100644
--- a/board/qca/arm/common/cmd_tzt.c
+++ b/board/qca/arm/common/cmd_tzt.c
@@ -117,6 +117,7 @@
 	u32 img_addr;
 	u32 img_size;
 	u32 args[MAX_QCA_SCM_ARGS + 1];
+	int ret;
 
 	/* at least two arguments should be there */
 	if (argc < 2)
@@ -133,15 +134,24 @@
 		args[0] = QCA_SCM_ARGS(2, SCM_IO_WRITE);
 		args[1] = TZT_LOAD_ADDR;
 		args[2] = TZT_LOAD_SIZE;
-		qca_scm(SCM_SVC_APP_MGR, REGION_NOTIFICATION_ID,
+		ret = qca_scm(SCM_SVC_APP_MGR, REGION_NOTIFICATION_ID,
 			SCM_OWNR_QSEE_OS, args, 3);
+		if (ret) {
+			printf("tzt load failed ret = %d\n", ret);
+			return -1;
+		}
 
 		args[0] = QCA_SCM_ARGS(3);
 		args[1] = MDT_SIZE;
 		args[2] = img_size - MDT_SIZE;
 		args[3] = img_addr;
-		qca_scm(SCM_SVC_EXTERNAL, LOAD_TZTESTEXEC_IMG_ID,
+		ret = qca_scm(SCM_SVC_EXTERNAL, LOAD_TZTESTEXEC_IMG_ID,
 			SCM_OWNR_QSEE_OS, args, 4);
+		if (ret) {
+			printf("tzt load failed ret = %d\n", ret);
+			return -1;
+		}
+
 		tzt_loaded = 1;
 		return 0;
 	}
diff --git a/board/qca/arm/common/crashdump.c b/board/qca/arm/common/crashdump.c
index a3efdfc..b7b4097 100644
--- a/board/qca/arm/common/crashdump.c
+++ b/board/qca/arm/common/crashdump.c
@@ -97,6 +97,8 @@
        int cur_page_data_len;
        int write_size;
        unsigned char temp_data[MAX_NAND_PAGE_SIZE];
+       uint32_t part_start;
+       uint32_t part_size;
 };
 
 #ifdef CONFIG_QCA_SPI
@@ -118,8 +120,9 @@
 };
 #endif
 
-
+#ifdef CONFIG_MTD_DEVICE
 static struct crashdump_flash_nand_cxt crashdump_nand_cnxt;
+#endif
 #ifdef CONFIG_QCA_SPI
 static struct spi_flash *crashdump_spi_flash;
 static struct crashdump_flash_spi_cxt crashdump_flash_spi_cnxt;
@@ -275,13 +278,18 @@
 	while (static_enum_count < 3) {
 		ret_val = qca_wdt_scm_extract_tlv_info(scm_tlv_msg,
 			&cur_type, &cur_size);
-		if (!ret_val && cur_type == QCA_WDT_LOG_DUMP_TYPE_UNAME ){
+		if (ret_val)
+			return ret_val;
+
+		switch (cur_type) {
+		case QCA_WDT_LOG_DUMP_TYPE_UNAME:
 			crashdump_data->uname_length = cur_size;
 			ret_val = qca_wdt_scm_extract_tlv_data(scm_tlv_msg,
 					crashdump_data->uname, cur_size);
 			crashdump_tlv_count++;
 			static_enum_count++;
-		}else if (!ret_val && cur_type == QCA_WDT_LOG_DUMP_TYPE_DMESG){
+			break;
+		case QCA_WDT_LOG_DUMP_TYPE_DMESG:
 			ret_val = qca_wdt_scm_extract_tlv_data(scm_tlv_msg,
 				(unsigned char *)&tlv_info,
 				cur_size);
@@ -291,7 +299,8 @@
 		         }
 			crashdump_tlv_count++;
 			static_enum_count++;
-		}else if (!ret_val && cur_type == QCA_WDT_LOG_DUMP_TYPE_LEVEL1_PT){
+			break;
+		case QCA_WDT_LOG_DUMP_TYPE_LEVEL1_PT:
 			ret_val = qca_wdt_scm_extract_tlv_data(scm_tlv_msg,(unsigned char *)&tlv_info,cur_size);
 			if (!ret_val) {
 				crashdump_data->pt_start =(unsigned char *)(uintptr_t)tlv_info.start;
@@ -299,12 +308,18 @@
 			}
 			crashdump_tlv_count++;
 			static_enum_count++;
-		}
-		else if(!ret_val && cur_type == QCA_WDT_LOG_DUMP_TYPE_WLAN_MOD) {
+			break;
+		case QCA_WDT_LOG_DUMP_TYPE_WLAN_MOD:
 			tlv_size = (cur_size + QCA_WDT_SCM_TLV_TYPE_LEN_SIZE);
 			scm_tlv_msg->cur_msg_buffer_pos += tlv_size;
+			break;
+		default:
+			printf("%s: invalid dump type\n", __func__);
+			ret_val = -EINVAL;
+			goto err;
 		}
 	}
+err:
 	return ret_val;
 }
 
@@ -714,8 +729,16 @@
 		printf("\nHit any key within 10s to stop dump activity...");
 		while (!tstc()) {       /* while no incoming data */
 			if (get_timer_masked() >= etime) {
-				if (do_dumpqca_data(dump_level) == CMD_RET_FAILURE)
-					printf("Crashdump saving failed!\n");
+				if (getenv("dump_minimal_and_full")) { 
+					/* dump minidump and full dump*/
+					if (do_dumpqca_data(MINIMAL_DUMP) == CMD_RET_FAILURE)
+						printf("Minidump saving failed!\n");
+					if (do_dumpqca_data(FULL_DUMP) == CMD_RET_FAILURE)
+						printf("Crashdump saving failed!\n");
+				} else {
+					if (do_dumpqca_data(dump_level) == CMD_RET_FAILURE)
+						printf("Crashdump saving failed!\n");
+				}
 				break;
 			}
 		}
@@ -726,6 +749,98 @@
 reset:
 	reset_board();
 }
+#ifdef CONFIG_MTD_DEVICE
+
+/*
+* NAND flash check and write. Before writing into the nand flash
+* this function checks if the block is non-bad, and skips if bad. While
+* skipping, there is also possiblity of crossing the partition and corrupting
+* next partition with crashdump data. So this function also checks whether
+* offset is within the partition, where the configured offset belongs.
+*
+* Returns 0 on succes and 1 otherwise
+*/
+static int check_and_write_crashdump_nand_flash(
+			struct crashdump_flash_nand_cxt *nand_cnxt,
+			nand_info_t *nand, unsigned char *data,
+			unsigned int req_size)
+{
+	nand_erase_options_t nand_erase_options;
+	uint32_t part_start = nand_cnxt->part_start;
+	uint32_t part_end = nand_cnxt->part_start + nand_cnxt->part_size;
+	unsigned int remaining_len = req_size;
+	unsigned int write_length, data_offset = 0;
+	loff_t skipoff, skipoff_cmp, *offset;
+	int ret = 0;
+	static int first_erase = 1;
+
+	offset = &nand_cnxt->cur_crashdump_offset;
+
+	memset(&nand_erase_options, 0, sizeof(nand_erase_options));
+	nand_erase_options.length = nand->erasesize;
+
+	while (remaining_len)
+	{
+
+		skipoff = *offset - (*offset & (nand->erasesize - 1));
+		skipoff_cmp = skipoff;
+
+		for (; skipoff < part_end; skipoff += nand->erasesize) {
+			if (nand_block_isbad(nand, skipoff)) {
+				printf("Skipping bad block at 0x%llx\n", skipoff);
+				continue;
+			}
+			else
+				break;
+		}
+		if (skipoff_cmp != skipoff)
+			*offset = skipoff;
+
+		if(part_start > *offset || ((*offset + remaining_len) >= part_end)) {
+			printf("Failure: Attempt to write in next partition\n");
+			return 1;
+		}
+
+		if((*offset & (nand->erasesize - 1)) == 0 || first_erase){
+			nand_erase_options.offset = *offset;
+
+			ret = nand_erase_opts(&nand_info[0],
+					&nand_erase_options);
+			if (ret)
+				return ret;
+			first_erase = 0;
+		}
+
+		if( remaining_len > nand->erasesize) {
+
+			skipoff = (*offset & (nand->erasesize - 1));
+
+			write_length = (skipoff != 0) ? (nand->erasesize - skipoff)
+							: (nand->erasesize);
+
+			ret = nand_write(nand, *offset, &write_length,
+				data + data_offset);
+
+			if (ret)
+				return ret;
+
+			remaining_len -= write_length;
+			*offset += write_length;
+			data_offset += write_length;
+		}
+		else {
+
+			ret = nand_write(nand, *offset, &remaining_len,
+				data + data_offset);
+
+			*offset += remaining_len;
+			remaining_len = 0;
+		}
+	}
+
+	return ret;
+
+}
 
 /*
 * Init function for NAND flash writing. It intializes its own context
@@ -734,10 +849,14 @@
 int init_crashdump_nand_flash_write(void *cnxt, loff_t offset,
 					unsigned int total_size)
 {
-	nand_erase_options_t nand_erase_options;
 	struct crashdump_flash_nand_cxt *nand_cnxt = cnxt;
 	int ret;
 
+	ret = smem_getpart_from_offset(offset, &nand_cnxt->part_start,
+						&nand_cnxt->part_size);
+	if (ret)
+		return ret;
+
 	nand_cnxt->start_crashdump_offset = offset;
 	nand_cnxt->cur_crashdump_offset = offset;
 	nand_cnxt->cur_page_data_len = 0;
@@ -748,16 +867,6 @@
 		return -ENOMEM;
 	}
 
-	memset(&nand_erase_options, 0, sizeof(nand_erase_options));
-
-	nand_erase_options.length = total_size;
-	nand_erase_options.offset = offset;
-
-	ret = nand_erase_opts(&nand_info[0],
-			&nand_erase_options);
-	if (ret)
-		return ret;
-
 	return 0;
 }
 
@@ -782,9 +891,11 @@
 			0xFF, remaining_bytes);
 
 		cur_nand_write_len = nand_cnxt->write_size;
-		ret_val = nand_write(&nand_info[0],
-				nand_cnxt->cur_crashdump_offset,
-				&cur_nand_write_len, nand_cnxt->temp_data);
+
+		ret_val = check_and_write_crashdump_nand_flash(nand_cnxt,
+					&nand_info[0], nand_cnxt->temp_data,
+					cur_nand_write_len);
+
 	}
 
 	return ret_val;
@@ -832,15 +943,14 @@
 	memcpy(nand_cnxt->temp_data + nand_cnxt->cur_page_data_len, data,
 			remaining_len_cur_page);
 
-	ret_val = nand_write(&nand_info[0], nand_cnxt->cur_crashdump_offset,
-				&cur_nand_write_len,
-				nand_cnxt->temp_data);
+	ret_val = check_and_write_crashdump_nand_flash(nand_cnxt,
+					&nand_info[0], nand_cnxt->temp_data,
+					cur_nand_write_len);
 
 	if (ret_val)
 		return ret_val;
 
 	cur_data_pos += remaining_len_cur_page;
-	nand_cnxt->cur_crashdump_offset += cur_nand_write_len;
 
 	/*
 	* Calculate the write length in multiple of page length and do the nand
@@ -850,17 +960,16 @@
 				nand_cnxt->write_size) * nand_cnxt->write_size;
 
 	if (cur_nand_write_len > 0) {
-		ret_val = nand_write(&nand_info[0],
-				nand_cnxt->cur_crashdump_offset,
-				&cur_nand_write_len,
-				cur_data_pos);
+		ret_val = check_and_write_crashdump_nand_flash(nand_cnxt,
+						&nand_info[0], cur_data_pos,
+						cur_nand_write_len);
 
 		if (ret_val)
 			return ret_val;
+
 	}
 
 	cur_data_pos += cur_nand_write_len;
-	nand_cnxt->cur_crashdump_offset += cur_nand_write_len;
 
 	/* Store the remaining data in temp data */
 	remaining_bytes = data + size - cur_data_pos;
@@ -871,7 +980,7 @@
 
 	return 0;
 }
-
+#endif
 #ifdef CONFIG_QCA_SPI
 /* Init function for SPI NOR flash writing. It erases the required sectors */
 int init_crashdump_spi_flash_write(void *cnxt,
@@ -1113,11 +1222,13 @@
 	*/
 	if (((flash_type == SMEM_BOOT_NAND_FLASH) ||
 		(flash_type == SMEM_BOOT_QSPI_NAND_FLASH))) {
+#ifdef CONFIG_MTD_DEVICE
 		crashdump_cnxt = (void *)&crashdump_nand_cnxt;
 		crashdump_flash_write_init = init_crashdump_nand_flash_write;
 		crashdump_flash_write = crashdump_nand_flash_write_data;
 		crashdump_flash_write_deinit =
 			deinit_crashdump_nand_flash_write;
+#endif
 #ifdef CONFIG_QCA_SPI
 	} else if (flash_type == SMEM_BOOT_SPI_FLASH) {
 		if (!crashdump_spi_flash) {
@@ -1227,22 +1338,24 @@
 	tlv_msg.len = CONFIG_TLV_DUMP_SIZE;
 
 	ret_val = qca_wdt_extract_crashdump_data(&tlv_msg, &g_crashdump_data);
-
-	if (!ret_val) {
-		if (getenv("dump_to_flash")) {
-			ret_val = qca_wdt_write_crashdump_data(&g_crashdump_data,
-					flash_type, crashdump_offset);
-		} else {
-			dump_func(MINIMAL_DUMP);
-		}
-	}
-
 	if (ret_val) {
-		printf("crashdump data writing in flash failure\n");
-		return -EPERM;
+		printf("%s: crashdump extraction failed\n", __func__);
+		return ret_val;
 	}
 
-	printf("crashdump data writing in flash successful\n");
+	if (getenv("dump_to_flash")) {
+		ret_val = qca_wdt_write_crashdump_data(&g_crashdump_data,
+						       flash_type,
+						       crashdump_offset);
+		if (ret_val) {
+			printf("crashdump data writing in flash failure\n");
+			return -EPERM;
+		}
+
+		printf("crashdump data writing in flash successful\n");
+	} else {
+		dump_func(MINIMAL_DUMP);
+	}
 
 	return 0;
 }
diff --git a/board/qca/arm/common/env.c b/board/qca/arm/common/env.c
index 3050b82..5fab9a5 100644
--- a/board/qca/arm/common/env.c
+++ b/board/qca/arm/common/env.c
@@ -18,10 +18,10 @@
 #ifdef CONFIG_SDHCI_SUPPORT
 #include <sdhci.h>
 #endif
-
+#ifdef CONFIG_ENV_IS_IN_NAND
 extern void nand_env_relocate_spec(void);
 extern int nand_env_init(void);
-
+#endif
 #ifdef CONFIG_ENV_IS_IN_SPI_FLASH
 extern void sf_env_relocate_spec(void);
 extern int sf_env_init(void);
@@ -58,7 +58,9 @@
 		ret = mmc_env_init();
 #endif
 	} else {
+#ifdef CONFIG_ENV_IS_IN_NAND
 		ret = nand_env_init();
+#endif
 	}
 
 	return ret;
@@ -85,7 +87,9 @@
                 mmc_env_relocate_spec();
 #endif
 	} else {
+#ifdef CONFIG_ENV_IS_IN_NAND
 		nand_env_relocate_spec();
+#endif
 	}
 
 };
@@ -125,3 +129,27 @@
 	return ret;
 }
 #endif
+
+void set_platform_specific_default_env(void)
+{
+	uint32_t soc_ver_major, soc_ver_minor, soc_version;
+	uint32_t machid;
+	uint32_t soc_hw_version;
+	int ret;
+
+	machid = smem_get_board_platform_type();
+	if (machid != 0)
+		setenv_addr("machid", (void *)machid);
+
+	soc_hw_version = get_soc_hw_version();
+	if (soc_hw_version)
+		setenv_hex("soc_hw_version", (unsigned long)soc_hw_version);
+
+	ret = ipq_smem_get_socinfo_version((uint32_t *)&soc_version);
+	if (!ret) {
+		soc_ver_major = SOCINFO_VERSION_MAJOR(soc_version);
+		soc_ver_minor = SOCINFO_VERSION_MINOR(soc_version);
+		setenv_ulong("soc_version_major", (unsigned long)soc_ver_major);
+		setenv_ulong("soc_version_minor", (unsigned long)soc_ver_minor);
+	}
+}
diff --git a/board/qca/arm/common/ethaddr.c b/board/qca/arm/common/ethaddr.c
index cd7af73..4809f4c 100644
--- a/board/qca/arm/common/ethaddr.c
+++ b/board/qca/arm/common/ethaddr.c
@@ -19,7 +19,18 @@
 #include <asm/arch-qca-common/smem.h>
 #include <asm/arch-qca-common/qca_common.h>
 #include <sdhci.h>
-
+#ifdef CONFIG_IPQ_TINY_SPI_NOR
+#include <spi.h>
+#include <spi_flash.h>
+#endif
+#if defined(CONFIG_ART_COMPRESSED) &&	\
+	(defined(CONFIG_GZIP) || defined(CONFIG_LZMA))
+#ifndef CONFIG_COMPRESSED_LOAD_ADDR
+#define CONFIG_COMPRESSED_LOAD_ADDR CONFIG_SYS_LOAD_ADDR
+#endif
+#include <mapmem.h>
+#include <lzma/LzmaTools.h>
+#endif
 #ifdef CONFIG_QCA_MMC
 #ifndef CONFIG_SDHCI_SUPPORT
 extern qca_mmc mmc_host;
@@ -46,6 +57,15 @@
 	struct mmc *mmc;
 	char mmc_blks[512];
 #endif
+#ifdef CONFIG_IPQ_TINY_SPI_NOR
+	struct spi_flash *flash = NULL;
+#if defined(CONFIG_ART_COMPRESSED) && (defined(CONFIG_GZIP) || defined(CONFIG_LZMA))
+	void *load_buf, *image_buf;
+	unsigned long img_size;
+	unsigned long desMaxSize;
+#endif
+#endif
+
 	if (sfi->flash_type != SMEM_BOOT_MMC_FLASH) {
 		if (qca_smem_flash_info.flash_type == SMEM_BOOT_SPI_FLASH)
 			flash_type = CONFIG_SPI_FLASH_INFO_IDX;
@@ -70,8 +90,50 @@
 		art_offset =
 		((loff_t) qca_smem_flash_info.flash_block_size * start_blocks);
 
+#ifdef CONFIG_IPQ_TINY_SPI_NOR
+		flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS,
+				CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
+		if (flash == NULL){
+			printf("No SPI flash device found\n");
+			ret = -1;
+		} else {
+#if defined(CONFIG_ART_COMPRESSED) && (defined(CONFIG_GZIP) || defined(CONFIG_LZMA))
+		image_buf = map_sysmem(CONFIG_COMPRESSED_LOAD_ADDR, 0);
+		load_buf = map_sysmem(CONFIG_COMPRESSED_LOAD_ADDR + 0x100000, 0);
+		img_size = qca_smem_flash_info.flash_block_size * size_blocks;
+		desMaxSize = 0x100000;
+		ret = spi_flash_read(flash, art_offset, img_size, image_buf);
+		if (ret == 0) {
+			ret = -1;
+#ifdef CONFIG_GZIP
+			ret = gunzip(load_buf, desMaxSize, image_buf, &img_size);
+#endif
+#ifdef CONFIG_LZMA
+			if (ret != 0)
+				ret = lzmaBuffToBuffDecompress(load_buf,
+					(SizeT *)&desMaxSize,
+					image_buf,
+					(SizeT)img_size);
+#endif
+			if (ret == 0) {
+				memcpy(enetaddr, load_buf, length);
+			} else {
+				printf("Invalid compression type..\n");
+				ret = -1;
+			}
+		}
+#else
+		ret = spi_flash_read(flash, art_offset, length, enetaddr);
+#endif
+		}
+		/*
+		 * Avoid unused warning
+		 */
+		(void)flash_type;
+#else
 		ret = nand_read(&nand_info[flash_type],
 				art_offset, &length, enetaddr);
+#endif
 		if (ret < 0)
 			printf("ART partition read failed..\n");
 #ifdef CONFIG_QCA_MMC
diff --git a/board/qca/arm/common/fdt_fixup.c b/board/qca/arm/common/fdt_fixup.c
index 197105c..ae754a3 100644
--- a/board/qca/arm/common/fdt_fixup.c
+++ b/board/qca/arm/common/fdt_fixup.c
@@ -16,9 +16,13 @@
 #include <asm/arch-qca-common/scm.h>
 #include <jffs2/load_kernel.h>
 #include <fdtdec.h>
+#include <stdlib.h>
+#include "fdt_info.h"
+
 #include <led_control.h>
 #include <cp_board.h>
 #include <bootconfig.h>
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef CONFIG_IPQ_FDT_FIXUP
@@ -164,7 +168,162 @@
 	}
 #endif /* RPM_VERSION */
 }
+#ifdef CONFIG_IPQ_TINY
+#define		OFFSET_NOT_SPECIFIED	(~0llu)
+struct reg_cell {
+	unsigned int r0;
+	unsigned int r1;
+};
 
+extern int fdt_del_partitions(void *blob, int parent_offset);
+
+int parse_nor_partition(const char *const partdef,
+			const char **ret,
+			struct part_info **retpart);
+
+void free_parse(struct list_head *head);
+
+static void ipq_nor_fdt_fixup(void *blob, struct flash_node_info *ni)
+{
+	int parent_offset;
+	struct part_info *part, *pPartInfo;
+	struct reg_cell cell;
+	int off, ndepth = 0;
+	int part_num, ret, newoff;
+	char buf[64];
+	int offset = 0;
+	struct list_head *pentry;
+	LIST_HEAD(tmp_list);
+	const char *pMtdparts =  getenv("mtdparts");
+
+	if (!pMtdparts)
+		return;
+
+	for (; ni->compat; ni++) {
+		parent_offset = fdt_node_offset_by_compatible(
+					blob, -1, ni->compat);
+		if (parent_offset != -FDT_ERR_NOTFOUND)
+			break;
+	}
+
+	if (parent_offset == -FDT_ERR_NOTFOUND){
+		printf(" compatible not found \n");
+		return;
+	}
+
+	ret = fdt_del_partitions(blob, parent_offset);
+	if (ret < 0)
+		return;
+
+	/*
+	 * Check if it is nand {}; subnode, adjust
+	 * the offset in this case
+	 */
+	off = fdt_next_node(blob, parent_offset, &ndepth);
+	if (off > 0 && ndepth == 1)
+		parent_offset = off;
+
+	if (strncmp(pMtdparts, "mtdparts=", 9) == 0) {
+		pMtdparts += 9;
+		pMtdparts = strchr(pMtdparts, ':');
+		pMtdparts++;
+	} else {
+		printf("mtdparts variable doesn't start with 'mtdparts='\n");
+		return;
+	}
+
+	part_num = 0;
+
+	while (pMtdparts && (*pMtdparts != '\0') && (*pMtdparts != ';')) {
+		if ((parse_nor_partition(pMtdparts, &pMtdparts, &pPartInfo) != 0))
+			break;
+
+		/* calculate offset when not specified */
+		if (pPartInfo->offset == OFFSET_NOT_SPECIFIED)
+			pPartInfo->offset = offset;
+		else
+			offset = pPartInfo->offset;
+
+		offset += pPartInfo->size;
+		/* partition is ok, add it to the list */
+		list_add_tail(&pPartInfo->link, &tmp_list);
+	}
+	list_for_each_prev(pentry, &tmp_list) {
+
+		part = list_entry(pentry, struct part_info, link);
+
+		debug("%2d: %-20s0x%08llx\t0x%08llx\t%d\n",
+			part_num, part->name, part->size,
+			part->offset, part->mask_flags);
+
+		snprintf(buf, sizeof(buf), "partition@%llx", part->offset);
+add_sub:
+		ret = fdt_add_subnode(blob, parent_offset, buf);
+		if (ret == -FDT_ERR_NOSPACE) {
+			ret = fdt_increase_size(blob, 512);
+			if (!ret)
+				goto add_sub;
+			else
+				goto err_size;
+		} else if (ret < 0) {
+			printf("Can't add partition node: %s\n",
+				fdt_strerror(ret));
+			return;
+		}
+		newoff = ret;
+
+		/* Check MTD_WRITEABLE_CMD flag */
+		if (pPartInfo->mask_flags & 1) {
+add_ro:
+			ret = fdt_setprop(blob, newoff, "read_only", NULL, 0);
+			if (ret == -FDT_ERR_NOSPACE) {
+				ret = fdt_increase_size(blob, 512);
+				if (!ret)
+					goto add_ro;
+				else
+					goto err_size;
+			} else if (ret < 0)
+				goto err_prop;
+		}
+
+		cell.r0 = cpu_to_fdt32(part->offset);
+		cell.r1 = cpu_to_fdt32(part->size);
+add_reg:
+		ret = fdt_setprop(blob, newoff, "reg", &cell, sizeof(cell));
+		if (ret == -FDT_ERR_NOSPACE) {
+			ret = fdt_increase_size(blob, 512);
+			if (!ret)
+				goto add_reg;
+			else
+				goto err_size;
+		} else if (ret < 0)
+			goto err_prop;
+
+add_label:
+		ret = fdt_setprop_string(blob, newoff, "label", part->name);
+		if (ret == -FDT_ERR_NOSPACE) {
+			ret = fdt_increase_size(blob, 512);
+			if (!ret)
+				goto add_label;
+			else
+				goto err_size;
+		} else if (ret < 0)
+			goto err_prop;
+
+		part_num++;
+	}
+	goto remove_list;
+err_size:
+	printf("Can't increase blob size: %s\n", fdt_strerror(ret));
+	goto remove_list;
+err_prop:
+	printf("Can't add property: %s\n", fdt_strerror(ret));
+	goto remove_list;
+remove_list:
+	free_parse(&tmp_list);
+	return;
+}
+#else
 void ipq_fdt_fixup_mtdparts(void *blob, struct flash_node_info *ni)
 {
 	struct mtd_device *dev;
@@ -193,6 +352,7 @@
 		}
 	}
 }
+#endif
 
 void ipq_fdt_mem_rsvd_fixup(void *blob)
 {
@@ -242,9 +402,13 @@
 	/* Set the dload_status to DLOAD_DISABLE */
 	nodeoff = fdt_path_offset(blob, "/soc/qca,scm_restart_reason");
 	if (nodeoff < 0) {
-		debug("fdt-fixup: unable to find compatible node\n");
-		return;
+		nodeoff = fdt_path_offset(blob, "/qti,scm_restart_reason");
+		if (nodeoff < 0) {
+			debug("fdt-fixup: unable to find compatible node\n");
+			return;
+		}
 	}
+
 	ret = fdt_setprop(blob, nodeoff, "dload_status", &dload, sizeof(dload));
 	if (ret != 0) {
 		debug("fdt-fixup: unable to find compatible node\n");
@@ -489,60 +653,148 @@
 }
 
 #ifdef CONFIG_IPQ_FDT_FIXUP
+/* setenv fdteditnum <num>   - here <num> represents number of envs to parse
+ * Note: without setting 'fdteditnum' fdtedit envs will not parsed
+ *
+ * fdtedit<num> <node>%<property>%<node_value>   - dts patching env format
+ * here '%' is separator; <num> can be between 1 to 99;
+ *
+ * 1. To change add/change a particular property of a node:
+ *       setenv fdtedit0 <node_path>%<property>%<value>
+ *
+ *    This can be used to add properties which doesn't have any value associated
+ *       eg: qca,secure; property of q6v5_wcss@CD00000 node can be added as:
+ *       setenv fdtedit0 /soc/q6v5_wcss@CD00000/%qca,secure%1
+ *    other eg:
+ *       fdtedit0=/soc/q6v5_wcss@CD00000%qca,sec-reset-cmd%0x19
+ *       fdtedit1=/soc/usb3@8A00000/dwc3@8A00000%dr_mode%?peripheral
+ *       fdtedit2=/soc/qcom,gadget_diag@0/%status%?ok
+ *
+ * 2. To delete a property of a node:
+ *       setenv fdtedit0 <node_path>%delete%<property>
+ *    example:
+ *       fdtedit0=/soc/q6v5_wcss@CD00000%delete%?qca,secure
+ *
+ * The last param in both add or delete case, if it is a string, it should
+ * start with '?' else if it is a number, it can be put directly.
+ * check above examples for reference.
+ *
+ * 3. To add 32bit or 64bit array values:
+ *       setenv fdtedit0 <node_path>%<bit_value>?<num_values>?<property_name>%<value1>?<value2>?<value3>?..
+ *       <bit_value> can be 32 / 64;  <num_values> is number of array elements
+ *       to be patched; <property_name> is the actual name of the property to
+ *       be patched; each array value has to be separated by '?'
+ *       for reg = <addr> <size>; <num_values> is 2 in this case
+ *    example:
+ *       setenv fdtedit0 /soc/dbm@0x8AF8000/%32?2?reg%0x8AF8000?0x500
+ *       setenv fdtedit1 /soc/pci@20000000/%32?2?bus-range%0xee?0xee
+ *       setenv fdtedit2 /soc/usb3@8A00000/%32?4?reg%0x8AF8600?0x200?0x8A00000?0xcb00
+ *       setenv fdtedit3 /reserved-memory/tzapp@49B00000/%64?2?reg%0x49A00000?0x500000
+ */
 void parse_fdt_fixup(char* buf, void *blob)
 {
-	int nodeoff, value, ret;
-	char *node, *property, *node_value;
-	bool str = true;
+	int nodeoff, value, ret, num_values, i;
+	char *node, *property, *node_value, *sliced_string;
+	bool if_string = true, bit32 = true;
+	u32 *values32;
+	u64 *values64;
 
+	/* env is split into <node>%<property>%<node_value>. '%' is separator */
 	node = strsep(&buf, "%");
 	property = strsep(&buf, "%");
 	node_value = strsep(&buf, "%");
 
-	debug("node: %s, property: %s, node_value: %s\n",
-			node, property, node_value);
+	debug("node: %s  property: %s  node_value: %s\n", node, property, node_value);
 
+	/* if '?' is present then node_value is string;
+	 * else, node_value is 32bit value
+	 */
 	if (node_value && node_value[0] != '?') {
-		str = false;
+		if_string = false;
 		value = simple_strtoul(node_value, NULL, 10);
 	} else {
+		/* skip '?' */
 		node_value++;
 	}
 
 	nodeoff = fdt_path_offset(blob, node);
 	if (nodeoff < 0) {
-		printf("%s: unable to find node '%s'\n",
-				__func__, node);
+		printf("%s: unable to find node '%s'\n", __func__, node);
 		return;
 	}
 
 	if (!strncmp(property, "delete", strlen("delete"))) {
+		/* handle property deletes */
 		ret = fdt_delprop(blob, nodeoff, node_value);
 		if (ret) {
-			printf("%s: unable to delete %s\n",
-					__func__, node_value);
+			printf("%s: unable to delete %s\n", __func__, node_value);
 			return;
 		}
-	} else if (!str) {
-		ret = fdt_setprop_u32(blob, nodeoff, property,
-				value);
+	} else if (!strncmp(property, "32", strlen("32")) || !strncmp(property, "64", strlen("64"))) {
+		/* if property name starts with '32' or '64', then it is used
+		 * for patching array of 32bit / 64bit values correspondingly.
+		 * 32bit patching is usually used to patch reg = <addr> <size>;
+		 * but could also be used to patch multiple addresses & sizes
+		 * <property> = <addr1> <size1> <addr2> <size2> ..
+		 * 64bit patching is usually used to patch reserved memory nodes
+		 */
+		sliced_string = strsep(&property, "?");
+		if (simple_strtoul(sliced_string, NULL, 10) == 64)
+			bit32 = false;
+
+		/* get the number of array values */
+		sliced_string = strsep(&property, "?");
+		num_values = simple_strtoul(sliced_string, NULL, 10);
+
+		if (bit32 == true) {
+			values32 = malloc(num_values * sizeof(u32));
+
+			for (i = 0; i < num_values; i++)  {
+				sliced_string = strsep(&node_value, "?");
+				values32[i] =  cpu_to_fdt32(simple_strtoul(sliced_string, NULL, 10));
+			}
+
+			ret = fdt_setprop(blob, nodeoff, property, values32, num_values * sizeof(u32));
+			if (ret) {
+				printf("%s: failed to set prop %s\n", __func__, property);
+				return;
+			}
+		} else {
+			values64 = malloc(num_values * sizeof(u64));
+
+			for (i = 0; i < num_values; i++)  {
+				sliced_string = strsep(&node_value, "?");
+				values64[i] =  cpu_to_fdt64(simple_strtoul(sliced_string, NULL, 10));
+			}
+
+			ret = fdt_setprop(blob, nodeoff, property, values64, num_values * sizeof(u64));
+			if (ret) {
+				printf("%s: failed to set prop %s\n", __func__, property);
+				return;
+			}
+		}
+	} else if (!if_string) {
+		/* handle 32bit integer value patching */
+		ret = fdt_setprop_u32(blob, nodeoff, property, value);
 		if (ret) {
-			printf("%s: failed to set prop %s\n",
-					__func__, property);
+			printf("%s: failed to set prop %s\n", __func__, property);
 			return;
 		}
 	} else {
+		/* handle string value patching
+		 * usually used to patch status = "ok"; status = "disabled";
+		 */
 		ret = fdt_setprop(blob, nodeoff, property,
 				node_value,
 				(strlen(node_value) + 1));
 		if (ret) {
-			printf("%s: failed to set prop %s\n",
-					__func__, property);
+			printf("%s: failed to set prop %s\n", __func__, property);
 			return;
 		}
 	}
 }
 
+/* check parse_fdt_fixup for detailed explanation */
 void ipq_fdt_fixup(void *blob)
 {
 	int i, fdteditnum;
@@ -593,11 +845,6 @@
 	return;
 }
 
-__weak void fdt_fixup_set_dload_dis(void *blob)
-{
-	return;
-}
-
 __weak void fdt_fixup_set_dload_warm_reset(void *blob)
 {
 	return;
@@ -618,6 +865,62 @@
 	return;
 }
 
+__weak void fdt_fixup_art_format(void *blob)
+{
+	return;
+}
+
+#ifdef CONFIG_IPQ_BT_SUPPORT
+__weak void fdt_fixup_bt_running(void *blob)
+{
+	return;
+}
+#endif
+
+__weak void fdt_fixup_bt_debug(void *blob)
+{
+	return;
+}
+
+__weak void fdt_fixup_qpic(void *blob)
+{
+	return;
+}
+
+void set_mtdids(void)
+{
+	char mtdids[256];
+
+	if (getenv("mtdids") != NULL) {
+		/* mtdids env is already set, nothing to do */
+		return;
+	}
+
+	qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
+	if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) {
+		if (get_which_flash_param("rootfs") ||
+		    ((sfi->flash_secondary_type == SMEM_BOOT_NAND_FLASH) ||
+			(sfi->flash_secondary_type == SMEM_BOOT_QSPI_NAND_FLASH))) {
+
+			snprintf(mtdids, sizeof(mtdids),
+				 "nand%d=nand%d,nand%d=" QCA_SPI_NOR_DEVICE,
+				 is_spi_nand_available(),
+				 is_spi_nand_available(),
+				 CONFIG_SPI_FLASH_INFO_IDX);
+		} else {
+
+			snprintf(mtdids, sizeof(mtdids), "nand%d="
+				QCA_SPI_NOR_DEVICE, CONFIG_SPI_FLASH_INFO_IDX);
+
+		}
+		setenv("mtdids", mtdids);
+	} else if (((sfi->flash_type == SMEM_BOOT_NAND_FLASH) ||
+			(sfi->flash_type == SMEM_BOOT_QSPI_NAND_FLASH))) {
+
+		snprintf(mtdids, sizeof(mtdids), "nand0=nand0");
+		setenv("mtdids", mtdids);
+	}
+}
 
 void fdt_fixup_read_qfprom(void *blob)
 {
@@ -800,21 +1103,30 @@
 	uint32_t flash_type;
 	char *s;
 	char *mtdparts = NULL;
+	char *addparts = NULL;
 	char parts_str[4096];
 	int len = sizeof(parts_str), ret;
 	qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
 	int activepart = 0;
+#ifdef CONFIG_IPQ_TINY
+	struct flash_node_info nodes[] = {
+		{ "n25q128a11", MTD_DEV_TYPE_NAND,
+				CONFIG_IPQ_SPI_NOR_INFO_IDX }
+		};
+#else
 	struct flash_node_info nodes[] = {
 		{ "qcom,msm-nand", MTD_DEV_TYPE_NAND, 0 },
 		{ "qcom,qcom_nand", MTD_DEV_TYPE_NAND, 0 },
 		{ "qcom,ebi2-nandc-bam-v1.5.0", MTD_DEV_TYPE_NAND, 0 },
 		{ "qcom,ebi2-nandc-bam-v2.1.1", MTD_DEV_TYPE_NAND, 0 },
+		{ "qcom,ipq8074-nand", MTD_DEV_TYPE_NAND, 0 },
 		{ "spinand,mt29f", MTD_DEV_TYPE_NAND, 1 },
 		{ "n25q128a11", MTD_DEV_TYPE_NAND,
 				CONFIG_IPQ_SPI_NOR_INFO_IDX },
 		{ "s25fl256s1", MTD_DEV_TYPE_NAND, 1 },
 		{ NULL, 0, -1 },	/* Terminator */
 	};
+#endif
 
 	/* force memory to 256MB if boardID is 002007 */
 	struct custdata cd;
@@ -867,12 +1179,23 @@
 	if (mtdparts) {
 		qca_smem_part_to_mtdparts(mtdparts,len);
 		if (mtdparts[0] != '\0') {
+			addparts = getenv("addmtdparts");
+			if (addparts) {
+				debug("addmtdparts = %s\n", addparts);
+				strlcat(mtdparts, ",", sizeof(parts_str));
+				strlcat(mtdparts, addparts, sizeof(parts_str));
+			}
 			debug("mtdparts = %s\n", mtdparts);
 			setenv("mtdparts", mtdparts);
 		}
 
+		set_mtdids();
 		debug("MTDIDS: %s\n", getenv("mtdids"));
+#ifdef CONFIG_IPQ_TINY
+		ipq_nor_fdt_fixup(blob, nodes);
+#else
 		ipq_fdt_fixup_mtdparts(blob, nodes);
+#endif
 	}
 
 	/* Add "flash_type" to root node of the devicetree*/
@@ -902,6 +1225,7 @@
 	fdt_fixup_cpr(blob);
 	fdt_fixup_cpus_node(blob);
 	fdt_low_memory_fixup(blob);
+	fdt_fixup_qpic(blob);
 
 	fdt_fixup_read_qfprom(blob);
 	fdt_fixup_add_signatures(blob);
@@ -913,7 +1237,7 @@
 		fdt_fixup_set_dload_warm_reset(blob);
 	s = getenv("dload_dis");
 	if (s)
-		fdt_fixup_set_dload_dis(blob);
+		ipq_fdt_mem_rsvd_fixup(blob);
 	s = getenv("qce_fixed_key");
 	if (s)
 		fdt_fixup_set_qce_fixed_key(blob);
@@ -922,6 +1246,19 @@
 		fdt_fixup_set_qca_cold_reboot_enable(blob);
 		fdt_fixup_wcss_rproc_for_atf(blob);
 	}
+	s = getenv("bt_debug");
+	if (s) {
+		fdt_fixup_bt_debug(blob);
+	}
+
+#ifdef CONFIG_IPQ_BT_SUPPORT
+	fdt_fixup_bt_running(blob);
+#endif
+	/*
+	|| This features fixup compressed_art in
+	|| dts if its 16M profile build.
+	*/
+	fdt_fixup_art_format(blob);
 
 #ifdef CONFIG_QCA_MMC
 	board_mmc_deinit();
diff --git a/board/qca/arm/ipq40xx/ipq40xx.c b/board/qca/arm/ipq40xx/ipq40xx.c
index 247aef2..61bd3ee 100644
--- a/board/qca/arm/ipq40xx/ipq40xx.c
+++ b/board/qca/arm/ipq40xx/ipq40xx.c
@@ -37,6 +37,9 @@
 
 #define DLOAD_MAGIC_COOKIE 0x10
 #define TCSR_USB_HSPHY_DEVICE_MODE		0x00C700E7
+
+#define TCSR_SOC_HW_VERSION_REG 0x194D000
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #define CPU0_APCS_SAW2_VCTL	0x0b089014
@@ -788,3 +791,7 @@
 	return;
 }
 
+int get_soc_hw_version(void)
+{
+	return readl(TCSR_SOC_HW_VERSION_REG);
+}
diff --git a/board/qca/arm/ipq5018/Makefile b/board/qca/arm/ipq5018/Makefile
new file mode 100644
index 0000000..ea342f2
--- /dev/null
+++ b/board/qca/arm/ipq5018/Makefile
@@ -0,0 +1,6 @@
+ccflags-y += -I$(srctree)/board/qca/arm/ipq5018
+cppflags-y += -I$(srctree)/board/qca/arm/ipq5018
+obj-y   := ipq5018.o
+obj-y   += clock.o
+obj-$(CONFIG_IPQ_BT_SUPPORT) += bt_ipc.o
+
diff --git a/board/qca/arm/ipq5018/bt.h b/board/qca/arm/ipq5018/bt.h
new file mode 100644
index 0000000..bb54444
--- /dev/null
+++ b/board/qca/arm/ipq5018/bt.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _BT_H
+#define _BT_H
+
+#include <asm/atomic.h>
+
+#define	PAS_ID	0xC
+#define	CMD_ID	0x14
+#define BT_M0_WARM_RST_ORIDE	0x0
+#define BT_M0_WARM_RST		0x4
+
+#define IOCTL_IPC_BOOT		0xBE
+#define IPC_TX_QSIZE		0x20
+
+#define	TO_APPS_ADDR(a)		(btmem->virt + (int)(uintptr_t)a)
+#define	TO_BT_ADDR(a)		(a - btmem->virt)
+#define IPC_LBUF_SZ(w, x, y, z)	(((TO_BT_ADDR((void *)w) + w->x) - w->y) / w->z)
+
+#define IPC_MSG_HDR_SZ		(4u)
+#define IPC_MSG_PLD_SZ		(40u)
+#define IPC_TOTAL_MSG_SZ	(IPC_MSG_HDR_SZ + IPC_MSG_PLD_SZ)
+
+#define IPC_LMSG_MASK		(0x8000u)
+#define IPC_RACK_MASK		(0x4000u)
+#define IPC_PKT_TYPE_MASK	(0x0300u)
+#define IPC_MSG_ID_MASK		(0x00FFu)
+
+#define IPC_LMSG_TYPE		((uint16_t) IPC_LMSG_MASK)
+#define IPC_SMSG_TYPE		((uint16_t) 0x0000u)
+#define IPC_REQ_ACK		((uint16_t) IPC_RACK_MASK)
+#define IPC_NO_ACK		((uint16_t) 0x0000u)
+#define IPC_PKT_TYPE_CUST	((uint16_t) 0x0000u)
+#define IPC_PKT_TYPE_HCI	((uint16_t) 0x0100u)
+#define IPC_PKT_TYPE_AUDIO	((uint16_t) 0x0200u)
+#define IPC_PKT_TYPE_RFU	(IPC_PKT_TYPE_MASK)
+
+#define IPC_LMSG_SHIFT		(15u)
+#define IPC_RACK_SHIFT		(14u)
+#define IPC_PKT_TYPE_SHIFT	(8u)
+
+#define	GET_NO_OF_BLOCKS(a, b) ((a + b - 1) / b)
+
+#define GET_RX_INDEX_FROM_BUF(x, y)	((x - btmem->rx_ctxt->lring_buf) / y)
+
+#define GET_TX_INDEX_FROM_BUF(x, y)	((x - btmem->tx_ctxt->lring_buf) / y)
+
+#define IS_RX_MEM_NON_CONTIGIOUS(pBuf, len, sz)		\
+	((pBuf + len) >			\
+	(btmem->rx_ctxt->lring_buf +	\
+	(sz * btmem->rx_ctxt->lmsg_buf_cnt)))
+
+/** Message header format.
+ *
+ *         ---------------------------------------------------------------
+ * BitPos |    15    | 14 | 13 | 12 | 11 | 10 |  9  |  8  |    7 - 0     |
+ *         ---------------------------------------------------------------
+ * Field  | Long Msg |rAck|        RFU        |  PktType  |    msgID     |
+ *         ---------------------------------------------------------------
+ *
+ * - Long Msg   :
+ *
+ * - reqAck     : This is interpreted by receiver for sending acknowledegement
+ *                to sender i.e. send a ack IPC interrupt if set.
+ *                Use @ref IS_REQ_ACK or @ref IS_NO_ACK
+ *                to determine ack is requested or not.
+ *
+ * - RFU        : Reserved for future use.
+ *
+ * - pktType    :
+ *
+ * - msgID      : Contains unique message ID within a Category.
+ *                Use @ref IPC_GET_MSG_ID to get message ID.
+ */
+#define IPC_ConstructMsgHeader(msgID, reqAck, pktType, longMsg)	\
+	(((uint8_t) longMsg << IPC_LMSG_SHIFT) |		\
+	((uint8_t) reqAck << IPC_RACK_SHIFT) |			\
+	((uint16_t) pktType << IPC_PKT_TYPE_SHIFT) | msgID)
+
+#define IPC_GET_PKT_TYPE(hdr)	\
+	((enum ipc_pkt_type)((hdr & IPC_PKT_TYPE_MASK) >> IPC_PKT_TYPE_SHIFT))
+
+#define IS_LONG_MSG(hdr)	((hdr & IPC_LMSG_MASK) == IPC_LMSG_TYPE)
+#define IS_SHORT_MSG(hdr)	((hdr & IPC_LMSG_MASK) == IPC_SMSG_TYPE)
+
+#define IS_REQ_ACK(hdr)		((hdr & IPC_RACK_MASK) == IPC_REQ_ACK)
+#define IS_NO_ACK(hdr)		((hdr & IPC_RACK_MASK) == IPC_NO_ACK)
+
+#define IS_HCI_PKT(hdr)		((hdr & IPC_PKT_TYPE_MASK) == IPC_PKT_TYPE_HCI)
+#define IS_CUST_PKT(hdr)	((hdr & IPC_PKT_TYPE_MASK) == IPC_PKT_TYPE_CUST)
+
+#define IPC_GET_MSG_ID(hdr)	((uint8_t)(hdr & IPC_MSG_ID_MASK))
+
+#define IPC_CMD_IPC_STOP	(0x01)
+#define IPC_CMD_SWITCH_TO_UART	(0x02)
+#define IPC_CMD_PREPARE_DUMP	(0x03)
+#define IPC_CMD_COLLECT_DUMP	(0x04)
+#define IPC_CMD_IPC_START	(0x05)
+
+#define BT_RAM_START 0x7000000
+#define BT_RAM_PATCH 0x7020250
+#define BT_RAM_SIZE 0x58000
+#define SYSCON 0x0B111000
+
+/*-------------------------------------------------------------------------
+ * Type Declarations
+ * ------------------------------------------------------------------------
+ */
+
+enum ipc_pkt_type {
+	IPC_CUST_PKT,
+	IPC_HCI_PKT,
+	IPC_AUDIO_PKT,
+	IPC_PKT_MAX
+};
+
+struct long_msg_info {
+	uint16_t smsg_free_cnt;
+	uint16_t lmsg_free_cnt;
+	uint8_t ridx;
+	uint8_t widx;
+};
+
+struct ipc_aux_ptr {
+	uint32_t len;
+	uint32_t buf;
+};
+
+struct ring_buffer {
+	uint16_t msg_hdr;
+	uint16_t len;
+
+	union {
+		uint8_t  smsg_data[IPC_MSG_PLD_SZ];
+		uint32_t  lmsg_data;
+	} payload;
+};
+
+struct ring_buffer_info {
+	uint32_t rbuf;
+	uint8_t ring_buf_cnt;
+	uint8_t ridx;
+	uint8_t widx;
+	uint8_t tidx;
+	uint32_t next;
+};
+
+struct context_info {
+	uint16_t TotalMemorySize;
+	uint8_t lmsg_buf_cnt;
+	uint8_t smsg_buf_cnt;
+	struct ring_buffer_info sring_buf_info;
+	uint32_t sring_buf;
+	uint32_t lring_buf;
+	uint32_t reserved;
+};
+
+
+struct bt_mem {
+	phys_addr_t phys;
+	phys_addr_t reloc;
+	void __iomem *virt;
+	size_t size;
+	struct context_info *tx_ctxt;
+	struct context_info *rx_ctxt;
+	struct long_msg_info lmsg_ctxt;
+};
+
+struct bt_ipc {
+	uint32_t regmap;
+	int offset;
+	int bit;
+	int irq;
+	atomic_t tx_q_cnt;
+};
+
+struct bt_descriptor {
+	void __iomem *warm_reset;
+	struct bt_ipc ipc;
+	struct bt_mem btmem;
+	int (*sendmsg_cb)(struct bt_descriptor *, unsigned char *, int);
+	void (*recvmsg_cb)(struct bt_descriptor *, unsigned char *, int);
+	atomic_t state;
+	atomic_t tx_in_progress;
+	unsigned char *buf;
+	uint32_t len;
+};
+
+struct ipc_intent {
+	uint8_t *buf;
+	uint16_t len;
+};
+
+extern int bt_ipc_sendmsg(struct bt_descriptor *btDesc, unsigned char *buf, int len );
+extern void bt_ipc_init(struct bt_descriptor *btDesc);
+extern void bt_ipc_worker(struct bt_descriptor *btDesc);
+extern int bt_running;
+#endif /* _BT_H */
diff --git a/board/qca/arm/ipq5018/bt_ipc.c b/board/qca/arm/ipq5018/bt_ipc.c
new file mode 100644
index 0000000..18caf82
--- /dev/null
+++ b/board/qca/arm/ipq5018/bt_ipc.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <asm/atomic.h>
+#include <asm-generic/atomic-long.h>
+
+#include <linux/ctype.h>
+#include "bt.h"
+
+#include <common.h>
+#include <memalign.h>
+
+#include <linux/err.h>
+
+static void *bt_ipc_alloc_lmsg(struct bt_descriptor *btDesc, uint32_t len,
+		struct ipc_aux_ptr *aux_ptr, uint8_t *is_lbuf_full)
+{
+	uint8_t idx;
+	uint8_t blks;
+	uint8_t blks_consumed;
+	struct bt_mem *btmem = &btDesc->btmem;
+	uint32_t lsz = IPC_LBUF_SZ(btmem->tx_ctxt, TotalMemorySize, lring_buf,
+				   lmsg_buf_cnt);
+
+	if (btmem->tx_ctxt->lring_buf == 0) {
+		printf("no long message buffer not initialized\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	blks = GET_NO_OF_BLOCKS(len, lsz);
+
+	if (!btmem->lmsg_ctxt.lmsg_free_cnt ||
+			(blks > btmem->lmsg_ctxt.lmsg_free_cnt))
+		return ERR_PTR(-EAGAIN);
+
+	idx = btmem->lmsg_ctxt.widx;
+
+	if ((btmem->lmsg_ctxt.widx + blks) > btmem->tx_ctxt->lmsg_buf_cnt) {
+		blks_consumed = btmem->tx_ctxt->lmsg_buf_cnt - idx;
+		aux_ptr->len = len - (blks_consumed * lsz);
+		aux_ptr->buf = btmem->tx_ctxt->lring_buf;
+	}
+
+	btmem->lmsg_ctxt.widx = (btmem->lmsg_ctxt.widx + blks) %
+		btmem->tx_ctxt->lmsg_buf_cnt;
+
+	btmem->lmsg_ctxt.lmsg_free_cnt -= blks;
+
+	if (btmem->lmsg_ctxt.lmsg_free_cnt <=
+			((btmem->tx_ctxt->lmsg_buf_cnt * 20) / 100))
+		*is_lbuf_full = 1;
+
+	return (TO_APPS_ADDR(btmem->tx_ctxt->lring_buf) + (idx * lsz));
+}
+
+static struct ring_buffer_info *bt_ipc_get_tx_rbuf(struct bt_descriptor *btDesc,
+		uint8_t *is_sbuf_full)
+{
+	uint8_t idx;
+	struct ring_buffer_info *rinfo;
+	struct bt_mem *btmem = &btDesc->btmem;
+
+	for (rinfo = &(btmem->tx_ctxt->sring_buf_info);	rinfo != NULL;
+		rinfo = (struct ring_buffer_info *)(uintptr_t)(rinfo->next)) {
+		idx = (rinfo->widx + 1) % (btmem->tx_ctxt->smsg_buf_cnt);
+
+		if (idx != rinfo->tidx) {
+			btmem->lmsg_ctxt.smsg_free_cnt--;
+
+			if (btmem->lmsg_ctxt.smsg_free_cnt <=
+				((btmem->tx_ctxt->smsg_buf_cnt * 20) / 100))
+				*is_sbuf_full = 1;
+
+			return rinfo;
+		}
+	}
+
+	return ERR_PTR(-EAGAIN);
+}
+
+int bt_ipc_send_msg(struct bt_descriptor *btDesc, uint16_t msg_hdr,
+		const uint8_t *pData, uint16_t len, bool dequeue)
+{
+	int ret = 0;
+	struct bt_mem *btmem = &btDesc->btmem;
+	struct ring_buffer_info *rinfo;
+	struct ring_buffer *rbuf;
+	uint8_t is_lbuf_full = 0;
+	uint8_t is_sbuf_full = 0;
+	struct ipc_aux_ptr aux_ptr;
+	void *lmsg_data;
+
+	rinfo = bt_ipc_get_tx_rbuf(btDesc, &is_sbuf_full);
+	if (IS_ERR(rinfo)) {
+		printf("short msg buf full, queuing msg[%d]\n",
+				atomic_read(&btDesc->ipc.tx_q_cnt));
+		ret = PTR_ERR(rinfo);
+		return ret;
+	}
+
+	rbuf = &((struct ring_buffer *)(TO_APPS_ADDR(
+						rinfo->rbuf)))[rinfo->widx];
+	rbuf->msg_hdr = msg_hdr;
+	rbuf->len = len;
+
+	if (len > IPC_MSG_PLD_SZ) {
+		rbuf->msg_hdr = rbuf->msg_hdr | IPC_LMSG_MASK;
+
+		aux_ptr.len = 0;
+		aux_ptr.buf = 0;
+
+		lmsg_data = bt_ipc_alloc_lmsg(btDesc, len,
+				&aux_ptr, &is_lbuf_full);
+
+		if (IS_ERR(lmsg_data)) {
+			printf("long msg buf full, queuing msg[%d]\n",
+					atomic_read(&btDesc->ipc.tx_q_cnt));
+			ret = PTR_ERR(lmsg_data);
+			return ret;
+		}
+
+		memcpy_toio(lmsg_data, pData,
+				(len - aux_ptr.len));
+
+		if (aux_ptr.buf) {
+			memcpy_toio(TO_APPS_ADDR(aux_ptr.buf),
+				(pData + (len - aux_ptr.len)), aux_ptr.len);
+		}
+
+		rbuf->payload.lmsg_data = TO_BT_ADDR(lmsg_data);
+	} else {
+		memcpy_toio(rbuf->payload.smsg_data, pData, len);
+	}
+
+	if (is_sbuf_full || is_lbuf_full)
+		rbuf->msg_hdr = rbuf->msg_hdr | IPC_RACK_MASK;
+
+	rinfo->widx = (rinfo->widx + 1) % btmem->tx_ctxt->smsg_buf_cnt;
+
+	writel( BIT(btDesc->ipc.bit), btDesc->ipc.regmap+ btDesc->ipc.offset);
+
+	return ret;
+}
+
+static
+void bt_ipc_free_lmsg(struct bt_descriptor *btDesc, uint32_t lmsg, uint16_t len)
+{
+	uint8_t idx;
+	uint8_t blks;
+	struct bt_mem *btmem = &btDesc->btmem;
+	uint32_t lsz = IPC_LBUF_SZ(btmem->tx_ctxt, TotalMemorySize, lring_buf,
+				   lmsg_buf_cnt);
+
+	idx = GET_TX_INDEX_FROM_BUF(lmsg, lsz);
+
+	if (idx != btmem->lmsg_ctxt.ridx)
+		return;
+
+	blks = GET_NO_OF_BLOCKS(len, lsz);
+
+	btmem->lmsg_ctxt.ridx  = (btmem->lmsg_ctxt.ridx  + blks) %
+		btmem->tx_ctxt->lmsg_buf_cnt;
+
+	btmem->lmsg_ctxt.lmsg_free_cnt += blks;
+}
+
+static void bt_ipc_cust_msg(struct bt_descriptor *btDesc, uint8_t msgid)
+{
+	struct bt_mem *btmem = &btDesc->btmem;
+	uint16_t msg_hdr = 0;
+	int ret;
+
+	msg_hdr |= msgid;
+
+	switch (msgid) {
+	case IPC_CMD_IPC_STOP:
+		printf("BT IPC Stopped, gracefully stopping APSS IPC\n");
+		break;
+	case IPC_CMD_SWITCH_TO_UART:
+		printf("Configured UART, Swithing BT to debug mode\n");
+		break;
+	case IPC_CMD_PREPARE_DUMP:
+		printf("IPQ crashed, inform BT to prepare dump\n");
+		break;
+	case IPC_CMD_COLLECT_DUMP:
+		printf("BT Crashed, gracefully stopping IPC\n");
+		return;
+	case IPC_CMD_IPC_START:
+		btmem->tx_ctxt = (struct context_info *)((void *)
+			btmem->rx_ctxt + btmem->rx_ctxt->TotalMemorySize);
+		btmem->lmsg_ctxt.widx = 0;
+		btmem->lmsg_ctxt.ridx = 0;
+		btmem->lmsg_ctxt.smsg_free_cnt = btmem->tx_ctxt->smsg_buf_cnt;
+		btmem->lmsg_ctxt.lmsg_free_cnt = btmem->tx_ctxt->lmsg_buf_cnt;
+		atomic_set(&btDesc->state, 1);
+
+		printf("BT IPC Started, starting APSS IPC\n");
+		return;
+	default:
+		printf("invalid custom message\n");
+		return;
+	}
+
+	if (unlikely(!atomic_read(&btDesc->state))) {
+		printf("BT IPC not initialized, no message sent\n");
+		return;
+	}
+
+	atomic_set(&btDesc->state, 0);
+
+	ret = bt_ipc_send_msg(btDesc, msg_hdr, NULL, 0, true);
+	if (ret)
+		printf("err: sending message\n");
+}
+
+static bool bt_ipc_process_peer_msgs(struct bt_descriptor *btDesc,
+		struct ring_buffer_info *rinfo, uint8_t *pRxMsgCount)
+{
+	struct bt_mem *btmem = &btDesc->btmem;
+	struct ring_buffer *rbuf;
+	uint8_t ridx, lbuf_idx;
+	uint8_t blks_consumed;
+	struct ipc_aux_ptr aux_ptr;
+	enum ipc_pkt_type pktType = IPC_CUST_PKT;
+	bool ackReqd = false;
+	uint8_t *rxbuf = NULL;
+	uint32_t lsz = IPC_LBUF_SZ(btmem->rx_ctxt, TotalMemorySize, lring_buf,
+				   lmsg_buf_cnt);
+
+	ridx = rinfo->ridx;
+
+	rbuf = &((struct ring_buffer *)(TO_APPS_ADDR(
+			btmem->rx_ctxt->sring_buf_info.rbuf)))[ridx];
+
+	while (ridx != rinfo->widx) {
+		memset(&aux_ptr, 0, sizeof(struct ipc_aux_ptr));
+
+		rbuf = &((struct ring_buffer *)(TO_APPS_ADDR(
+				btmem->rx_ctxt->sring_buf_info.rbuf)))[ridx];
+
+		if (IS_LONG_MSG(rbuf->msg_hdr)) {
+			rxbuf = TO_APPS_ADDR(rbuf->payload.lmsg_data);
+
+			if (IS_RX_MEM_NON_CONTIGIOUS(rbuf->payload.lmsg_data,
+							rbuf->len, lsz)) {
+
+				lbuf_idx = GET_RX_INDEX_FROM_BUF(
+						rbuf->payload.lmsg_data, lsz);
+
+				blks_consumed = btmem->rx_ctxt->lmsg_buf_cnt -
+					lbuf_idx;
+				aux_ptr.len = rbuf->len - (blks_consumed * lsz);
+				aux_ptr.buf = btmem->rx_ctxt->lring_buf;
+			}
+		} else {
+			rxbuf = rbuf->payload.smsg_data;
+		}
+
+		if (IS_REQ_ACK(rbuf->msg_hdr))
+			ackReqd = true;
+
+		pktType = IPC_GET_PKT_TYPE(rbuf->msg_hdr);
+
+		switch (pktType) {
+		case IPC_HCI_PKT:
+			btDesc->buf = kzalloc(rbuf->len, GFP_ATOMIC);
+			if (!btDesc->buf)
+				return -ENOMEM;
+
+			memcpy_fromio(btDesc->buf, rxbuf, (rbuf->len - aux_ptr.len));
+
+			if (aux_ptr.buf)
+				memcpy_fromio(btDesc->buf + (rbuf->len - aux_ptr.len),
+					TO_APPS_ADDR(aux_ptr.buf), aux_ptr.len);
+
+			btDesc->len = rbuf->len;
+			atomic_set(&btDesc->tx_in_progress, 0);
+			break;
+		case IPC_CUST_PKT:
+			bt_ipc_cust_msg(btDesc, IPC_GET_MSG_ID(rbuf->msg_hdr));
+			break;
+		case IPC_AUDIO_PKT:
+			break;
+		default:
+			break;
+		}
+
+		ridx = (ridx + 1) % rinfo->ring_buf_cnt;
+	}
+
+	rinfo->ridx = ridx;
+
+	return ackReqd;
+}
+
+static void bt_ipc_process_ack(struct bt_descriptor *btDesc)
+{
+	struct ring_buffer_info *rinfo;
+	struct bt_mem *btmem = &btDesc->btmem;
+
+	for (rinfo = &btmem->tx_ctxt->sring_buf_info; rinfo != NULL;
+		rinfo = (struct ring_buffer_info *)(uintptr_t)(rinfo->next)) {
+		uint8_t tidx = rinfo->tidx;
+		struct ring_buffer *rbuf = (struct ring_buffer *)
+			TO_APPS_ADDR(rinfo->rbuf);
+
+		while (tidx != rinfo->ridx) {
+			if (IS_LONG_MSG(rbuf[tidx].msg_hdr)) {
+				bt_ipc_free_lmsg(btDesc,
+						 rbuf[tidx].payload.lmsg_data,
+						 rbuf[tidx].len);
+			}
+
+			tidx = (tidx + 1) % btmem->tx_ctxt->smsg_buf_cnt;
+			btmem->lmsg_ctxt.smsg_free_cnt++;
+		}
+
+		rinfo->tidx = tidx;
+	}
+}
+
+int bt_ipc_sendmsg(struct bt_descriptor *btDesc, unsigned char *buf, int len)
+{
+	int ret;
+	uint16_t msg_hdr = 0x100;
+
+	if (unlikely(!atomic_read(&btDesc->state))) {
+		printf("BT IPC not initialized, no message sent\n");
+		return -ENODEV;
+	}
+
+	atomic_set(&btDesc->tx_in_progress, 1);
+	ret = bt_ipc_send_msg(btDesc, msg_hdr, (uint8_t *)buf, (uint16_t)len,
+				true);
+	if (ret)
+		printf("err: sending message\n");
+
+	return ret;
+}
+
+void bt_ipc_worker(struct bt_descriptor *btDesc)
+{
+	struct ring_buffer_info *rinfo;
+
+	struct bt_mem *btmem = &btDesc->btmem;
+	bool ackReqd = false;
+
+	if (unlikely(!atomic_read(&btDesc->state))) {
+		btmem->rx_ctxt = (struct context_info *)(btmem->virt + 0xe000);
+		if (btmem->rx_ctxt->sring_buf_info.widx != 0x1)
+			return;
+	}
+	else
+		bt_ipc_process_ack(btDesc);
+
+	for (rinfo = &(btmem->rx_ctxt->sring_buf_info); rinfo != NULL;
+		rinfo = (struct ring_buffer_info *)(uintptr_t)(rinfo->next)) {
+		if (bt_ipc_process_peer_msgs(btDesc, rinfo,
+					&btmem->rx_ctxt->smsg_buf_cnt)) {
+			ackReqd = true;
+		}
+	}
+
+	if (ackReqd) {
+		writel( BIT(btDesc->ipc.bit), btDesc->ipc.regmap+ btDesc->ipc.offset);
+	}
+
+}
+
+void  bt_ipc_init(struct bt_descriptor *btDesc)
+{
+	struct bt_mem *btmem;
+
+	btmem = &btDesc->btmem;
+	btmem->phys = BT_RAM_START;
+        btmem->reloc = BT_RAM_START;
+        btmem->size = BT_RAM_SIZE;
+        btmem->virt = (void __iomem *)BT_RAM_START;
+
+	btDesc->ipc.regmap = SYSCON;
+	btDesc->ipc.offset = 8;
+	btDesc->ipc.bit = 23;
+	atomic_set(&btDesc->state, 0);
+	atomic_set(&btDesc->tx_in_progress, 0);
+}
diff --git a/board/qca/arm/ipq5018/clock.c b/board/qca/arm/ipq5018/clock.c
new file mode 100644
index 0000000..247dc79
--- /dev/null
+++ b/board/qca/arm/ipq5018/clock.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015-2016, 2018-2019 The Linux Foundation. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <asm/arch-ipq5018/clk.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#ifdef CONFIG_IPQ5018_I2C
+void i2c_clock_config(void)
+{
+	int cfg;
+
+	/* Configure qup1_i2c_apps_clk_src */
+	cfg = (GCC_BLSP1_QUP3_I2C_APPS_CFG_RCGR_SRC_SEL |
+			GCC_BLSP1_QUP3_I2C_APPS_CFG_RCGR_SRC_DIV);
+	writel(cfg, GCC_BLSP1_QUP3_I2C_APPS_CFG_RCGR);
+
+	writel(CMD_UPDATE, GCC_BLSP1_QUP3_I2C_APPS_CMD_RCGR);
+	mdelay(100);
+	writel(ROOT_EN, GCC_BLSP1_QUP3_I2C_APPS_CMD_RCGR);
+
+	/* Configure CBCR */
+	writel(CLK_ENABLE, GCC_BLSP1_QUP3_I2C_APPS_CBCR);
+}
+#endif
+
+#ifdef CONFIG_IPQ_BT_SUPPORT
+void enable_btss_lpo_clk(void)
+{
+	writel(CLK_ENABLE, GCC_BTSS_LPO_CBCR);
+}
+#endif
diff --git a/board/qca/arm/ipq5018/ipq5018.c b/board/qca/arm/ipq5018/ipq5018.c
new file mode 100644
index 0000000..01b4d44
--- /dev/null
+++ b/board/qca/arm/ipq5018/ipq5018.c
@@ -0,0 +1,1987 @@
+/*
+* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <common.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <environment.h>
+#include <fdtdec.h>
+#include <asm/arch-qca-common/gpio.h>
+#include <asm/arch-qca-common/uart.h>
+#include <asm/arch-qca-common/scm.h>
+#include <asm/arch-qca-common/iomap.h>
+#include <ipq5018.h>
+#ifdef CONFIG_QCA_MMC
+#include <mmc.h>
+#include <sdhci.h>
+#endif
+#ifdef CONFIG_USB_XHCI_IPQ
+#include <usb.h>
+#endif
+#ifdef CONFIG_QPIC_NAND
+#include <asm/arch-qca-common/qpic_nand.h>
+#endif
+#ifdef CONFIG_IPQ_BT_SUPPORT
+#include <malloc.h>
+#include "bt.h"
+#include "bt_binary_array.h"
+#include <linux/compat.h>
+#endif
+
+#define DLOAD_MAGIC_COOKIE	0x10
+
+#define TCSR_SOC_HW_VERSION_REG 0x194D000
+
+ipq_gmac_board_cfg_t gmac_cfg[CONFIG_IPQ_NO_MACS];
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_QCA_MMC
+struct sdhci_host mmc_host;
+#endif
+
+#ifdef CONFIG_MTD_DEVICE
+extern int ipq_spi_init(u16);
+#endif
+
+extern void ppe_uniphy_set_forceMode(void);
+extern void ppe_uniphy_refclk_set(void);
+
+unsigned int qpic_frequency = 0, qpic_phase = 0;
+
+const char *rsvd_node = "/reserved-memory";
+const char *del_node[] = {"uboot",
+			  "sbl",
+			  NULL};
+const add_node_t add_fdt_node[] = {{}};
+
+struct dumpinfo_t dumpinfo_n[] = {
+	/* TZ stores the DDR physical address at which it stores the
+	 * APSS regs, UTCM copy dump. We will have the TZ IMEM
+	 * IMEM Addr at which the DDR physical address is stored as
+	 * the start
+	 *     --------------------
+         *     |  DDR phy (start) | ----> ------------------------
+         *     --------------------       | APSS regsave (8k)    |
+         *                                ------------------------
+         *                                |                      |
+	 *                                | 	 UTCM copy	 |
+         *                                |        (192k)        |
+	 *                                |                      |
+         *                                ------------------------
+	 *				  |			 |
+	 *				  |	BTRAM Copy	 |
+	 *				  |	  (352k)	 |
+	 *				  |			 |
+	 *				  ------------------------
+	 */
+	{ "EBICS0.BIN", 0x40000000, 0x10000000, 0 },
+	/*
+	 * The below 3 config enable compress crash dump support.
+	 * the RAM region will be split in 3 section and collect based on the
+	 * config as given below. NOT SUPPORT IN  TINY_NOR profile.
+	 * Note : EBICS2.BIN start and size varies dynamically based on RAM size.
+	 *  basically it's seconds half of ram region.
+	*/
+#ifndef CONFIG_IPQ_TINY
+	{ "EBICS2.BIN", 0x60000000, 0x20000000, 0, 0, 0, 0, 1 },
+	{ "EBICS1.BIN", CONFIG_UBOOT_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
+	{ "EBICS0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
+#endif
+	{ "IMEM.BIN", 0x08600000, 0x00001000, 0 },
+	{ "NSSUTCM.BIN", 0x08600658, 0x00030000, 0, 1, 0x2000 },
+	{ "BTRAM.BIN", 0x08600658, 0x00058000, 0, 1, 0x00032000 },
+	{ "UNAME.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
+	{ "CPU_INFO.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
+	{ "DMESG.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
+	{ "PT.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
+	{ "WLAN_MOD.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
+};
+int dump_entries_n = ARRAY_SIZE(dumpinfo_n);
+
+struct dumpinfo_t dumpinfo_s[] = {
+	{ "EBICS_S0.BIN", 0x40000000, 0xAC00000, 0 },
+	{ "EBICS_S1.BIN", CONFIG_TZ_END_ADDR, 0x10000000, 0 },
+#ifndef CONFIG_IPQ_TINY
+	{ "EBICS_S2.BIN", CONFIG_TZ_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
+	{ "EBICS_S1.BIN", CONFIG_UBOOT_END_ADDR, 0x200000, 0, 0, 0, 0, 1 },
+	{ "EBICS_S0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
+#endif
+	{ "IMEM.BIN", 0x08600000, 0x00001000, 0 },
+	{ "NSSUTCM.BIN", 0x08600658, 0x00030000, 0, 1, 0x2000 },
+	{ "BTRAM.BIN", 0x08600658, 0x00058000, 0, 1, 0x00032000 },
+	{ "UNAME.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
+	{ "CPU_INFO.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
+	{ "DMESG.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
+	{ "PT.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
+	{ "WLAN_MOD.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
+};
+int dump_entries_s = ARRAY_SIZE(dumpinfo_s);
+u32 *tz_wonce = (u32 *)CONFIG_IPQ5018_TZ_WONCE_4_ADDR;
+
+void uart1_configure_mux(void)
+{
+	unsigned long cfg_rcgr;
+
+	cfg_rcgr = readl(GCC_BLSP1_UART1_APPS_CFG_RCGR);
+	/* Clear mode, src sel, src div */
+	cfg_rcgr &= ~(GCC_UART_CFG_RCGR_MODE_MASK |
+			GCC_UART_CFG_RCGR_SRCSEL_MASK |
+			GCC_UART_CFG_RCGR_SRCDIV_MASK);
+
+	cfg_rcgr |= ((UART1_RCGR_SRC_SEL << GCC_UART_CFG_RCGR_SRCSEL_SHIFT)
+			& GCC_UART_CFG_RCGR_SRCSEL_MASK);
+
+	cfg_rcgr |= ((UART1_RCGR_SRC_DIV << GCC_UART_CFG_RCGR_SRCDIV_SHIFT)
+			& GCC_UART_CFG_RCGR_SRCDIV_MASK);
+
+	cfg_rcgr |= ((UART1_RCGR_MODE << GCC_UART_CFG_RCGR_MODE_SHIFT)
+			& GCC_UART_CFG_RCGR_MODE_MASK);
+
+	writel(cfg_rcgr, GCC_BLSP1_UART1_APPS_CFG_RCGR);
+}
+
+void uart1_set_rate_mnd(unsigned int m,
+		unsigned int n, unsigned int two_d)
+{
+	writel(m, GCC_BLSP1_UART1_APPS_M);
+	writel(n, GCC_BLSP1_UART1_APPS_N);
+	writel(two_d, GCC_BLSP1_UART1_APPS_D);
+}
+
+void reset_board(void)
+{
+	run_command("reset", 0);
+}
+
+void uart1_toggle_clock(void)
+{
+	unsigned long cbcr_val;
+
+	cbcr_val = readl(GCC_BLSP1_UART1_APPS_CBCR);
+	cbcr_val |= UART1_CBCR_CLK_ENABLE;
+	writel(cbcr_val, GCC_BLSP1_UART1_APPS_CBCR);
+}
+
+int uart1_trigger_update(void)
+{
+	unsigned long cmd_rcgr;
+	int timeout = 0;
+
+	cmd_rcgr = readl(GCC_BLSP1_UART1_APPS_CMD_RCGR);
+	cmd_rcgr |= UART1_CMD_RCGR_UPDATE | UART1_CMD_RCGR_ROOT_EN;
+	writel(cmd_rcgr, GCC_BLSP1_UART1_APPS_CMD_RCGR);
+
+	while (readl(GCC_BLSP1_UART1_APPS_CMD_RCGR) & UART1_CMD_RCGR_UPDATE) {
+		if (timeout++ >= CLOCK_UPDATE_TIMEOUT_US) {
+			printf("Timeout waiting for UART1 clock update\n");
+			return -ETIMEDOUT;
+			udelay(1);
+		}
+	}
+	uart1_toggle_clock();
+	return 0;
+}
+
+int uart1_clock_config(struct ipq_serial_platdata *plat)
+{
+
+	uart1_configure_mux();
+	uart1_set_rate_mnd(plat->m_value,
+		plat->n_value,
+		plat->d_value);
+	return uart1_trigger_update();
+}
+
+void qca_serial_init(struct ipq_serial_platdata *plat)
+{
+	int ret;
+
+	if (plat->gpio_node < 0) {
+		printf("serial_init: unable to find gpio node \n");
+		return;
+	}
+	qca_gpio_init(plat->gpio_node);
+	ret = uart1_clock_config(plat);
+	if (ret)
+		printf("UART clock config failed %d \n", ret);
+}
+
+/*
+ * Set the uuid in bootargs variable for mounting rootfilesystem
+ */
+#ifdef CONFIG_QCA_MMC
+int set_uuid_bootargs(char *boot_args, char *part_name, int buflen, bool gpt_flag)
+{
+	int ret, len;
+	block_dev_desc_t *blk_dev;
+	disk_partition_t disk_info;
+
+	blk_dev = mmc_get_dev(mmc_host.dev_num);
+	if (!blk_dev) {
+		printf("Invalid block device name\n");
+		return -EINVAL;
+	}
+
+	if (buflen <= 0 || buflen > MAX_BOOT_ARGS_SIZE)
+		return -EINVAL;
+
+#ifdef CONFIG_PARTITION_UUIDS
+	ret = get_partition_info_efi_by_name(blk_dev,
+			part_name, &disk_info);
+	if (ret) {
+		printf("bootipq: unsupported partition name %s\n",part_name);
+		return -EINVAL;
+	}
+	if ((len = strlcpy(boot_args, "root=PARTUUID=", buflen)) >= buflen)
+		return -EINVAL;
+#else
+	if ((len = strlcpy(boot_args, "rootfsname=", buflen)) >= buflen)
+		return -EINVAL;
+#endif
+	boot_args += len;
+	buflen -= len;
+
+#ifdef CONFIG_PARTITION_UUIDS
+	if ((len = strlcpy(boot_args, disk_info.uuid, buflen)) >= buflen)
+		return -EINVAL;
+#else
+	if ((len = strlcpy(boot_args, part_name, buflen)) >= buflen)
+		return -EINVAL;
+#endif
+	boot_args += len;
+	buflen -= len;
+
+	if (gpt_flag && strlcpy(boot_args, " gpt", buflen) >= buflen)
+		return -EINVAL;
+
+	return 0;
+}
+#else
+int set_uuid_bootargs(char *boot_args, char *part_name, int buflen, bool gpt_flag)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_QCA_MMC
+void emmc_clock_config(void)
+{
+	/* Enable root clock generator */
+	writel(readl(GCC_SDCC1_APPS_CBCR)|0x1, GCC_SDCC1_APPS_CBCR);
+	/* Add 10us delay for CLK_OFF to get cleared */
+	udelay(10);
+	writel(readl(GCC_SDCC1_AHB_CBCR)|0x1, GCC_SDCC1_AHB_CBCR);
+	/* PLL0 - 192Mhz */
+	writel(0x20B, GCC_SDCC1_APPS_CFG_RCGR);
+	/* Delay for clock operation complete */
+	udelay(10);
+	writel(0x1, GCC_SDCC1_APPS_M);
+	/* check this M, N D value while debugging
+	 * because as per clock tool the actual M, N, D
+	 * values are M=1, N=FA, D=F9
+	 */
+	writel(0xFC, GCC_SDCC1_APPS_N);
+	writel(0xFD, GCC_SDCC1_APPS_D);
+	/* Delay for clock operation complete */
+	udelay(10);
+	/* Update APPS_CMD_RCGR to reflect source selection */
+	writel(readl(GCC_SDCC1_APPS_CMD_RCGR)|0x1, GCC_SDCC1_APPS_CMD_RCGR);
+	/* Add 10us delay for clock update to complete */
+	udelay(10);
+}
+
+void mmc_iopad_config(struct sdhci_host *host)
+{
+	u32 val;
+	val = sdhci_readb(host, SDHCI_VENDOR_IOPAD);
+	/*set bit 15 & 16*/
+	val |= 0x18000;
+	writel(val, host->ioaddr + SDHCI_VENDOR_IOPAD);
+}
+
+void sdhci_bus_pwr_off(struct sdhci_host *host)
+{
+	u32 val;
+
+	val = sdhci_readb(host, SDHCI_HOST_CONTROL);
+	sdhci_writeb(host,(val & (~SDHCI_POWER_ON)), SDHCI_POWER_CONTROL);
+}
+
+__weak void board_mmc_deinit(void)
+{
+	/*since we do not have misc register in ipq5018
+	 * so simply return from this function
+	 */
+	return;
+}
+
+void emmc_clock_reset(void)
+{
+	writel(0x1, GCC_SDCC1_BCR);
+	udelay(10);
+	writel(0x0, GCC_SDCC1_BCR);
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	int node, gpio_node;
+	int ret = 0;
+	qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
+	node = fdt_path_offset(gd->fdt_blob, "mmc");
+	if (node < 0) {
+		printf("sdhci: Node Not found, skipping initialization\n");
+		return -1;
+	}
+
+	gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "mmc_gpio");
+	qca_gpio_init(gpio_node);
+
+	mmc_host.ioaddr = (void *)MSM_SDC1_SDHCI_BASE;
+	mmc_host.voltages = MMC_VDD_165_195;
+	mmc_host.version = SDHCI_SPEC_300;
+	mmc_host.cfg.part_type = PART_TYPE_EFI;
+	mmc_host.quirks = SDHCI_QUIRK_BROKEN_VOLTAGE;
+
+	emmc_clock_reset();
+	udelay(10);
+	emmc_clock_config();
+
+	if (add_sdhci(&mmc_host, 200000000, 400000)) {
+		printf("add_sdhci fail!\n");
+		return -1;
+	}
+
+	if (!ret && sfi->flash_type == SMEM_BOOT_MMC_FLASH) {
+		ret = board_mmc_env_init(mmc_host);
+	}
+
+	return ret;
+}
+#else
+int board_mmc_init(bd_t *bis)
+{
+	return 0;
+}
+#endif
+
+__weak int ipq_get_tz_version(char *version_name, int buf_size)
+{
+	return 1;
+}
+
+int apps_iscrashed(void)
+{
+	u32 *dmagic = (u32 *)CONFIG_IPQ5018_DMAGIC_ADDR;
+
+	if (*dmagic == DLOAD_MAGIC_COOKIE)
+		return 1;
+
+	return 0;
+}
+
+static void __fixup_usb_device_mode(void *blob)
+{
+	parse_fdt_fixup("/soc/usb3@8A00000/dwc3@8A00000%dr_mode%?peripheral", blob);
+	parse_fdt_fixup("/soc/usb3@8A00000/dwc3@8A00000%maximum-speed%?high-speed", blob);
+}
+
+static void fdt_fixup_diag_gadget(void *blob)
+{
+	__fixup_usb_device_mode(blob);
+	parse_fdt_fixup("/soc/qcom,gadget_diag@0%status%?ok", blob);
+}
+
+void ipq_fdt_fixup_usb_device_mode(void *blob)
+{
+	const char *usb_cfg;
+
+	usb_cfg = getenv("usb_mode");
+	if (!usb_cfg)
+		return;
+
+	if (!strncmp(usb_cfg, "peripheral", sizeof("peripheral")))
+		__fixup_usb_device_mode(blob);
+	else if (!strncmp(usb_cfg, "diag_gadget", sizeof("diag_gadget")))
+		fdt_fixup_diag_gadget(blob);
+	else
+		printf("%s: invalid param for usb_mode\n", __func__);
+}
+
+void ipq_fdt_fixup_socinfo(void *blob)
+{
+	uint32_t cpu_type;
+	uint32_t soc_version, soc_version_major, soc_version_minor;
+	int nodeoff, ret;
+
+	nodeoff = fdt_path_offset(blob, "/");
+
+	if (nodeoff < 0) {
+		printf("ipq: fdt fixup cannot find root node\n");
+		return;
+	}
+
+	ret = ipq_smem_get_socinfo_cpu_type(&cpu_type);
+	if (!ret) {
+		ret = fdt_setprop(blob, nodeoff, "cpu_type",
+				  &cpu_type, sizeof(cpu_type));
+		if (ret)
+			printf("%s: cannot set cpu type %d\n", __func__, ret);
+	} else {
+		printf("%s: cannot get socinfo\n", __func__);
+	}
+
+	ret = ipq_smem_get_socinfo_version((uint32_t *)&soc_version);
+	if (!ret) {
+		soc_version_major = SOCINFO_VERSION_MAJOR(soc_version);
+		soc_version_minor = SOCINFO_VERSION_MINOR(soc_version);
+
+		ret = fdt_setprop(blob, nodeoff, "soc_version_major",
+				  &soc_version_major,
+				  sizeof(soc_version_major));
+		if (ret)
+			printf("%s: cannot set soc_version_major %d\n",
+			       __func__, soc_version_major);
+
+		ret = fdt_setprop(blob, nodeoff, "soc_version_minor",
+				  &soc_version_minor,
+				  sizeof(soc_version_minor));
+		if (ret)
+			printf("%s: cannot set soc_version_minor %d\n",
+			       __func__, soc_version_minor);
+	} else {
+		printf("%s: cannot get soc version\n", __func__);
+	}
+	return;
+}
+
+void fdt_fixup_auto_restart(void *blob)
+{
+	const char *paniconwcssfatal;
+
+	paniconwcssfatal = getenv("paniconwcssfatal");
+
+	if (!paniconwcssfatal)
+		return;
+
+	if (strncmp(paniconwcssfatal, "1", sizeof("1"))) {
+		printf("fixup_auto_restart: invalid variable 'paniconwcssfatal'");
+	} else {
+		parse_fdt_fixup("/soc/q6v5_wcss@CD00000%delete%?qca,auto-restart", blob);
+	}
+	return;
+}
+
+#ifdef CONFIG_IPQ_BT_SUPPORT
+int bt_running;
+
+unsigned char hci_reset[] =
+{0x01, 0x03, 0x0c, 0x00};
+
+unsigned char adv_data[] =
+{0x01, 0X08, 0X20, 0X20, 0X1F, 0X0A, 0X09, 0X71,
+ 0X75, 0X61, 0X6c, 0X63, 0X6f, 0X6d, 0X6d, 0X00,
+ 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
+ 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
+ 0X00, 0X00, 0X00, 0X00};
+
+unsigned char set_interval[] =
+{0X01, 0X06, 0X20, 0X0F, 0X20, 0X00, 0X20, 0X00,
+ 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
+ 0X00, 0X07, 0X00};
+
+unsigned char start_beacon[] =
+{0x01, 0x0A, 0x20, 0x01, 0x01};
+
+struct hci_cmd{
+	unsigned char* data;
+	unsigned int len;
+};
+
+struct hci_cmd hci_cmds[] = {
+	{ hci_reset, sizeof(hci_reset) },
+	{ adv_data, sizeof(adv_data) },
+	{ set_interval, sizeof(set_interval) },
+	{ start_beacon, sizeof(start_beacon) },
+};
+
+int wait_for_bt_event(struct bt_descriptor *btDesc, u8 bt_wait)
+{
+	int val, timeout = 0;
+
+	do{
+		udelay(10);
+		bt_ipc_worker(btDesc);
+
+		if (bt_wait == BT_WAIT_FOR_START)
+			val = !atomic_read(&btDesc->state);
+		else
+			val = atomic_read(&btDesc->tx_in_progress);
+
+		if (timeout++ >= BT_TIMEOUT_US/10) {
+			printf(" %s timed out \n", __func__);
+			return -ETIMEDOUT;
+		}
+
+	} while (val);
+
+	return 0;
+}
+
+static int initialize_nvm(struct bt_descriptor *btDesc,
+						void *fileaddr, u32 filesize)
+{
+	unsigned char *buffer = fileaddr;
+	int bytes_read = 0, bytes_consumed = 0, ret;
+	HCI_Packet_t *hci_packet = NULL;
+
+	while(bytes_consumed < filesize )
+	{
+		bytes_read = (filesize - bytes_consumed) > NVM_SEGMENT_SIZE ?
+			NVM_SEGMENT_SIZE : filesize - bytes_consumed;
+		/* Constructing a HCI Packet to write NVM Segments to BTSS */
+		hci_packet = (HCI_Packet_t*)malloc(sizeof(HCI_Packet_t) +
+							NVM_SEGMENT_SIZE);
+
+		if(!hci_packet)
+		{
+			printf("Cannot allocate memory to HCI Packet \n");
+			return -ENOMEM;
+		}
+
+		/* Initializing HCI Packet Header */
+		hci_packet->HCIPacketType = ptHCICommandPacket;
+
+		/* Populating TLV Request Packet in HCI */
+		LE_UNALIGNED(&(hci_packet->HCIPayload.opcode), TLV_REQ_OPCODE);
+		LE_UNALIGNED(&(hci_packet->HCIPayload.parameter_total_length),
+				(bytes_read + DATA_REMAINING_LENGTH));
+		hci_packet->HCIPayload.command_request = TLV_COMMAND_REQUEST;
+		hci_packet->HCIPayload.tlv_segment_length = bytes_read;
+		memcpy(hci_packet->HCIPayload.tlv_segment_data, buffer,
+								bytes_read);
+
+		bt_ipc_sendmsg(btDesc, (u8*)hci_packet,
+				sizeof(HCI_Packet_t) + bytes_read);
+
+		free(hci_packet);
+		bytes_consumed += bytes_read;
+		buffer = fileaddr + bytes_consumed;
+
+		ret = wait_for_bt_event(btDesc, BT_WAIT_FOR_TX_COMPLETE);
+		if(ret || *((u8 *)btDesc->buf + TLV_RESPONSE_STATUS_INDEX) != 0)
+		{
+			printf( "\n NVM download failed\n");
+			if (!ret) {
+				kfree(btDesc->buf);
+				btDesc->buf = NULL;
+			}
+			return -EINVAL;
+		}
+		kfree(btDesc->buf);
+		btDesc->buf = NULL;
+	}
+
+	printf("NVM download successful \n");
+	bt_ipc_worker(btDesc);
+	return 0;
+}
+
+int send_bt_hci_cmds(struct bt_descriptor *btDesc)
+{
+	int ret, i;
+	int count = sizeof hci_cmds/ sizeof(struct hci_cmd);
+
+	for (i = 0; i < count; i++) {
+		bt_ipc_sendmsg(btDesc, hci_cmds[i].data, hci_cmds[i].len);
+
+		ret = wait_for_bt_event(btDesc, BT_WAIT_FOR_TX_COMPLETE);
+		if (ret)
+			return ret;
+
+		/*btDesc->buf will have response data with length btDesc->len*/
+		kfree(btDesc->buf);
+		btDesc->buf = NULL;
+	}
+	return 0;
+}
+
+int bt_init(void)
+{
+	struct bt_descriptor *btDesc;
+	int ret;
+
+	btDesc = kzalloc(sizeof(*btDesc), GFP_KERNEL);
+	if (!btDesc)
+		return -ENOMEM;
+
+	bt_ipc_init(btDesc);
+
+	enable_btss_lpo_clk();
+	ret = qti_scm_pas_init_image(PAS_ID, (u32)bt_fw_patchmdt);
+	if (ret) {
+		printf("patch auth failed\n");
+		return ret;
+	}
+
+	printf("patch authenticated successfully\n");
+
+	memcpy((void*)BT_RAM_PATCH, (void*)bt_fw_patchb02,
+					sizeof bt_fw_patchb02);
+
+	ret = qti_pas_and_auth_reset(PAS_ID);
+
+	if (ret) {
+		printf("BT out of reset failed\n");
+		return ret;
+	}
+
+	ret = wait_for_bt_event(btDesc, BT_WAIT_FOR_START);
+	if (ret)
+		return ret;
+
+	ret = initialize_nvm(btDesc, (void*)mpnv10bin, sizeof mpnv10bin);
+	if (ret)
+		return ret;
+
+	ret = wait_for_bt_event(btDesc, BT_WAIT_FOR_START);
+	if (ret)
+		return ret;
+
+	send_bt_hci_cmds(btDesc);
+
+	bt_running = 1;
+	return 0;
+}
+
+void fdt_fixup_bt_running(void *blob)
+{
+	if (bt_running) {
+		parse_fdt_fixup("/soc/bt@7000000%qcom,bt-running%1", blob);
+	}
+}
+#endif
+
+void reset_crashdump(void)
+{
+	unsigned int ret = 0;
+	qca_scm_sdi();
+	ret = qca_scm_dload(CLEAR_MAGIC);
+	if (ret)
+		printf ("Error in reseting the Magic cookie\n");
+	return;
+}
+
+void psci_sys_reset(void)
+{
+	__invoke_psci_fn_smc(0x84000009, 0, 0, 0);
+}
+
+void qti_scm_pshold(void)
+{
+	int ret;
+
+	ret = scm_call(SCM_SVC_BOOT, SCM_CMD_TZ_PSHOLD, NULL, 0, NULL, 0);
+
+	if (ret != 0)
+		writel(0, GCNT_PSHOLD);
+}
+
+void reset_cpu(unsigned long a)
+{
+	reset_crashdump();
+	if (is_scm_armv8()) {
+		psci_sys_reset();
+	} else {
+		qti_scm_pshold();
+	}
+	while(1);
+}
+
+#ifdef CONFIG_QPIC_NAND
+void qpic_set_clk_rate(unsigned int clk_rate, int blk_type, int req_clk_src_type)
+{
+	switch (blk_type) {
+		case QPIC_IO_MACRO_CLK:
+			/* select the clk source for IO_PAD_MACRO
+			 * clk source wil be either XO = 24MHz. or GPLL0 = 800MHz.
+			 */
+			if (req_clk_src_type == XO_CLK_SRC) {
+				/* default XO clock will enabled
+				 * i.e XO clock = 24MHz.
+				 * so div value will 0.
+				 * Input clock to IO_MACRO will be divided by 4 by default
+				 * by hardware and then taht clock will be go on bus.
+				 * i.e 24/4MHz = 6MHz i.e 6MHz will go onto the bus.
+				 */
+				writel(0x0, GCC_QPIC_IO_MACRO_CFG_RCGR);
+
+			} else if (req_clk_src_type == GPLL0_CLK_SRC) {
+				/* selct GPLL0 clock source 800MHz
+				 * so 800/4 = 200MHz.
+				 * Input clock to IO_MACRO will be divided by 4 by default
+				 * by hardware and then that clock will be go on bus.
+				 * i.e 200/4MHz = 50MHz i.e 50MHz will go onto the bus.
+				 */
+				if (clk_rate == IO_MACRO_CLK_320_MHZ)
+				       writel(0x104, GCC_QPIC_IO_MACRO_CFG_RCGR);
+				else if (clk_rate == IO_MACRO_CLK_266_MHZ)
+					writel(0x105, GCC_QPIC_IO_MACRO_CFG_RCGR);
+				else if (clk_rate == IO_MACRO_CLK_228_MHZ)
+					writel(0x106, GCC_QPIC_IO_MACRO_CFG_RCGR);
+				else if (clk_rate == IO_MACRO_CLK_100_MHZ)
+					writel(0x10F, GCC_QPIC_IO_MACRO_CFG_RCGR);
+				else if (clk_rate == IO_MACRO_CLK_200_MHZ)
+					writel(0x107, GCC_QPIC_IO_MACRO_CFG_RCGR);
+
+			} else {
+				printf("wrong clk src selection requested.\n");
+			}
+
+			/* Enablle update bit to update the new configuration */
+			writel((UPDATE_EN | readl(GCC_QPIC_IO_MACRO_CMD_RCGR)),
+					GCC_QPIC_IO_MACRO_CMD_RCGR);
+
+			/* Enable the QPIC_IO_MACRO_CLK */
+			writel(0x1, GCC_QPIC_IO_MACRO_CBCR);
+
+		       break;
+		case QPIC_CORE_CLK:
+		       /* To DO if needed for QPIC core clock setting */
+		       break;
+		default:
+		       printf("wrong qpic block type\n");
+		       break;
+	}
+}
+#endif
+
+void board_nand_init(void)
+{
+#ifdef CONFIG_QPIC_SERIAL
+	/* check for nand node in dts
+	 * if nand node in dts is disabled then
+	 * simply return from here without
+	 * initializing
+	 */
+	int node;
+	node = fdt_path_offset(gd->fdt_blob, "/nand-controller");
+	if (!fdtdec_get_is_enabled(gd->fdt_blob, node)) {
+		printf("QPIC: disabled, skipping initialization\n");
+	} else {
+		qpic_nand_init(NULL);
+	}
+#endif
+
+#ifdef CONFIG_IPQ_BT_SUPPORT
+	bt_init();
+#endif
+#ifdef CONFIG_QCA_SPI
+	int gpio_node;
+	gpio_node = fdt_path_offset(gd->fdt_blob, "/spi/spi_gpio");
+	if (gpio_node >= 0) {
+		qca_gpio_init(gpio_node);
+#ifdef CONFIG_MTD_DEVICE
+		ipq_spi_init(CONFIG_IPQ_SPI_NOR_INFO_IDX);
+#endif
+	}
+#endif
+}
+
+void enable_caches(void)
+{
+	qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
+	smem_get_boot_flash(&sfi->flash_type,
+		&sfi->flash_index,
+		&sfi->flash_chip_select,
+		&sfi->flash_block_size,
+		&sfi->flash_density);
+	icache_enable();
+	/*Skips dcache_enable during JTAG recovery */
+	if (sfi->flash_type)
+		dcache_enable();
+}
+
+void disable_caches(void)
+{
+	icache_disable();
+	dcache_disable();
+}
+
+unsigned long timer_read_counter(void)
+{
+	return 0;
+}
+
+static void set_ext_mdio_gpio(int node)
+{
+	unsigned int mdio_gpio[2] = {0};
+	int status = -1;
+	unsigned int *mdio_gpio_base;
+
+	status = fdtdec_get_int_array(gd->fdt_blob,
+					node,
+					"ext_mdio_gpio",
+					mdio_gpio,
+					2);
+	if (status >= 0) {
+		/*  mdc  */
+		mdio_gpio_base =
+			(unsigned int *)GPIO_CONFIG_ADDR(mdio_gpio[0]);
+		writel(0x7, mdio_gpio_base);
+		/*  mdio */
+		mdio_gpio_base =
+			(unsigned int *)GPIO_CONFIG_ADDR(mdio_gpio[1]);
+		writel(0x7, mdio_gpio_base);
+	}
+}
+
+static void reset_napa_phy_gpio(int gpio)
+{
+	unsigned int *napa_gpio_base;
+
+	napa_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(gpio);
+	writel(0x203, napa_gpio_base);
+	writel(0x0, GPIO_IN_OUT_ADDR(gpio));
+	mdelay(500);
+	writel(0x2, GPIO_IN_OUT_ADDR(gpio));
+}
+
+static void reset_8033_phy_gpio(int gpio)
+{
+	unsigned int *phy_8033_gpio_base;
+
+	ppe_uniphy_refclk_set();
+	phy_8033_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(gpio);
+	writel(0x2C1, phy_8033_gpio_base);
+	writel(0x0, GPIO_IN_OUT_ADDR(gpio));
+	mdelay(500);
+	writel(0x2, GPIO_IN_OUT_ADDR(gpio));
+}
+
+static void reset_s17c_switch_gpio(int gpio)
+{
+	unsigned int *switch_gpio_base =
+		(unsigned int *)GPIO_CONFIG_ADDR(gpio);
+/*
+ * Set ref clock 25MHZ and enable Force mode
+ */
+	ppe_uniphy_refclk_set();
+	ppe_uniphy_set_forceMode();
+
+	writel(0x203, switch_gpio_base);
+	writel(0x0, GPIO_IN_OUT_ADDR(gpio));
+	mdelay(500);
+	writel(0x2, GPIO_IN_OUT_ADDR(gpio));
+}
+
+static void cmn_blk_clk_set(void)
+{
+	/* GMN block */
+	writel(0x1, GCC_CMN_BLK_AHB_CBCR);
+	mdelay(20);
+	writel(0x1, GCC_CMN_BLK_SYS_CBCR);
+	mdelay(20);
+}
+
+static void uniphy_clk_set(void)
+{
+	writel(0x1, GCC_UNIPHY_AHB_CBCR);
+	mdelay(20);
+	writel(0x1, GCC_UNIPHY_SYS_CBCR);
+	mdelay(20);
+	writel(0x1, GCC_UNIPHY_RX_CBCR);
+	mdelay(20);
+	writel(0x1, GCC_UNIPHY_TX_CBCR);
+	mdelay(20);
+
+}
+
+static void gephy_uniphy_clock_disable(void)
+{
+	u32 reg_val = 0;
+
+	reg_val = readl(GCC_GEPHY_RX_CBCR);
+	reg_val &= ~GCC_CBCR_CLK_ENABLE;
+	writel(reg_val, GCC_GEPHY_RX_CBCR);
+	mdelay(20);
+
+	reg_val = readl(GCC_GEPHY_TX_CBCR);
+	reg_val &= ~GCC_CBCR_CLK_ENABLE;
+	writel(reg_val, GCC_GEPHY_TX_CBCR);
+	mdelay(20);
+
+	reg_val = readl(GCC_UNIPHY_RX_CBCR);
+	reg_val &= ~GCC_CBCR_CLK_ENABLE;
+	writel(reg_val, GCC_UNIPHY_RX_CBCR);
+	mdelay(20);
+
+	reg_val = readl(GCC_UNIPHY_TX_CBCR);
+	reg_val &= ~GCC_CBCR_CLK_ENABLE;
+	writel(reg_val, GCC_UNIPHY_TX_CBCR);
+	mdelay(20);
+
+}
+
+static void gmac_clock_disable(void)
+{
+        u32 reg_val = 0;
+
+	reg_val = readl(GCC_GMAC0_RX_CBCR);
+	reg_val &= ~GCC_CBCR_CLK_ENABLE;
+	writel(reg_val, GCC_GMAC0_RX_CBCR);
+	mdelay(20);
+
+	reg_val = readl(GCC_GMAC0_TX_CBCR);
+	reg_val &= ~GCC_CBCR_CLK_ENABLE;
+	writel(reg_val, GCC_GMAC0_TX_CBCR);
+	mdelay(20);
+
+	reg_val = readl(GCC_GMAC1_RX_CBCR);
+	reg_val &= ~GCC_CBCR_CLK_ENABLE;
+	writel(reg_val, GCC_GMAC1_RX_CBCR);
+	mdelay(20);
+
+	reg_val = readl(GCC_GMAC1_TX_CBCR);
+	reg_val &= ~GCC_CBCR_CLK_ENABLE;
+	writel(reg_val, GCC_GMAC1_TX_CBCR);
+	mdelay(20);
+
+}
+
+static void gmac_clk_src_init(void)
+{
+	u32 reg_val, iGmac_id, iTxRx;
+
+	/*select source of GMAC*/
+	reg_val = readl(GCC_GMAC0_RX_CFG_RCGR);
+	reg_val &= ~GCC_GMAC_CFG_RCGR_SRC_SEL_MASK;
+	reg_val |= GCC_GMAC0_RX_SRC_SEL_GEPHY_TX;
+	writel(reg_val, GCC_GMAC0_RX_CFG_RCGR);
+
+	reg_val = readl(GCC_GMAC0_TX_CFG_RCGR);
+	reg_val &= ~GCC_GMAC_CFG_RCGR_SRC_SEL_MASK;
+	reg_val |= GCC_GMAC0_TX_SRC_SEL_GEPHY_TX;
+	writel(reg_val, GCC_GMAC0_TX_CFG_RCGR);
+
+	reg_val = readl(GCC_GMAC1_RX_CFG_RCGR);
+	reg_val &= ~GCC_GMAC_CFG_RCGR_SRC_SEL_MASK;
+	reg_val |= GCC_GMAC1_RX_SRC_SEL_UNIPHY_RX;
+	writel(reg_val, GCC_GMAC1_RX_CFG_RCGR);
+
+	reg_val = readl(GCC_GMAC1_TX_CFG_RCGR);
+	reg_val &= ~GCC_GMAC_CFG_RCGR_SRC_SEL_MASK;
+	reg_val |= GCC_GMAC1_TX_SRC_SEL_UNIPHY_TX;
+	writel(reg_val, GCC_GMAC1_TX_CFG_RCGR);
+
+	/* update above clock configuration */
+	for (iGmac_id = 0; iGmac_id < 2; ++iGmac_id) {
+		for (iTxRx = 0; iTxRx < 2; ++iTxRx){
+			reg_val = 0;
+			reg_val = readl(GCC_GMAC0_RX_CMD_RCGR +
+				(iTxRx * 8) + (iGmac_id * 0x10));
+			reg_val &= ~0x1;
+			reg_val |= 0x1;
+			writel(reg_val, GCC_GMAC0_RX_CMD_RCGR +
+				(iTxRx * 8) + (iGmac_id * 0x10));
+		}
+	}
+	reg_val = readl(GCC_GMAC_CFG_RCGR);
+	reg_val = 0x209;
+	writel(reg_val, GCC_GMAC_CFG_RCGR);
+
+	reg_val = readl(GCC_GMAC_CMD_RCGR);
+	reg_val &= ~0x1;
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC_CMD_RCGR);
+}
+
+static void gephy_reset(void)
+{
+	u32 reg_val;
+
+	reg_val = readl(GCC_GEPHY_BCR);
+	writel(reg_val | (GCC_GEPHY_BCR_BLK_ARES),
+		GCC_GEPHY_BCR);
+	mdelay(20);
+	writel(reg_val & (~GCC_GEPHY_BCR_BLK_ARES),
+		GCC_GEPHY_BCR);
+	reg_val = readl(GCC_GEPHY_MISC);
+	writel(reg_val | (GCC_GEPHY_MISC_ARES),
+		GCC_GEPHY_MISC);
+	mdelay(20);
+	writel(reg_val & (~GCC_GEPHY_MISC_ARES),
+		GCC_GEPHY_MISC);
+}
+
+static void uniphy_reset(void)
+{
+	u32 reg_val;
+
+	reg_val = readl(GCC_UNIPHY_BCR);
+	writel(reg_val | (GCC_UNIPHY_BCR_BLK_ARES),
+		GCC_UNIPHY_BCR);
+	mdelay(20);
+	writel(reg_val & (~GCC_UNIPHY_BCR_BLK_ARES),
+		GCC_UNIPHY_BCR);
+}
+
+static void gmac_reset(void)
+{
+	u32 reg_val;
+
+	reg_val = readl(GCC_GMAC0_BCR);
+	writel(reg_val | (GCC_GMAC0_BCR_BLK_ARES),
+		GCC_GMAC0_BCR);
+	mdelay(20);
+	writel(reg_val & (~GCC_GMAC0_BCR_BLK_ARES),
+		GCC_GMAC0_BCR);
+
+	reg_val = readl(GCC_GMAC1_BCR);
+	writel(reg_val | (GCC_GMAC1_BCR_BLK_ARES),
+		GCC_GMAC1_BCR);
+	mdelay(200);
+	writel(reg_val & (~GCC_GMAC1_BCR_BLK_ARES),
+		GCC_GMAC1_BCR);
+
+}
+
+static void cmn_clock_init (void)
+{
+	u32 reg_val = 0;
+#ifdef INTERNAL_96MHZ
+	reg_val = readl(CMN_BLK_PLL_SRC_ADDR);
+	reg_val = ((reg_val & PLL_CTRL_SRC_MASK) |
+			(CMN_BLK_PLL_SRC_SEL_FROM_REG << 0x8));
+	writel(reg_val, CMN_BLK_PLL_SRC_ADDR);
+	reg_val = readl(CMN_BLK_ADDR + 4);
+	reg_val = (reg_val & PLL_REFCLK_DIV_MASK) | PLL_REFCLK_DIV_2;
+	writel(reg_val, CMN_BLK_ADDR + 0x4);
+#else
+	reg_val = readl(CMN_BLK_ADDR + 4);
+	reg_val = (reg_val & FREQUENCY_MASK) | INTERNAL_48MHZ_CLOCK;
+	writel(reg_val, CMN_BLK_ADDR + 0x4);
+#endif
+	reg_val = readl(CMN_BLK_ADDR);
+	reg_val = reg_val | 0x40;
+	writel(reg_val, CMN_BLK_ADDR);
+	mdelay(1);
+	reg_val = reg_val & (~0x40);
+	writel(reg_val, CMN_BLK_ADDR);
+	mdelay(1);
+	writel(0xbf, CMN_BLK_ADDR);
+	mdelay(1);
+	writel(0xff, CMN_BLK_ADDR);
+	mdelay(1);
+}
+
+static void cmnblk_enable(void)
+{
+	u32 reg_val;
+
+	reg_val = readl(TCSR_ETH_LDO_RDY_REG);
+	reg_val |= ETH_LDO_RDY;
+	writel(reg_val, TCSR_ETH_LDO_RDY_REG);
+}
+
+static void cmnblk_check_state(void)
+{
+	u32 reg_val, times = 20;
+
+	while(times--)
+	{
+		reg_val = readl(CMN_PLL_PLL_LOCKED_REG);
+		if(reg_val & CMN_PLL_LOCKED) {
+			printf("cmbblk is stable %x\n",
+			reg_val);
+			break;
+		}
+		mdelay(10);
+	}
+	if(!times) {
+		printf("200ms have been over %x\n",
+		readl(CMN_PLL_PLL_LOCKED_REG));
+	}
+}
+
+static void gcc_clock_enable(void)
+{
+	u32 reg_val;
+
+	reg_val = readl(GCC_MDIO0_BASE + 0x4);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_MDIO0_BASE + 0x4);
+
+	reg_val = readl(GCC_MDIO0_BASE + 0x14);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_MDIO0_BASE + 0x14);
+
+	reg_val = readl(GCC_GMAC0_SYS_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC0_SYS_CBCR);
+
+	reg_val = readl(GCC_GMAC0_PTP_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC0_PTP_CBCR);
+
+	reg_val = readl(GCC_GMAC0_CFG_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC0_CFG_CBCR);
+
+	reg_val = readl(GCC_GMAC1_SYS_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC1_SYS_CBCR);
+
+	reg_val = readl(GCC_GMAC1_PTP_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC1_PTP_CBCR);
+
+	reg_val = readl(GCC_GMAC1_CFG_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC1_CFG_CBCR);
+
+	reg_val = readl(GCC_GMAC0_RX_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC0_RX_CBCR);
+
+	reg_val = readl(GCC_GMAC0_TX_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC0_TX_CBCR);
+
+	reg_val = readl(GCC_GMAC1_RX_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC1_RX_CBCR);
+
+	reg_val = readl(GCC_GMAC1_TX_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_GMAC1_TX_CBCR);
+
+	reg_val = readl(GCC_SNOC_GMAC0_AHB_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_SNOC_GMAC0_AHB_CBCR);
+
+	reg_val = readl(GCC_SNOC_GMAC1_AHB_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_SNOC_GMAC1_AHB_CBCR);
+
+	reg_val = readl(GCC_SNOC_GMAC0_AXI_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_SNOC_GMAC0_AXI_CBCR);
+
+	reg_val = readl(GCC_SNOC_GMAC1_AXI_CBCR);
+	reg_val |= 0x1;
+	writel(reg_val, GCC_SNOC_GMAC1_AXI_CBCR);
+}
+
+static void ethernet_clock_enable(void)
+{
+	cmn_blk_clk_set();
+	uniphy_clk_set();
+	gephy_uniphy_clock_disable();
+	gmac_clock_disable();
+	gmac_clk_src_init();
+	cmn_clock_init();
+	cmnblk_enable();
+	cmnblk_check_state();
+	gephy_reset();
+	uniphy_reset();
+	gmac_reset();
+	gcc_clock_enable();
+}
+
+static void enable_gephy_led(int gpio)
+{
+	unsigned int *led_gpio_base =
+		(unsigned int *)GPIO_CONFIG_ADDR(gpio);
+
+	writel(0xc5, led_gpio_base);
+}
+
+int board_eth_init(bd_t *bis)
+{
+	int status;
+	int led_gpio;
+	int gmac_cfg_node = 0, offset = 0;
+	int loop = 0;
+	int switch_gpio = 0;
+	unsigned int tmp_phy_array[8] = {0};
+
+	gmac_cfg_node = fdt_path_offset(gd->fdt_blob, "/gmac_cfg");
+	if (gmac_cfg_node >= 0) {
+		/*
+		 * Clock enable
+		 */
+		ethernet_clock_enable();
+		led_gpio = fdtdec_get_uint(gd->fdt_blob,
+				gmac_cfg_node, "gephy_led", 0);
+		if (led_gpio)
+			enable_gephy_led(led_gpio);
+
+		set_ext_mdio_gpio(gmac_cfg_node);
+
+		for (offset = fdt_first_subnode(gd->fdt_blob, gmac_cfg_node);
+			offset > 0;
+			offset = fdt_next_subnode(gd->fdt_blob, offset) , loop++) {
+
+			gmac_cfg[loop].base = fdtdec_get_uint(gd->fdt_blob,
+					offset, "base", 0);
+
+			gmac_cfg[loop].unit = fdtdec_get_uint(gd->fdt_blob,
+					offset, "unit", 0);
+
+			gmac_cfg[loop].phy_addr = fdtdec_get_uint(gd->fdt_blob,
+					offset, "phy_address", 0);
+
+			gmac_cfg[loop].phy_interface_mode = fdtdec_get_uint(gd->fdt_blob,
+					offset, "phy_interface_mode", 0);
+
+			gmac_cfg[loop].phy_external_link = fdtdec_get_uint(gd->fdt_blob,
+					offset, "phy_external_link", 0);
+
+			gmac_cfg[loop].phy_napa_gpio = fdtdec_get_uint(gd->fdt_blob,
+					offset, "napa_gpio", 0);
+			if (gmac_cfg[loop].phy_napa_gpio){
+				reset_napa_phy_gpio(gmac_cfg[loop].phy_napa_gpio);
+			}
+			gmac_cfg[loop].phy_8033_gpio = fdtdec_get_uint(gd->fdt_blob,
+					offset, "8033_gpio", 0);
+			if (gmac_cfg[loop].phy_8033_gpio){
+				reset_8033_phy_gpio(gmac_cfg[loop].phy_8033_gpio);
+			}
+			switch_gpio =  fdtdec_get_uint(gd->fdt_blob, offset, "switch_gpio", 0);
+			if (switch_gpio) {
+				reset_s17c_switch_gpio(switch_gpio);
+			}
+			gmac_cfg[loop].phy_type = fdtdec_get_uint(gd->fdt_blob,
+					offset, "phy_type", -1);
+
+			gmac_cfg[loop].mac_pwr = fdtdec_get_uint(gd->fdt_blob,
+					offset, "mac_pwr", 0);
+
+			gmac_cfg[loop].ipq_swith = fdtdec_get_uint(gd->fdt_blob,
+					offset, "s17c_switch_enable", 0);
+			if (gmac_cfg[loop].ipq_swith) {
+				gmac_cfg[loop].switch_port_count = fdtdec_get_uint(
+					gd->fdt_blob,
+					offset, "switch_port_count", 0);
+
+				fdtdec_get_int_array(gd->fdt_blob, offset, "switch_phy_address",
+					tmp_phy_array, gmac_cfg[loop].switch_port_count);
+
+				for(int inner_loop = 0; inner_loop < gmac_cfg[loop].switch_port_count;
+					inner_loop++){
+				gmac_cfg[loop].switch_port_phy_address[inner_loop] =
+					(char)tmp_phy_array[inner_loop];
+				}
+			}
+		}
+	}
+
+	if (loop < CONFIG_IPQ_NO_MACS)
+		 gmac_cfg[loop].unit = -1;
+
+	status = ipq_gmac_init(gmac_cfg);
+
+	return status;
+}
+
+void set_flash_secondary_type(qca_smem_flash_info_t *smem)
+{
+	return;
+};
+
+#ifdef CONFIG_USB_XHCI_IPQ
+void board_usb_deinit(int id)
+{
+	int nodeoff, ssphy, gpio_node;
+	char node_name[8];
+
+	if(readl(EUD_EUD_EN2))
+	/*
+	 * Eud enable skipping deinit part
+	 */
+		return;
+
+	snprintf(node_name, sizeof(node_name), "usb%d", id);
+	nodeoff = fdt_path_offset(gd->fdt_blob, node_name);
+	if (fdtdec_get_int(gd->fdt_blob, nodeoff, "qcom,emulation", 0))
+		return;
+
+	ssphy = fdtdec_get_int(gd->fdt_blob, nodeoff, "ssphy", 0);
+	/* Enable USB PHY Power down */
+	setbits_le32(QUSB2PHY_BASE + 0xA4, 0x0);
+	/* Disable clocks */
+	writel(0x0, GCC_USB0_PHY_CFG_AHB_CBCR);
+	writel(0x4220, GCC_USB0_MASTER_CBCR);
+	writel(0x0, GCC_SYS_NOC_USB0_AXI_CBCR);
+	writel(0x0, GCC_USB0_SLEEP_CBCR);
+	writel(0x0, GCC_USB0_MOCK_UTMI_CBCR);
+	writel(0x0, GCC_USB0_AUX_CBCR);
+	writel(0x0, GCC_USB0_LFPS_CBCR);
+	/* GCC_QUSB2_0_PHY_BCR */
+	set_mdelay_clearbits_le32(GCC_QUSB2_0_PHY_BCR, 0x1, 10);
+	/* GCC_USB0_PHY_BCR */
+	if (ssphy)
+		set_mdelay_clearbits_le32(GCC_USB0_PHY_BCR, 0x1, 10);
+	/* GCC Reset USB BCR */
+	set_mdelay_clearbits_le32(GCC_USB0_BCR, 0x1, 10);
+	/* Deselect the usb phy mux */
+	if (ssphy)
+		writel(0x0, TCSR_USB_PCIE_SEL);
+
+	/* skip gpio pull config if bt_debug is enabled */
+	if(getenv("bt_debug"))
+		return;
+
+	/* deinit USB power GPIO for drive 5V */
+	gpio_node = fdt_subnode_offset(gd->fdt_blob, nodeoff, "usb_gpio");
+	if (gpio_node >= 0){
+		gpio_node = fdt_first_subnode(gd->fdt_blob, gpio_node);
+		if (gpio_node > 0) {
+			int gpio = fdtdec_get_uint(gd->fdt_blob,
+					gpio_node, "gpio", 0);
+			unsigned int *gpio_base =
+				(unsigned int *)GPIO_CONFIG_ADDR(gpio);
+			int usb_pwr_gpio = fdtdec_get_int(gd->fdt_blob, nodeoff, "usb_pwr_gpio", 0);
+			writel(0xC1, gpio_base);
+			gpio_set_value(usb_pwr_gpio, GPIO_OUT_LOW);
+		}
+	}
+
+}
+
+static void usb_clock_init(int id, int ssphy)
+{
+	int cfg;
+
+	/* select usb phy mux */
+	if (ssphy)
+		writel(0x1, TCSR_USB_PCIE_SEL);
+
+	/* Configure usb0_master_clk_src */
+	cfg = (GCC_USB0_MASTER_CFG_RCGR_SRC_SEL |
+		GCC_USB0_MASTER_CFG_RCGR_SRC_DIV);
+	writel(cfg, GCC_USB0_MASTER_CFG_RCGR);
+	writel(CMD_UPDATE, GCC_USB0_MASTER_CMD_RCGR);
+	mdelay(100);
+	writel(ROOT_EN, GCC_USB0_MASTER_CMD_RCGR);
+
+	/* Configure usb0_mock_utmi_clk_src */
+	cfg = (GCC_USB_MOCK_UTMI_SRC_SEL |
+		GCC_USB_MOCK_UTMI_SRC_DIV);
+	writel(cfg, GCC_USB0_MOCK_UTMI_CFG_RCGR);
+	writel(GCC_USB_MOCK_UTMI_CLK_DIV, GCC_USB0_MOCK_UTMI_CBCR);
+	writel(CMD_UPDATE, GCC_USB0_MOCK_UTMI_CMD_RCGR);
+	mdelay(100);
+	writel(ROOT_EN, GCC_USB0_MOCK_UTMI_CMD_RCGR);
+
+	/* Configure usb0_aux_clk_src */
+	cfg = (GCC_USB0_AUX_CFG_SRC_SEL |
+		GCC_USB0_AUX_CFG_SRC_DIV);
+	writel(cfg, GCC_USB0_AUX_CFG_RCGR);
+	writel(CMD_UPDATE, GCC_USB0_AUX_CMD_RCGR);
+	mdelay(100);
+	writel(ROOT_EN, GCC_USB0_AUX_CMD_RCGR);
+
+	/* Configure usb0_lfps_cmd_rcgr */
+	cfg = (GCC_USB0_LFPS_CFG_SRC_SEL |
+		GCC_USB0_LFPS_CFG_SRC_DIV);
+	writel(cfg, GCC_USB0_LFPS_CFG_RCGR);
+	writel(LFPS_M, GCC_USB0_LFPS_M);
+	writel(LFPS_N, GCC_USB0_LFPS_N);
+	writel(LFPS_D, GCC_USB0_LFPS_D);
+	writel(readl(GCC_USB0_LFPS_CFG_RCGR) | GCC_USB0_LFPS_MODE,
+			GCC_USB0_LFPS_CFG_RCGR);
+	writel(CMD_UPDATE, GCC_USB0_LFPS_CMD_RCGR);
+	mdelay(100);
+	writel(ROOT_EN, GCC_USB0_LFPS_CMD_RCGR);
+
+	/* Configure CBCRs */
+	writel(CLK_DISABLE, GCC_SYS_NOC_USB0_AXI_CBCR);
+	writel(CLK_ENABLE, GCC_SYS_NOC_USB0_AXI_CBCR);
+	writel((readl(GCC_USB0_MASTER_CBCR) | CLK_ENABLE),
+		GCC_USB0_MASTER_CBCR);
+	writel(CLK_ENABLE, GCC_USB0_SLEEP_CBCR);
+	writel((GCC_USB_MOCK_UTMI_CLK_DIV | CLK_ENABLE),
+		GCC_USB0_MOCK_UTMI_CBCR);
+	writel(CLK_DISABLE, GCC_USB0_PIPE_CBCR);
+	writel(CLK_ENABLE, GCC_USB0_PHY_CFG_AHB_CBCR);
+	writel(CLK_ENABLE, GCC_USB0_AUX_CBCR);
+	writel(CLK_ENABLE, GCC_USB0_LFPS_CBCR);
+}
+
+static void usb_init_hsphy(void __iomem *phybase, int ssphy)
+{
+	if (!ssphy) {
+		/*Enable utmi instead of pipe*/
+		writel((readl(USB30_GENERAL_CFG) | PIPE_UTMI_CLK_DIS), USB30_GENERAL_CFG);
+
+		udelay(100);
+
+		writel((readl(USB30_GENERAL_CFG) | PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW), USB30_GENERAL_CFG);
+
+		udelay(100);
+
+		writel((readl(USB30_GENERAL_CFG) & ~PIPE_UTMI_CLK_DIS), USB30_GENERAL_CFG);
+	}
+	/* Disable USB PHY Power down */
+	setbits_le32(phybase + 0xA4, 0x1);
+	/* Enable override ctrl */
+	writel(UTMI_PHY_OVERRIDE_EN, phybase + USB_PHY_CFG0);
+	/* Enable POR*/
+	writel(POR_EN, phybase + USB_PHY_UTMI_CTRL5);
+	udelay(15);
+	/* Configure frequency select value*/
+	writel(FREQ_SEL, phybase + USB_PHY_FSEL_SEL);
+	/* Configure refclk frequency */
+	writel(COMMONONN | FSEL | RETENABLEN,
+			phybase + USB_PHY_HS_PHY_CTRL_COMMON0);
+	/* select refclk source */
+	writel(CLKCORE, phybase + USB_PHY_REFCLK_CTRL);
+	/* select ATERESET*/
+	writel(POR_EN & ATERESET, phybase + USB_PHY_UTMI_CTRL5);
+	writel(USB2_SUSPEND_N_SEL | USB2_SUSPEND_N | USB2_UTMI_CLK_EN,
+			phybase + USB_PHY_HS_PHY_CTRL2);
+	writel(0x0, phybase + USB_PHY_UTMI_CTRL5);
+	writel(USB2_SUSPEND_N | USB2_UTMI_CLK_EN,
+			phybase + USB_PHY_HS_PHY_CTRL2);
+	/* Disable override ctrl */
+	writel(0x0, phybase + USB_PHY_CFG0);
+}
+
+static void usb_init_ssphy(void __iomem *phybase)
+{
+	writel(CLK_ENABLE, GCC_USB0_PHY_CFG_AHB_CBCR);
+	writel(CLK_ENABLE, GCC_USB0_PIPE_CBCR);
+	udelay(100);
+	/*set frequency initial value*/
+	writel(0x1cb9, phybase + SSCG_CTRL_REG_4);
+	writel(0x023a, phybase + SSCG_CTRL_REG_5);
+	/*set spectrum spread count*/
+	writel(0xd360, phybase + SSCG_CTRL_REG_3);
+	/*set fstep*/
+	writel(0x1, phybase + SSCG_CTRL_REG_1);
+	writel(0xeb, phybase + SSCG_CTRL_REG_2);
+	return;
+}
+
+static void usb_init_phy(int index, int ssphy)
+{
+	void __iomem *boot_clk_ctl, *usb_bcr, *qusb2_phy_bcr;
+
+	boot_clk_ctl = (u32 *)GCC_USB_0_BOOT_CLOCK_CTL;
+	usb_bcr = (u32 *)GCC_USB0_BCR;
+	qusb2_phy_bcr = (u32 *)GCC_QUSB2_0_PHY_BCR;
+
+	/* Disable USB Boot Clock */
+	clrbits_le32(boot_clk_ctl, 0x0);
+
+	/* GCC Reset USB BCR */
+	set_mdelay_clearbits_le32(usb_bcr, 0x1, 10);
+
+	if (ssphy)
+		setbits_le32(GCC_USB0_PHY_BCR, 0x1);
+	setbits_le32(qusb2_phy_bcr, 0x1);
+	udelay(1);
+	/* Config user control register */
+	writel(0x4004010, USB30_GUCTL);
+	writel(0x4945920, USB30_FLADJ);
+	if (ssphy)
+		clrbits_le32(GCC_USB0_PHY_BCR, 0x1);
+	clrbits_le32(qusb2_phy_bcr, 0x1);
+	udelay(30);
+
+	if (ssphy)
+		usb_init_ssphy((u32 *)USB3PHY_APB_BASE);
+	usb_init_hsphy((u32 *)QUSB2PHY_BASE, ssphy);
+}
+
+int ipq_board_usb_init(void)
+{
+	int i, nodeoff, ssphy, gpio_node, usb_pwr_gpio;
+	char node_name[8];
+
+	if(readl(EUD_EUD_EN2)) {
+		printf("USB: EUD Enable, skipping initialization\n");
+		return 0;
+	}
+
+	for (i=0; i<CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
+		snprintf(node_name, sizeof(node_name), "usb%d", i);
+		nodeoff = fdt_path_offset(gd->fdt_blob, node_name);
+		if (nodeoff < 0){
+			printf("USB: Node Not found, skipping initialization\n");
+			return 0;
+		}
+
+		ssphy = fdtdec_get_int(gd->fdt_blob, nodeoff, "ssphy", 0);
+		if (!fdtdec_get_int(gd->fdt_blob, nodeoff, "qcom,emulation", 0)) {
+
+			usb_clock_init(i, ssphy);
+			usb_init_phy(i, ssphy);
+		}else {
+			/* Config user control register */
+			writel(0x0C804010, USB30_GUCTL);
+		}
+	}
+	/* skip gpio pull config if bt_debug is enabled */
+	if(!getenv("bt_debug")){
+		/* USB power GPIO for drive 5V */
+		gpio_node =
+			fdt_subnode_offset(gd->fdt_blob, nodeoff, "usb_gpio");
+		if (gpio_node >= 0) {
+			qca_gpio_init(gpio_node);
+			usb_pwr_gpio = fdtdec_get_int(gd->fdt_blob, nodeoff, "usb_pwr_gpio", 0);
+			gpio_set_value(usb_pwr_gpio, GPIO_OUT_HIGH);
+		}
+	}
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PCI_IPQ
+static void pcie_v2_clock_init(int lane)
+{
+#ifdef CONFIG_PCI
+	u32 reg_val;
+	void __iomem *base;
+
+	/*single lane*/
+	/* Enable SYS_NOC clock */
+	if (lane == 1) {
+		base = (void __iomem *)GCC_PCIE1_BOOT_CLOCK_CTL;
+		writel(CLK_ENABLE, GCC_SYS_NOC_PCIE1_AXI_CBCR);
+		mdelay(1);
+		/* Configure pcie1_aux_clk_src */
+		writel((GCC_PCIE1_AUX_CFG_RCGR_SRC_SEL |
+			GCC_PCIE1_AUX_CFG_RCGR_SRC_DIV),
+			base + PCIE_AUX_CFG_RCGR);
+		mdelay(1);
+		reg_val = readl(base + PCIE_AUX_CMD_RCGR);
+		reg_val &= ~0x1;
+		reg_val |= 0x1;
+		writel(reg_val, base + PCIE_AUX_CMD_RCGR);
+
+		/* Configure pcie1_axi_clk_src */
+		writel((GCC_PCIE1_AXI_CFG_RCGR_SRC_SEL |
+			GCC_PCIE1_AXI_CFG_RCGR_SRC_DIV),
+			base + PCIE_AXI_CFG_RCGR);
+		mdelay(1);
+		reg_val = readl(base + PCIE_AXI_CMD_RCGR);
+		reg_val &= ~0x1;
+		reg_val |= 0x1;
+		writel(reg_val, base + PCIE_AXI_CMD_RCGR);
+	} else { /*double lane*/
+		base = (void __iomem *)GCC_PCIE0_BOOT_CLOCK_CTL;
+		writel(CLK_ENABLE, GCC_SYS_NOC_PCIE0_AXI_CBCR);
+		mdelay(1);
+		/* Configure pcie1_aux_clk_src */
+		writel((GCC_PCIE0_AUX_CFG_RCGR_SRC_SEL |
+			GCC_PCIE0_AUX_CFG_RCGR_SRC_DIV),
+			base + PCIE_AUX_CFG_RCGR);
+		mdelay(1);
+		reg_val = readl(base + PCIE_AUX_CMD_RCGR);
+		reg_val &= ~0x1;
+		reg_val |= 0x1;
+		writel(reg_val, base + PCIE_AUX_CMD_RCGR);
+
+		/* Configure pcie1_axi_clk_src */
+		writel((GCC_PCIE0_AXI_CFG_RCGR_SRC_SEL |
+			GCC_PCIE0_AXI_CFG_RCGR_SRC_DIV),
+			base + PCIE_AXI_CFG_RCGR);
+		mdelay(1);
+		reg_val = readl(base + PCIE_AXI_CMD_RCGR);
+		reg_val &= ~0x1;
+		reg_val |= 0x1;
+		writel(reg_val, base + PCIE_AXI_CMD_RCGR);
+	}
+	mdelay(1);
+	reg_val= readl(base + PCIE_AXI_M_CBCR);
+	reg_val |= CLK_ENABLE;
+	writel(reg_val, base + PCIE_AXI_M_CBCR);
+
+	mdelay(1);
+	reg_val = readl(base + PCIE_AXI_S_CBCR);
+	reg_val |= CLK_ENABLE;
+	writel(reg_val, base + PCIE_AXI_S_CBCR);
+
+	mdelay(1);
+	writel(CLK_ENABLE, base + PCIE_AHB_CBCR);
+
+	mdelay(1);
+	writel(CLK_ENABLE, base + PCIE_AUX_CBCR);
+
+	mdelay(1);
+	writel(CLK_ENABLE, base + PCIE_AXI_S_BRIDGE_CBCR);
+
+	mdelay(1);
+	reg_val= readl(base + PCIE_PIPE_CBCR);
+	reg_val |= CLK_ENABLE;
+	writel(reg_val, base + PCIE_PIPE_CBCR);
+	mdelay(1);
+#endif
+	return;
+}
+
+static void pcie_v2_clock_deinit(int lane)
+{
+#ifdef CONFIG_PCI
+	void __iomem *base;
+
+	/*single lane*/
+	if (lane == 1) {
+		base = (void __iomem *)GCC_PCIE1_BOOT_CLOCK_CTL;
+		writel(0x0, GCC_SYS_NOC_PCIE1_AXI_CBCR);
+	} else { /*double lane*/
+		base = (void __iomem *)GCC_PCIE0_BOOT_CLOCK_CTL;
+		writel(0x0, GCC_SYS_NOC_PCIE0_AXI_CBCR);
+	}
+	mdelay (5);
+	writel(0x0, base + PCIE_AHB_CBCR);
+	writel(0x0, base + PCIE_AXI_M_CBCR);
+	writel(0x0, base + PCIE_AXI_S_CBCR);
+	writel(0x0, base + PCIE_AUX_CBCR);
+	writel(0x0, base + PCIE_PIPE_CBCR);
+	writel(0x0, base + PCIE_AXI_S_BRIDGE_CBCR);
+#endif
+	return;
+}
+
+static void pcie_phy_init(u32 reg_base, int mode, int lane)
+{
+	for (int i = 0; i < lane; ++i) {
+	/*set frequency initial value*/
+	writel(0x1cb9, (reg_base + (i * 0x800)) + SSCG_CTRL_REG_4);
+	writel(0x023a, (reg_base + (i * 0x800)) + SSCG_CTRL_REG_5);
+	/*set spectrum spread count*/
+	writel(0x1360, (reg_base + (i * 0x800)) + SSCG_CTRL_REG_3);
+		if (mode == 1) {
+			/*set fstep*/
+			writel(0x0, (reg_base + (i * 0x800)) +
+				SSCG_CTRL_REG_1);
+			writel(0x0, (reg_base + (i * 0x800)) +
+				SSCG_CTRL_REG_2);
+		} else {
+			/*set fstep*/
+			writel(0x1, (reg_base + (i * 0x800)) +
+				SSCG_CTRL_REG_1);
+			writel(0xeb, (reg_base + (i * 0x800)) +
+				SSCG_CTRL_REG_2);
+			/*set FLOOP initial value*/
+			writel(0x3f9, (reg_base + (i * 0x800)) +
+				CDR_CTRL_REG_4);
+			writel(0x1c9, (reg_base + (i * 0x800)) +
+				CDR_CTRL_REG_5);
+			/*set upper boundary level*/
+			writel(0x419, (reg_base + (i * 0x800)) +
+				CDR_CTRL_REG_2);
+			/*set fixed offset*/
+			writel(0x200, (reg_base + (i * 0x800)) +
+				CDR_CTRL_REG_1);
+		}
+	}
+}
+
+static void pcie_reset(int lane)
+{
+	u32 reg_val;
+	void __iomem *base;
+
+	/*single lane*/
+	if (lane == 1)
+		base = (void __iomem *)GCC_PCIE1_BOOT_CLOCK_CTL;
+	else  /*double lane*/
+		base = (void __iomem *)GCC_PCIE0_BOOT_CLOCK_CTL;
+
+	reg_val = readl(base + PCIE_BCR);
+	writel(reg_val | GCC_PCIE_BCR_ENABLE,
+			(base + PCIE_BCR));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCIE_BCR_ENABLE),
+			(base + PCIE_BCR));
+
+	reg_val = readl(base + PCIE_PHY_BCR);
+	writel(reg_val | GCC_PCIE_BLK_ARES,
+			(base + PCIE_PHY_BCR));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCIE_BLK_ARES),
+			(base + PCIE_PHY_BCR));
+
+	reg_val = readl(base + PCIE_PHY_PHY_BCR);
+	writel(reg_val | GCC_PCIE_BLK_ARES,
+			(base + PCIE_PHY_PHY_BCR));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCIE_BLK_ARES),
+			(base + PCIE_PHY_PHY_BCR));
+
+	reg_val = readl(base + PCIE_MISC_RESET);
+	writel(reg_val | GCC_PCIE_PIPE_ARES,
+			(base + PCIE_MISC_RESET));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCIE_PIPE_ARES),
+			(base + PCIE_MISC_RESET));
+
+	reg_val = readl(base + PCIE_MISC_RESET);
+	writel(reg_val | GCC_PCIE_SLEEP_ARES,
+			(base + PCIE_MISC_RESET));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCIE_SLEEP_ARES),
+			(base + PCIE_MISC_RESET));
+
+	reg_val = readl(base + PCIE_MISC_RESET);
+	writel(reg_val | GCC_PCIE_CORE_STICKY_ARES,
+			(base + PCIE_MISC_RESET));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCIE_CORE_STICKY_ARES),
+			(base + PCIE_MISC_RESET));
+
+	reg_val = readl(base + PCIE_MISC_RESET);
+	writel(reg_val | GCC_PCIE_AXI_MASTER_ARES,
+			(base + PCIE_MISC_RESET));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCIE_AXI_MASTER_ARES),
+			(base + PCIE_MISC_RESET));
+
+	reg_val = readl(base + PCIE_MISC_RESET);
+	writel(reg_val | GCC_PCIE_AXI_SLAVE_ARES,
+			(base + PCIE_MISC_RESET));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCIE_AXI_SLAVE_ARES),
+			(base + PCIE_MISC_RESET));
+
+	reg_val = readl(base + PCIE_MISC_RESET);
+	writel(reg_val | GCC_PCIE_AHB_ARES,
+			(base + PCIE_MISC_RESET));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCIE_AHB_ARES),
+			(base + PCIE_MISC_RESET));
+
+	reg_val = readl(base + PCIE_MISC_RESET);
+	writel(reg_val | GCC_PCI_AXI_MASTER_STICKY_ARES,
+			(base + PCIE_MISC_RESET));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCI_AXI_MASTER_STICKY_ARES),
+			(base + PCIE_MISC_RESET));
+
+	reg_val = readl(base + PCIE_MISC_RESET);
+	writel(reg_val | GCC_PCI_AXI_SLAVE_STICKY_ARES,
+			(base + PCIE_MISC_RESET));
+	mdelay(1);
+	writel(reg_val & (~GCC_PCI_AXI_SLAVE_STICKY_ARES),
+			(base + PCIE_MISC_RESET));
+}
+
+void board_pci_init(int id)
+{
+	int node, gpio_node, mode = 0;
+	struct fdt_resource pci_phy;
+	char name[16];
+	int err, lane;
+
+	snprintf(name, sizeof(name), "pci%d", id);
+	node = fdt_path_offset(gd->fdt_blob, name);
+	if (node < 0) {
+		printf("Could not find PCI in device tree\n");
+		return;
+	}
+
+	err = fdt_get_named_resource(gd->fdt_blob, node,
+			"reg", "reg-names", "pci_phy",&pci_phy);
+	if (err < 0)
+		return;
+
+	if (!strcmp(fdt_getprop(gd->fdt_blob, node, "mode", NULL), "fixed")){
+		mode = 1;
+	}
+	lane = fdtdec_get_int(gd->fdt_blob, node, "lane", 0);
+
+	gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "pci_gpio");
+	if (gpio_node >= 0)
+		qca_gpio_init(gpio_node);
+
+	pcie_reset(lane);
+	pcie_v2_clock_init(lane);
+	pcie_phy_init(pci_phy.start, mode, lane);
+
+	return;
+}
+
+void board_pci_deinit()
+{
+	int node, gpio_node, i, lane, err;
+	char name[16];
+	struct fdt_resource parf;
+	struct fdt_resource pci_phy;
+
+	for (i = 0; i < PCI_MAX_DEVICES; i++) {
+		snprintf(name, sizeof(name), "pci%d", i);
+		node = fdt_path_offset(gd->fdt_blob, name);
+		if (node < 0) {
+			printf("Could not find PCI in device tree\n");
+			continue;
+		}
+		err = fdt_get_named_resource(gd->fdt_blob, node, "reg", "reg-names", "parf",
+				&parf);
+		writel(0x0, parf.start + 0x358);
+		writel(0x1, parf.start + 0x40);
+		err = fdt_get_named_resource(gd->fdt_blob, node, "reg", "reg-names", "pci_phy",
+				     &pci_phy);
+		if (err < 0)
+			continue;
+
+		writel(0x1, pci_phy.start + 800);
+		writel(0x0, pci_phy.start + 804);
+		gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "pci_gpio");
+		if (gpio_node >= 0)
+			qca_gpio_deinit(gpio_node);
+
+		lane = fdtdec_get_int(gd->fdt_blob, node, "lane", 0);
+		pcie_v2_clock_deinit(lane);
+	}
+
+	return ;
+}
+#endif
+
+void fdt_fixup_qpic(void *blob)
+{
+	int node_off, ret;
+	const char *qpic_node = {"/soc/qpic-nand@79b0000"};
+
+	/* This fixup is for qpic io_macro_clk
+	 * frequency & phase value
+	 */
+	node_off = fdt_path_offset(blob, qpic_node);
+	if (node_off < 0) {
+		printf("%s: QPIC: unable to find node '%s'\n",
+				__func__, qpic_node);
+		return;
+	}
+
+	ret = fdt_setprop_u32(blob, node_off, "qcom,iomacromax_clk", qpic_frequency);
+	if (ret) {
+		printf("%s : Unable to set property 'qcom,iomacromax_clk'\n",__func__);
+		return;
+	}
+
+	ret = fdt_setprop_u32(blob, node_off, "qcom,phase", qpic_phase);
+	if (ret) {
+		printf("%s : Unable to set property 'qcom,phase'\n",__func__);
+		return;
+	}
+}
+
+void fdt_fixup_bt_debug(void *blob)
+{
+	int node, phandle;
+	char node_name[32];
+
+	if ((gd->bd->bi_arch_number == MACH_TYPE_IPQ5018_AP_MP02_1) ||
+		(gd->bd->bi_arch_number == MACH_TYPE_IPQ5018_DB_MP02_1)) {
+		node = fdt_path_offset(blob, "/soc/pinctrl@1000000/btss_pins");
+		if (node >= 0) {
+			phandle = fdtdec_get_int(blob, node, "phandle", 0);
+			snprintf(node_name,
+				sizeof(node_name),
+				"%s%d",
+				"/soc/bt@7000000%pinctrl-0%",
+				phandle);
+			parse_fdt_fixup("/soc/bt@7000000%pinctrl-names%?btss_pins", blob);
+			parse_fdt_fixup(node_name, blob);
+		}
+		parse_fdt_fixup("/soc/mdio@90000/%delete%status", blob);
+		parse_fdt_fixup("/soc/mdio@90000/%status%?disabled", blob);
+	}
+	parse_fdt_fixup("/soc/serial@78b0000/%status%?ok", blob);
+	parse_fdt_fixup("/soc/usb3@8A00000/%delete%device-power-gpio", blob);
+}
+
+#ifdef CONFIG_IPQ_TINY
+void fdt_fixup_art_format(void *blob)
+{
+	int nodeoffset;
+	nodeoffset = fdt_path_offset(blob, "/");
+	fdt_add_subnode(blob, nodeoffset, "compressed_art");
+
+}
+#endif
+
+void run_tzt(void *address)
+{
+	execute_tzt(address);
+}
+
+void fdt_fixup_set_dload_warm_reset(void *blob)
+{
+	int nodeoff, ret;
+	uint32_t setval = 1;
+
+	nodeoff = fdt_path_offset(blob, "/soc/qca,scm_restart_reason");
+	if (nodeoff < 0) {
+		nodeoff = fdt_path_offset(blob, "/qti,scm_restart_reason");
+		if (nodeoff < 0) {
+			printf("fixup_set_dload: unable to find scm_restart_reason node\n");
+			return;
+		}
+	}
+
+	ret = fdt_setprop_u32(blob, nodeoff, "dload_status", setval);
+	if (ret)
+		printf("fixup_set_dload: 'dload_status' not set");
+
+	ret = fdt_setprop_u32(blob, nodeoff, "dload_warm_reset", setval);
+	if (ret)
+		printf("fixup_set_dload: 'dload_warm_reset' not set");
+}
+
+#ifdef CONFIG_SMP_CMD_SUPPORT
+int is_secondary_core_off(unsigned int cpuid)
+{
+	int err;
+
+	err = __invoke_psci_fn_smc(ARM_PSCI_TZ_FN_AFFINITY_INFO, cpuid, 0, 0);
+
+	return err;
+}
+
+void bring_secondary_core_down(unsigned int state)
+{
+	__invoke_psci_fn_smc(ARM_PSCI_TZ_FN_CPU_OFF, state, 0, 0);
+}
+
+int bring_sec_core_up(unsigned int cpuid, unsigned int entry, unsigned int arg)
+{
+	int err;
+
+	err = __invoke_psci_fn_smc(ARM_PSCI_TZ_FN_CPU_ON, cpuid, entry, arg);
+	if (err) {
+		printf("Enabling CPU%d via psci failed!\n", cpuid);
+		return -1;
+	}
+
+	printf("Enabled CPU%d via psci successfully!\n", cpuid);
+	return 0;
+}
+#endif
+
+int get_soc_hw_version(void)
+{
+	return readl(TCSR_SOC_HW_VERSION_REG);
+}
+
+void sdi_disable(void)
+{
+	qca_scm_sdi();
+}
diff --git a/board/qca/arm/ipq5018/ipq5018.h b/board/qca/arm/ipq5018/ipq5018.h
new file mode 100644
index 0000000..b6e5c0f
--- /dev/null
+++ b/board/qca/arm/ipq5018/ipq5018.h
@@ -0,0 +1,647 @@
+/*
+* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _IPQ5018_CDP_H_
+#define _IPQ5018_CDP_H_
+
+#include <configs/ipq5018.h>
+#include <asm/u-boot.h>
+#include <asm/arch-qca-common/qca_common.h>
+#include "phy.h"
+
+/*
+ * Eud register
+ */
+#define EUD_EUD_EN2				0x0005A000
+
+#define MSM_SDC1_BASE				0x7800000
+#define MSM_SDC1_SDHCI_BASE			0x7804000
+
+#define GCC_MDIO0_BASE				0x1858000
+#define GCC_GMAC_CFG_RCGR			0x01868084
+#define GCC_GMAC_CMD_RCGR			0x01868080
+#define GCC_GMAC_BASE				0x01868000
+
+
+#define GCC_GMAC_CFG_RCGR_SRC_SEL_MASK		0x700
+#define GCC_GMAC0_RX_SRC_SEL_GEPHY_TX		0x200
+#define GCC_GMAC0_TX_SRC_SEL_GEPHY_TX		0x100
+#define GCC_GMAC1_RX_SRC_SEL_UNIPHY_RX		0x100
+#define GCC_GMAC1_TX_SRC_SEL_UNIPHY_TX		0x100
+#define CMN_PLL_PLL_LOCKED_REG			0x9B064
+#define CMN_PLL_PLL_LOCKED_SIZE			0x4
+#define CMN_PLL_LOCKED				0x4
+
+/*
+ * CMN BLK clock
+ */
+#define GCC_CMN_BLK_AHB_CBCR			0x01856308
+#define GCC_CMN_BLK_SYS_CBCR			0x0185630C
+#define CMN_BLK_ADDR				0x0009B780
+#define CMN_BLK_SIZE				0x100
+#define FREQUENCY_MASK				0xfffffdf0
+#define INTERNAL_48MHZ_CLOCK    		0x7
+
+#define CMN_BLK_PLL_SRC_ADDR			0x0009B028
+#define PLL_CTRL_SRC_MASK			0xfffffcff
+#define PLL_REFCLK_DIV_MASK			0xfffffe0f
+#define PLL_REFCLK_DIV_2			0x20
+#define CMN_BLK_PLL_SRC_SEL_FROM_REG		0x0
+#define CMN_BLK_PLL_SRC_SEL_FROM_LOGIC		0x1
+#define CMN_BLK_PLL_SRC_SEL_FROM_PCS		0x2
+#define TCSR_ETH_LDO_RDY_REG			0x19475C4
+#define TCSR_ETH_LDO_RDY_SIZE			0x4
+#define ETH_LDO_RDY				0x1
+
+/*
+ * GEPHY Block Register
+ */
+#define GCC_GEPHY_BCR				0x01856000
+#define GCC_GEPHY_MISC				0x01856004
+#define GCC_GEPHY_RX_CBCR			0x01856010
+#define GCC_GEPHY_TX_CBCR			0x01856014
+#define GCC_GEPHY_BCR_BLK_ARES			0x1
+#define GCC_GEPHY_MISC_ARES			0xf
+
+/*
+ * UNIPHY Block Register
+ */
+#define GCC_UNIPHY_BCR				0x01856100
+#define GCC_UNIPHY_AHB_CBCR			0x01856108
+#define GCC_UNIPHY_SYS_CBCR			0x0185610C
+#define GCC_UNIPHY_BCR_BLK_ARES			0x1
+#define GCC_UNIPHY_MISC_ARES			0x32
+#define GCC_UNIPHY_RX_CBCR			0x01856110
+#define GCC_UNIPHY_TX_CBCR			0x01856114
+
+/* GMAC0 GCC clock */
+#define GCC_GMAC0_RX_CMD_RCGR			0x01868020
+#define GCC_GMAC0_RX_CFG_RCGR			0x01868024
+#define GCC_GMAC0_TX_CMD_RCGR			0x01868028
+#define GCC_GMAC0_TX_CFG_RCGR			0x0186802C
+#define GCC_GMAC0_RX_MISC			0x01868420
+#define GCC_GMAC0_TX_MISC			0x01868424
+#define GCC_GMAC0_MISC				0x01868428
+#define GCC_GMAC0_BCR				0x01819000
+#define GCC_SNOC_GMAC0_AXI_CBCR			0x01826084
+#define GCC_SNOC_GMAC0_AHB_CBCR			0x018260A0
+#define GCC_GMAC0_PTP_CBCR			0x01868300
+#define GCC_GMAC0_CFG_CBCR			0x01868304
+#define GCC_GMAC0_SYS_CBCR			0x01868190
+#define GCC_GMAC0_RX_CBCR			0x01868240
+#define GCC_GMAC0_TX_CBCR			0x01868244
+#define GCC_GMAC0_BCR_BLK_ARES			0x1
+
+/* GMAC1 GCC Clock */
+#define GCC_GMAC1_RX_CMD_RCGR			0x01868030
+#define GCC_GMAC1_RX_CFG_RCGR			0x01868034
+#define GCC_GMAC1_TX_CMD_RCGR			0x01868038
+#define GCC_GMAC1_TX_CFG_RCGR			0x0186803C
+#define GCC_GMAC1_RX_MISC			0x01868430
+#define GCC_GMAC1_TX_MISC			0x01868434
+#define GCC_GMAC1_MISC				0x01868438
+#define GCC_GMAC1_BCR				0x01819100
+#define GCC_SNOC_GMAC1_AXI_CBCR			0x01826088
+#define GCC_SNOC_GMAC1_AHB_CBCR			0x018260A4
+#define GCC_GMAC1_SYS_CBCR			0x01868310
+#define GCC_GMAC1_PTP_CBCR			0x01868320
+#define GCC_GMAC1_CFG_CBCR			0x01868324
+#define GCC_GMAC1_RX_CBCR			0x01868248
+#define GCC_GMAC1_TX_CBCR			0x0186824C
+#define GCC_GMAC1_BCR_BLK_ARES			0x1
+
+#define GCC_CBCR_CLK_ENABLE			0x1
+
+/*
+ * GCC-SDCC Registers
+ */
+
+#define GCC_SDCC1_BCR			0x01842000
+#define GCC_SDCC1_APPS_CMD_RCGR		0x01842004
+#define GCC_SDCC1_APPS_CFG_RCGR		0x01842008
+#define GCC_SDCC1_APPS_M		0x0184200C
+#define GCC_SDCC1_APPS_N		0x01842010
+#define GCC_SDCC1_APPS_D		0x01842014
+#define GCC_SDCC1_APPS_CBCR		0x01842018
+#define GCC_SDCC1_AHB_CBCR		0x0184201C
+
+/*
+ * GCC-QPIC Registers
+ */
+#define GCC_QPIC_IO_MACRO_CBCR          0x0185701C
+#define GCC_QPIC_CBCR_ADDR		0x01857020
+#define GCC_QPIC_AHB_CBCR_ADDR		0x01857024
+#define GCC_QPIC_SLEEP_CBCR		0x01857028
+#define QPIC_CBCR_VAL			0x80004FF1
+#define GCC_QPIC_IO_MACRO_CMD_RCGR     0x01857010
+#define GCC_QPIC_IO_MACRO_CFG_RCGR     0x01857014
+#define IO_MACRO_CLK_320_MHZ		320000000
+#define IO_MACRO_CLK_266_MHZ		266000000
+#define IO_MACRO_CLK_228_MHZ		228000000
+#define IO_MACRO_CLK_200_MHZ		200000000
+#define IO_MACRO_CLK_100_MHZ		100000000
+#define IO_MACRO_CLK_24MHZ		24000000
+#define QPIC_IO_MACRO_CLK       	0
+#define QPIC_CORE_CLK           	1
+#define XO_CLK_SRC			2
+#define GPLL0_CLK_SRC			3
+#define FB_CLK_BIT			(1 << 4)
+#define UPDATE_EN			0x1
+
+/* UART 1 */
+#define GCC_BLSP1_UART1_BCR               0x01802038
+#define GCC_BLSP1_UART1_APPS_CBCR         0x0180203C
+#define GCC_BLSP1_UART1_APPS_CMD_RCGR     0x01802044
+#define GCC_BLSP1_UART1_APPS_CFG_RCGR     0x01802048
+#define GCC_BLSP1_UART1_APPS_M            0x0180204C
+#define GCC_BLSP1_UART1_APPS_N            0x01802050
+#define GCC_BLSP1_UART1_APPS_D            0x01802054
+
+/* UART 2 */
+#define GCC_BLSP1_UART2_BCR               0x01803028
+#define GCC_BLSP1_UART2_APPS_CBCR         0x0180302C
+#define GCC_BLSP1_UART2_APPS_CMD_RCGR     0x01803034
+#define GCC_BLSP1_UART2_APPS_CFG_RCGR     0x01803038
+#define GCC_BLSP1_UART2_APPS_M            0x0180303C
+#define GCC_BLSP1_UART2_APPS_N            0x01803040
+#define GCC_BLSP1_UART2_APPS_D            0x01803044
+
+#define GCC_UART_CFG_RCGR_MODE_MASK       0x3000
+#define GCC_UART_CFG_RCGR_SRCSEL_MASK     0x0700
+#define GCC_UART_CFG_RCGR_SRCDIV_MASK     0x001F
+
+#define GCC_UART_CFG_RCGR_MODE_SHIFT      12
+#define GCC_UART_CFG_RCGR_SRCSEL_SHIFT    8
+#define GCC_UART_CFG_RCGR_SRCDIV_SHIFT    0
+
+#define UART1_RCGR_SRC_SEL			0x1
+#define UART1_RCGR_SRC_DIV			0x0
+#define UART1_RCGR_MODE				0x2
+#define UART1_CMD_RCGR_UPDATE			0x1
+#define UART1_CMD_RCGR_ROOT_EN			0x2
+#define UART1_CBCR_CLK_ENABLE			0x1
+
+/* USB Registers */
+#define GCC_SYS_NOC_USB0_AXI_CBCR		0x1826040
+
+#define TCSR_USB_PCIE_SEL			0x01947540
+
+#define GCC_USB0_MASTER_CBCR			0x183E000
+#define GCC_USB0_SLEEP_CBCR			0x183E004
+#define GCC_USB0_MOCK_UTMI_CBCR			0x183E008
+#define GCC_USB0_MASTER_CMD_RCGR		0x183E00C
+#define GCC_USB0_MASTER_CFG_RCGR		0x183E010
+#define GCC_USB0_MASTER_M			0x183E014
+#define GCC_USB0_MASTER_N			0x183E018
+#define GCC_USB0_MASTER_D			0x183E01C
+#define GCC_USB0_MOCK_UTMI_CMD_RCGR		0x183E020
+#define GCC_USB0_MOCK_UTMI_CFG_RCGR		0x183E024
+#define GCC_USB0_MOCK_UTMI_M			0x183E028
+#define GCC_USB0_MOCK_UTMI_N			0x183E02C
+#define GCC_USB0_MOCK_UTMI_D			0x183E030
+#define GCC_USB0_PHY_BCR			0x183E034
+#define GCC_USB0_PIPE_CBCR			0x183E040
+#define GCC_USB0_AUX_CBCR			0x183E044
+#define GCC_USB0_PHY_PIPE_MISC			0x183E048
+#define GCC_USB0_EUD_AT_CBCR			0x183E04C
+#define GCC_USB0_LFPS_CBCR			0x183E050
+#define GCC_USB0_AUX_CMD_RCGR			0x183E05C
+#define GCC_USB0_AUX_CFG_RCGR			0x183E060
+#define GCC_USB0_BCR				0x183E070
+#define GCC_USB0_PHY_CFG_AHB_CBCR		0x183E080
+#define GCC_USB0_LFPS_CMD_RCGR			0x183E090
+#define GCC_USB0_LFPS_CFG_RCGR			0x183E094
+#define GCC_USB0_LFPS_M				0x183E098
+#define GCC_USB0_LFPS_N				0x183E09C
+#define GCC_USB0_LFPS_D				0x183E0A0
+
+#define GCC_USB_0_BOOT_CLOCK_CTL		0x1840000
+#define GCC_QUSB2_0_PHY_BCR			0x1841030
+
+#define USB30_GENERAL_CFG			0x8AF8808
+#define USB30_GUCTL				0x8A0C12C
+#define USB30_FLADJ				0x8A0C630
+#define GUCTL					0x700C12C
+#define FLADJ					0x700C630
+
+#define PIPE_UTMI_CLK_SEL			0x1
+#define PIPE3_PHYSTATUS_SW			(0x1 << 3)
+#define PIPE_UTMI_CLK_DIS			(0x1 << 8)
+
+#define QUSB2PHY_BASE				0x5b000
+
+#define GCC_USB0_LFPS_CFG_SRC_SEL		(0x1 << 8)
+#define GCC_USB0_LFPS_CFG_SRC_DIV		(0x1f << 0)
+#define LFPS_M					0x1
+#define LFPS_N					0xfe
+#define LFPS_D					0xfd
+#define GCC_USB0_LFPS_MODE			(0x2 << 12)
+
+#define GCC_USB0_AUX_CFG_MODE_DUAL_EDGE 	(2 << 12)
+#define GCC_USB0_AUX_CFG_SRC_SEL		(0 << 8)
+#define GCC_USB0_AUX_CFG_SRC_DIV		(0x17 << 0)
+
+#define AUX_M					0x0
+#define AUX_N					0x0
+#define AUX_D					0x0
+
+#define SW_COLLAPSE_ENABLE			(1 << 0)
+#define SW_OVERRIDE_ENABLE			(1 << 2)
+
+
+#define GCC_USB0_MASTER_CFG_RCGR_SRC_SEL	(1 << 8)
+#define GCC_USB0_MASTER_CFG_RCGR_SRC_DIV	(0x7 << 0)
+
+#define GCC_USB_MOCK_UTMI_SRC_SEL		(1 << 8)
+#define GCC_USB_MOCK_UTMI_SRC_DIV		(0x13 << 0)
+#define GCC_USB_MOCK_UTMI_CLK_DIV		(0x1 << 16)
+
+#define GCC_QUSB2_1_PHY_BCR			0x1841040
+
+#define USB3PHY_APB_BASE			0x5d000
+
+#define USB3_PHY_POWER_DOWN_CONTROL		0x804
+#define QSERDES_COM_SYSCLK_EN_SEL		0xac
+#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN		0x34
+#define QSERDES_COM_CLK_SELECT			0x174
+#define QSERDES_COM_BG_TRIM			0x70
+#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN	0x440
+#define QSERDES_COM_SVS_MODE_CLK_SEL		0x19c
+#define QSERDES_COM_HSCLK_SEL			0x178
+#define QSERDES_COM_CMN_CONFIG			0x194
+#define QSERDES_COM_PLL_IVCO			0x048
+#define QSERDES_COM_SYS_CLK_CTRL		0x3c
+#define QSERDES_COM_DEC_START_MODE0		0xd0
+#define QSERDES_COM_DIV_FRAC_START1_MODE0	0xdc
+#define QSERDES_COM_DIV_FRAC_START2_MODE0	0xe0
+#define QSERDES_COM_DIV_FRAC_START3_MODE0	0xe4
+#define QSERDES_COM_CP_CTRL_MODE0		0x78
+#define QSERDES_COM_PLL_RCTRL_MODE0		0x84
+#define QSERDES_COM_PLL_CCTRL_MODE0		0x90
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0	0x108
+#define QSERDES_COM_LOCK_CMP1_MODE0		0x4c
+#define QSERDES_COM_LOCK_CMP2_MODE0		0x50
+#define QSERDES_COM_LOCK_CMP3_MODE0		0x54
+#define QSERDES_COM_CORE_CLK_EN			0x18c
+#define QSERDES_COM_LOCK_CMP_CFG		0xcc
+#define QSERDES_COM_VCO_TUNE_MAP		0x128
+#define QSERDES_COM_BG_TIMER			0x0c
+#define QSERDES_COM_SSC_EN_CENTER		0x10
+#define QSERDES_COM_SSC_PER1			0x1c
+#define QSERDES_COM_SSC_PER2			0x20
+#define QSERDES_COM_SSC_ADJ_PER1		0x14
+#define QSERDES_COM_SSC_ADJ_PER2		0x18
+#define QSERDES_COM_SSC_STEP_SIZE1		0x24
+#define QSERDES_COM_SSC_STEP_SIZE2		0x28
+#define QSERDES_RX_UCDR_SO_GAIN			0x410
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2	0x4d8
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3	0x4dc
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4	0x4e0
+#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL	0x508
+#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2	0x50c
+#define QSERDES_RX_SIGDET_CNTRL			0x514
+#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL	0x51c
+#define QSERDES_RX_SIGDET_ENABLES		0x510
+#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_D	0x268
+#define QSERDES_TX_RCV_DETECT_LVL_2		0x2ac
+#define QSERDES_TX_LANE_MODE			0x294
+#define PCS_TXDEEMPH_M6DB_V0			0x824
+#define PCS_TXDEEMPH_M3P5DB_V0			0x828
+#define PCS_FLL_CNTRL2				0x8c8
+#define PCS_FLL_CNTRL1				0x8c4
+#define PCS_FLL_CNT_VAL_L			0x8cc
+#define PCS_FLL_CNT_VAL_H_TOL			0x8d0
+#define PCS_FLL_MAN_CODE			0x8d4
+#define PCS_LOCK_DETECT_CONFIG1			0x880
+#define PCS_LOCK_DETECT_CONFIG2			0x884
+#define PCS_LOCK_DETECT_CONFIG3			0x888
+#define PCS_POWER_STATE_CONFIG2			0x864
+#define PCS_RXEQTRAINING_WAIT_TIME		0x8b8
+#define PCS_RXEQTRAINING_RUN_TIME		0x8bc
+#define PCS_LFPS_TX_ECSTART_EQTLOCK		0x8b0
+#define PCS_PWRUP_RESET_DLY_TIME_AUXCLK		0x8a0
+#define PCS_TSYNC_RSYNC_TIME			0x88c
+#define PCS_RCVR_DTCT_DLY_P1U2_L		0x870
+#define PCS_RCVR_DTCT_DLY_P1U2_H		0x874
+#define PCS_RCVR_DTCT_DLY_U3_L			0x878
+#define PCS_RCVR_DTCT_DLY_U3_H			0x87c
+#define PCS_RX_SIGDET_LVL			0x9d8
+#define USB3_PCS_TXDEEMPH_M6DB_V0		0x824
+#define USB3_PCS_TXDEEMPH_M3P5DB_V0		0x828
+#define QSERDES_RX_SIGDET_ENABLES		0x510
+#define USB3_PHY_START_CONTROL			0x808
+#define USB3_PHY_SW_RESET			0x800
+
+#define CMD_UPDATE				0x1
+#define ROOT_EN					0x2
+#define CLK_DISABLE				0x0
+#define NOC_HANDSHAKE_FSM_EN			(1 << 15)
+
+#define set_mdelay_clearbits_le32(addr, value, delay)	\
+	 setbits_le32(addr, value);			\
+	 mdelay(delay);					\
+	 clrbits_le32(addr, value);			\
+/*
+ * PCIE Register
+ */
+#define GCC_SYS_NOC_PCIE0_AXI_CBCR		0x01826048
+#define GCC_SYS_NOC_PCIE1_AXI_CBCR		0x0182604C
+
+#define GCC_PCIE_BCR_ENABLE			(1 << 0)
+#define GCC_PCIE_BLK_ARES			(1 << 0)
+#define GCC_PCIE_PIPE_ARES			(1 << 0)
+#define GCC_PCIE_SLEEP_ARES			(1 << 1)
+#define GCC_PCIE_CORE_STICKY_ARES		(1 << 2)
+#define GCC_PCIE_AXI_MASTER_ARES		(1 << 3)
+#define GCC_PCIE_AXI_SLAVE_ARES			(1 << 4)
+#define GCC_PCIE_AHB_ARES			(1 << 5)
+#define GCC_PCI_AXI_MASTER_STICKY_ARES		(1 << 6)
+#define GCC_PCI_AXI_SLAVE_STICKY_ARES		(1 << 7)
+
+#define GCC_PCIE0_BOOT_CLOCK_CTL		0x01875000
+#define GCC_PCIE0_BCR				0x01875004
+#define GCC_PCIE0_AXI_M_CBCR			0x01875008
+#define GCC_PCIE0_AXI_S_CBCR			0x0187500C
+#define GCC_PCIE0_AHB_CBCR			0x01875010
+#define GCC_PCIE0_PHY_PIPE_MISC			0x0187501C
+#define GCC_PCIE0_AUX_CBCR			0x01875014
+#define GCC_PCIE0_PIPE_CBCR			0x01875018
+#define GCC_PCIE0_PHY_PIPE_MISC			0x0187501C
+#define GCC_PCIE0_AUX_CMD_RCGR			0x01875020
+#define GCC_PCIE0_AUX_CFG_RCGR			0x01875024
+#define GCC_PCIE0_PHY_BCR			0x01875038
+#define GCC_PCIE0PHY_PHY_BCR			0x0187503C
+#define GCC_PCIE0_MISC_RESET			0x01875040
+#define GCC_PCIE0_AXI_S_BRIDGE_CBCR		0x01875048
+#define GCC_PCIE0_AXI_CMD_RCGR			0x01875050
+#define GCC_PCIE0_AXI_CFG_RCGR			0x01875054
+#define GCC_PCIE0_LINK_DOWN_BCR			0x018750A8
+#define GCC_PCIE0_AUX_CFG_RCGR_SRC_SEL		(0 << 8)
+#define GCC_PCIE0_AUX_CFG_RCGR_SRC_DIV		0x17
+#define GCC_PCIE0_AXI_CFG_RCGR_SRC_SEL		(2 << 8)
+#define GCC_PCIE0_AXI_CFG_RCGR_SRC_DIV		0x9
+
+
+#define GCC_PCIE1_BOOT_CLOCK_CTL		0x01876000
+#define GCC_PCIE1_BCR				0x01876004
+#define GCC_PCIE1_AXI_M_CBCR			0x01876008
+#define GCC_PCIE1_AXI_S_CBCR			0x0187600C
+#define GCC_PCIE1_AHB_CBCR			0x01876010
+#define GCC_PCIE1_AUX_CBCR			0x01876014
+#define GCC_PCIE1_PIPE_CBCR			0x01876018
+#define GCC_PCIE1_PHY_PIPE_MISC			0x0187601C
+#define GCC_PCIE1_AUX_CMD_RCGR			0x01876020
+#define GCC_PCIE1_AUX_CFG_RCGR			0x01876024
+#define GCC_PCIE1_PHY_BCR			0x01876038
+#define GCC_PCIE1PHY_PHY_BCR			0x0187603C
+#define GCC_PCIE1_MISC_RESET			0x01876040
+#define GCC_PCIE1_LINK_DOWN_BCR			0x01876044
+#define GCC_PCIE1_AXI_S_BRIDGE_CBCR		0x01876048
+#define GCC_PCIE1_AXI_CMD_RCGR			0x01876050
+#define GCC_PCIE1_AXI_CFG_RCGR			0x01876054
+#define GCC_PCIE1_AUX_CFG_RCGR_SRC_SEL		(0 << 8)
+#define GCC_PCIE1_AUX_CFG_RCGR_SRC_DIV		0x17
+#define GCC_PCIE1_AXI_CFG_RCGR_SRC_SEL		(1 << 8)
+#define GCC_PCIE1_AXI_CFG_RCGR_SRC_DIV		0x7
+
+#define PCIE_BCR			0x4
+#define PCIE_AXI_M_CBCR			0x8
+#define PCIE_AXI_S_CBCR			0xC
+#define PCIE_AHB_CBCR			0x10
+#define PCIE_AUX_CBCR			0x14
+#define PCIE_PIPE_CBCR			0x18
+#define PCIE_AUX_CMD_RCGR		0x20
+#define PCIE_AUX_CFG_RCGR		0x24
+#define PCIE_PHY_BCR			0x38
+#define PCIE_PHY_PHY_BCR		0x3c
+#define PCIE_MISC_RESET			0x40
+#define PCIE_AXI_S_BRIDGE_CBCR		0x48
+#define PCIE_AXI_CMD_RCGR		0x50
+#define PCIE_AXI_CFG_RCGR		0x54
+
+#define NOT_2D(two_d)                     (~two_d)
+#define NOT_N_MINUS_M(n,m)                (~(n - m))
+#define CLOCK_UPDATE_TIMEOUT_US           1000
+
+#define KERNEL_AUTH_CMD                   0x13
+#define SCM_CMD_SEC_AUTH		0x15
+
+#define ARM_PSCI_TZ_FN_BASE		0x84000000
+#define ARM_PSCI_TZ_FN(n)		(ARM_PSCI_TZ_FN_BASE + (n))
+
+#define ARM_PSCI_TZ_FN_CPU_OFF		ARM_PSCI_TZ_FN(2)
+#define ARM_PSCI_TZ_FN_CPU_ON		ARM_PSCI_TZ_FN(3)
+#define ARM_PSCI_TZ_FN_AFFINITY_INFO	ARM_PSCI_TZ_FN(4)
+
+#define CLK_ENABLE			0x1
+
+#define SSCG_CTRL_REG_1			0x9c
+#define SSCG_CTRL_REG_2			0xa0
+#define SSCG_CTRL_REG_3			0xa4
+#define SSCG_CTRL_REG_4			0xa8
+#define SSCG_CTRL_REG_5			0xac
+#define SSCG_CTRL_REG_6			0xb0
+#define CDR_CTRL_REG_1                  0x80
+#define CDR_CTRL_REG_2                  0x84
+#define CDR_CTRL_REG_3                  0x88
+#define CDR_CTRL_REG_4                  0x8C
+#define CDR_CTRL_REG_5                  0x90
+#define CDR_CTRL_REG_6                  0x94
+#define CDR_CTRL_REG_7                  0x98
+
+#define USB_PHY_CFG0                    0x94
+#define USB_PHY_UTMI_CTRL5              0x50
+#define USB_PHY_FSEL_SEL                0xB8
+#define USB_PHY_HS_PHY_CTRL_COMMON0     0x54
+#define USB_PHY_REFCLK_CTRL             0xA0
+#define USB_PHY_HS_PHY_CTRL2            0x64
+#define USB_PHY_UTMI_CTRL0              0x3c
+
+#define UTMI_PHY_OVERRIDE_EN           (1 << 1)
+#define POR_EN                         (1 << 1)
+#define FREQ_SEL                       (1 << 0)
+#define COMMONONN                      (1 << 7)
+#define FSEL                           (1 << 4)
+#define RETENABLEN                     (1 << 3)
+#define USB2_SUSPEND_N_SEL             (1 << 3)
+#define USB2_SUSPEND_N                 (1 << 2)
+#define USB2_UTMI_CLK_EN               (1 << 1)
+#define CLKCORE                        (1 << 1)
+#define ATERESET                       ~(1 << 0)
+
+unsigned int __invoke_psci_fn_smc(unsigned int, unsigned int,
+					 unsigned int, unsigned int);
+
+#define S17C_MAX_PORT			4
+
+typedef struct {
+	u32 base;
+	int unit;
+	int phy_addr;
+	int phy_interface_mode;
+	int phy_napa_gpio;
+	int phy_8033_gpio;
+	int phy_type;
+	u32 mac_pwr;
+	int ipq_swith;
+	int phy_external_link;
+	int switch_port_count;
+	int switch_port_phy_address[S17C_MAX_PORT];
+	const char phy_name[MDIO_NAME_LEN];
+} ipq_gmac_board_cfg_t;
+
+extern ipq_gmac_board_cfg_t gmac_cfg[];
+
+static inline int gmac_cfg_is_valid(ipq_gmac_board_cfg_t *cfg)
+{
+	/*
+	* 'cfg' is valid if and only if
+	*      unit number is non-negative and less than CONFIG_IPQ_NO_MACS.
+	*/
+	return ((cfg >= &gmac_cfg[0]) &&
+		(cfg < &gmac_cfg[CONFIG_IPQ_NO_MACS]) &&
+			(cfg->unit >= 0) && (cfg->unit < CONFIG_IPQ_NO_MACS));
+}
+
+extern void ipq_gmac_common_init(ipq_gmac_board_cfg_t *cfg);
+extern int ipq_gmac_init(ipq_gmac_board_cfg_t *cfg);
+
+#ifdef CONFIG_PCI_IPQ
+void board_pci_init(int id);
+#endif
+
+struct smem_ram_ptn {
+	char name[16];
+	unsigned long long start;
+	unsigned long long size;
+
+	/* RAM Partition attribute: READ_ONLY, READWRITE etc.  */
+	unsigned attr;
+
+	/* RAM Partition category: EBI0, EBI1, IRAM, IMEM */
+	unsigned category;
+
+	/* RAM Partition domain: APPS, MODEM, APPS & MODEM (SHARED) etc. */
+	unsigned domain;
+
+	/* RAM Partition type: system, bootloader, appsboot, apps etc. */
+	unsigned type;
+
+	/* reserved for future expansion without changing version number */
+	unsigned reserved2, reserved3, reserved4, reserved5;
+} __attribute__ ((__packed__));
+
+__weak void aquantia_phy_reset_init_done(void) {}
+__weak void aquantia_phy_reset_init(void) {}
+__weak void qgic_init(void) {}
+__weak void handle_noc_err(void) {}
+__weak void board_pcie_clock_init(int id) {}
+
+struct smem_ram_ptable {
+	#define _SMEM_RAM_PTABLE_MAGIC_1	0x9DA5E0A8
+	#define _SMEM_RAM_PTABLE_MAGIC_2	0xAF9EC4E2
+	unsigned magic[2];
+	unsigned version;
+	unsigned reserved1;
+	unsigned len;
+	unsigned buf;
+	struct smem_ram_ptn parts[32];
+} __attribute__ ((__packed__));
+
+int smem_ram_ptable_init(struct smem_ram_ptable *smem_ram_ptable);
+void reset_crashdump(void);
+void reset_board(void);
+void qpic_clk_enbale(void);
+int ipq_get_tz_version(char *version_name, int buf_size);
+void ipq_fdt_fixup_socinfo(void *blob);
+void qpic_set_clk_rate(unsigned int clk_rate, int blk_type,
+		int req_clk_src_type);
+
+extern const char *rsvd_node;
+extern const char *del_node[];
+extern const add_node_t add_fdt_node[];
+
+typedef enum {
+	SMEM_SPINLOCK_ARRAY = 7,
+	SMEM_AARM_PARTITION_TABLE = 9,
+	SMEM_HW_SW_BUILD_ID = 137,
+	SMEM_USABLE_RAM_PARTITION_TABLE = 402,
+	SMEM_POWER_ON_STATUS_INFO = 403,
+	SMEM_MACHID_INFO_LOCATION = 425,
+	SMEM_IMAGE_VERSION_TABLE = 469,
+	SMEM_BOOT_FLASH_TYPE = 498,
+	SMEM_BOOT_FLASH_INDEX = 499,
+	SMEM_BOOT_FLASH_CHIP_SELECT = 500,
+	SMEM_BOOT_FLASH_BLOCK_SIZE = 501,
+	SMEM_BOOT_FLASH_DENSITY = 502,
+	SMEM_BOOT_DUALPARTINFO = 503,
+	SMEM_PARTITION_TABLE_OFFSET = 504,
+	SMEM_SPI_FLASH_ADDR_LEN = 505,
+	SMEM_FIRST_VALID_TYPE = SMEM_SPINLOCK_ARRAY,
+	SMEM_LAST_VALID_TYPE = SMEM_SPI_FLASH_ADDR_LEN,
+	SMEM_MAX_SIZE = SMEM_SPI_FLASH_ADDR_LEN + 1,
+} smem_mem_type_t;
+
+#ifdef CONFIG_IPQ_BT_SUPPORT
+#define NVM_SEGMENT_SIZE 243
+#define TLV_REQ_OPCODE 0xFC00
+#define TLV_COMMAND_REQUEST 0x1E
+#define DATA_REMAINING_LENGTH 2
+#define TLV_RESPONSE_PACKET_SIZE 8
+#define TLV_RESPONSE_STATUS_INDEX 6
+
+#define PACKED_STRUCT __attribute__((__packed__))
+
+#define LE_UNALIGNED(x, y)  \
+{                                        \
+	((u8 *)(x))[0] = ((u8)(((u32)(y)) & 0xFF));            \
+	((u8 *)(x))[1] = ((u8)((((u32)(y)) >> 8) & 0xFF));     \
+}
+
+typedef enum
+{
+	ptHCICommandPacket = 0x01,  /* Simple HCI Command Packet    */
+	ptHCIACLDataPacket = 0x02,  /* HCI ACL Data Packet Type.    */
+	ptHCISCODataPacket = 0x03,  /* HCI SCO Data Packet Type.    */
+	ptHCIeSCODataPacket= 0x03,  /* HCI eSCO Data Packet Type.   */
+	ptHCIEventPacket   = 0x04,  /* HCI Event Packet Type.       */
+	ptHCIAdditional    = 0x05   /* Starting Point for Additional*/
+} HCI_PacketType_t;
+
+typedef struct _tlv_download_req
+{
+	u16 opcode;
+	u8 parameter_total_length;
+	u8 command_request;
+	u8 tlv_segment_length;
+	u8 tlv_segment_data[0];
+
+} PACKED_STRUCT tlv_download_req;
+
+typedef struct _tagHCI_Packet_t
+{
+	u8 HCIPacketType;
+	tlv_download_req HCIPayload;
+} PACKED_STRUCT HCI_Packet_t;
+
+typedef enum {
+	BT_WAIT_FOR_START = 0,
+	BT_WAIT_FOR_TX_COMPLETE = 1,
+	BT_WAIT_FOR_STOP = 2,
+} bt_wait;
+
+#define BT_TIMEOUT_US 500000
+
+int bt_init(void);
+#endif
+#endif /* _IPQ5018_CDP_H_ */
diff --git a/board/qca/arm/ipq6018/clock.c b/board/qca/arm/ipq6018/clock.c
index 92beb06..71497fd 100644
--- a/board/qca/arm/ipq6018/clock.c
+++ b/board/qca/arm/ipq6018/clock.c
@@ -14,6 +14,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch-ipq6018/clk.h>
+#include <asm/errno.h>
 
 #ifdef CONFIG_IPQ6018_I2C
 void i2c_clock_config(void)
@@ -34,3 +35,67 @@
 }
 #endif
 
+static void uart_configure_mux(u8 id)
+{
+	unsigned long cfg_rcgr;
+
+	cfg_rcgr = readl(GCC_BLSP1_UART_APPS_CFG_RCGR(id));
+	/* Clear mode, src sel, src div */
+	cfg_rcgr &= ~(GCC_UART_CFG_RCGR_MODE_MASK |
+			GCC_UART_CFG_RCGR_SRCSEL_MASK |
+			GCC_UART_CFG_RCGR_SRCDIV_MASK);
+
+	cfg_rcgr |= ((UART_RCGR_SRC_SEL << GCC_UART_CFG_RCGR_SRCSEL_SHIFT)
+			& GCC_UART_CFG_RCGR_SRCSEL_MASK);
+
+	cfg_rcgr |= ((UART_RCGR_SRC_DIV << GCC_UART_CFG_RCGR_SRCDIV_SHIFT)
+			& GCC_UART_CFG_RCGR_SRCDIV_MASK);
+
+	cfg_rcgr |= ((UART_RCGR_MODE << GCC_UART_CFG_RCGR_MODE_SHIFT)
+			& GCC_UART_CFG_RCGR_MODE_MASK);
+
+	writel(cfg_rcgr, GCC_BLSP1_UART_APPS_CFG_RCGR(id));
+}
+
+static int uart_trigger_update(u8 id)
+{
+	unsigned long cmd_rcgr;
+	int timeout = 0;
+
+	cmd_rcgr = readl(GCC_BLSP1_UART_APPS_CMD_RCGR(id));
+	cmd_rcgr |= UART_CMD_RCGR_UPDATE;
+	writel(cmd_rcgr, GCC_BLSP1_UART_APPS_CMD_RCGR(id));
+
+	while (readl(GCC_BLSP1_UART_APPS_CMD_RCGR(id)) & UART_CMD_RCGR_UPDATE) {
+		if (timeout++ >= CLOCK_UPDATE_TIMEOUT_US) {
+			printf("Timeout waiting for UART clock update\n");
+			return -ETIMEDOUT;
+		}
+		udelay(1);
+	}
+	cmd_rcgr = readl(GCC_BLSP1_UART_APPS_CMD_RCGR(id));
+	return 0;
+}
+
+int uart_clock_config(struct ipq_serial_platdata *plat)
+{
+	unsigned long cbcr_val;
+	int ret;
+
+	uart_configure_mux(plat->port_id);
+
+	writel(plat->m_value, GCC_BLSP1_UART_APPS_M(plat->port_id));
+	writel(NOT_N_MINUS_M(plat->n_value, plat->m_value),
+				GCC_BLSP1_UART_APPS_N(plat->port_id));
+	writel(NOT_2D(plat->d_value), GCC_BLSP1_UART_APPS_D(plat->port_id));
+
+	ret = uart_trigger_update(plat->port_id);
+	if (ret)
+		return ret;
+
+	cbcr_val = readl(GCC_BLSP1_UART_APPS_CBCR(plat->port_id));
+	cbcr_val |= UART_CBCR_CLK_ENABLE;
+	writel(cbcr_val, GCC_BLSP1_UART_APPS_CBCR(plat->port_id));
+	return 0;
+}
+
diff --git a/board/qca/arm/ipq6018/ipq6018.c b/board/qca/arm/ipq6018/ipq6018.c
index d272a37..dfe61f9 100644
--- a/board/qca/arm/ipq6018/ipq6018.c
+++ b/board/qca/arm/ipq6018/ipq6018.c
@@ -31,6 +31,9 @@
 
 #define DLOAD_MAGIC_COOKIE	0x10
 #define DLOAD_DISABLED		0x40
+
+#define TCSR_SOC_HW_VERSION_REG 0x194D000
+
 DECLARE_GLOBAL_DATA_PTR;
 struct sdhci_host mmc_host;
 extern int ipq6018_edma_init(void *cfg);
@@ -109,99 +112,25 @@
 int dump_entries_s = ARRAY_SIZE(dumpinfo_s);
 u32 *tz_wonce = (u32 *)CONFIG_IPQ6018_TZ_WONCE_4_ADDR;
 
-
-void uart2_configure_mux(void)
-{
-	unsigned long cfg_rcgr;
-
-	cfg_rcgr = readl(GCC_BLSP1_UART2_APPS_CFG_RCGR);
-	/* Clear mode, src sel, src div */
-	cfg_rcgr &= ~(GCC_UART_CFG_RCGR_MODE_MASK |
-			GCC_UART_CFG_RCGR_SRCSEL_MASK |
-			GCC_UART_CFG_RCGR_SRCDIV_MASK);
-
-	cfg_rcgr |= ((UART2_RCGR_SRC_SEL << GCC_UART_CFG_RCGR_SRCSEL_SHIFT)
-			& GCC_UART_CFG_RCGR_SRCSEL_MASK);
-
-	cfg_rcgr |= ((UART2_RCGR_SRC_DIV << GCC_UART_CFG_RCGR_SRCDIV_SHIFT)
-			& GCC_UART_CFG_RCGR_SRCDIV_MASK);
-
-	cfg_rcgr |= ((UART2_RCGR_MODE << GCC_UART_CFG_RCGR_MODE_SHIFT)
-			& GCC_UART_CFG_RCGR_MODE_MASK);
-
-	writel(cfg_rcgr, GCC_BLSP1_UART2_APPS_CFG_RCGR);
-}
-
-void uart2_set_rate_mnd(unsigned int m,
-			unsigned int n, unsigned int two_d)
-{
-	writel(m, GCC_BLSP1_UART2_APPS_M);
-	writel(NOT_N_MINUS_M(n, m), GCC_BLSP1_UART2_APPS_N);
-	writel(NOT_2D(two_d), GCC_BLSP1_UART2_APPS_D);
-}
-
-int uart2_trigger_update(void)
-{
-	unsigned long cmd_rcgr;
-	int timeout = 0;
-
-	cmd_rcgr = readl(GCC_BLSP1_UART2_APPS_CMD_RCGR);
-	cmd_rcgr |= UART2_CMD_RCGR_UPDATE;
-	writel(cmd_rcgr, GCC_BLSP1_UART2_APPS_CMD_RCGR);
-
-	while (readl(GCC_BLSP1_UART2_APPS_CMD_RCGR) & UART2_CMD_RCGR_UPDATE) {
-		if (timeout++ >= CLOCK_UPDATE_TIMEOUT_US) {
-			printf("Timeout waiting for UART2 clock update\n");
-			return -ETIMEDOUT;
-		}
-		udelay(1);
-	}
-	cmd_rcgr = readl(GCC_BLSP1_UART2_APPS_CMD_RCGR);
-	return 0;
-}
-
-void uart2_toggle_clock(void)
-{
-	unsigned long cbcr_val;
-
-	cbcr_val = readl(GCC_BLSP1_UART2_APPS_CBCR);
-	cbcr_val |= UART2_CBCR_CLK_ENABLE;
-	writel(cbcr_val, GCC_BLSP1_UART2_APPS_CBCR);
-}
-
-void uart2_clock_config(unsigned int m,
-			unsigned int n, unsigned int two_d)
-{
-	uart2_configure_mux();
-	uart2_set_rate_mnd(m, n, two_d);
-	uart2_trigger_update();
-	uart2_toggle_clock();
-}
+#define BLSP1_UART0_BASE	0x078AF000
+#define UART_PORT_ID(reg)	((reg - BLSP1_UART0_BASE) / 0x1000)
 
 void qca_serial_init(struct ipq_serial_platdata *plat)
 {
-	int node, uart2_node;
+	int ret;
 
-	writel(1, GCC_BLSP1_UART1_APPS_CBCR);
-
-	node = fdt_path_offset(gd->fdt_blob, "/serial@78B1000/serial_gpio");
-	if (node < 0) {
-		printf("Could not find serial_gpio node\n");
+	if (plat->gpio_node < 0) {
+		printf("serial_init: unable to find gpio node \n");
 		return;
 	}
 
-	if (plat->port_id == 1) {
-		uart2_node = fdt_path_offset(gd->fdt_blob, "uart2");
-		if (uart2_node < 0) {
-			printf("Could not find uart2 node\n");
-			return;
-		}
-		node = fdt_subnode_offset(gd->fdt_blob,
-				uart2_node, "serial_gpio");
-		uart2_clock_config(plat->m_value, plat->n_value, plat->d_value);
-		writel(1, GCC_BLSP1_UART2_APPS_CBCR);
-	}
-	qca_gpio_init(node);
+	qca_gpio_init(plat->gpio_node);
+	plat->port_id = UART_PORT_ID(plat->reg_base);
+	ret = uart_clock_config(plat);
+	if (ret)
+		printf("UART clock config failed %d \n", ret);
+
+	return;
 }
 
 int do_pmic_reset()
@@ -844,11 +773,6 @@
 		printf("%s: invalid param for usb_mode\n", __func__);
 }
 
-void fdt_fixup_set_dload_dis(void *blob)
-{
-	parse_fdt_fixup("/soc/qca,scm_restart_reason%dload_status%1", blob);
-}
-
 void enable_caches(void)
 {
 	qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
@@ -1127,7 +1051,7 @@
 		for (i = 0; i < mdc_mdio_gpio_cnt; i++) {
 			if (mdc_mdio_gpio[i] >=0) {
 				mdc_mdio_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(mdc_mdio_gpio[i]);
-				writel(0x7, mdc_mdio_gpio_base);
+				writel(0xC7, mdc_mdio_gpio_base);
 			}
 		}
 	}
@@ -1397,6 +1321,7 @@
 	switch (machid)
 	{
 		case MACH_TYPE_IPQ6018_AP_CP01_C2:
+		case MACH_TYPE_IPQ6018_AP_CP01_C3:
 			return MACH_TYPE_IPQ6018_AP_CP01_C1;
 		case MACH_TYPE_IPQ6018_AP_CP01_C4:
 			return MACH_TYPE_IPQ6018_AP_CP01_C1;
@@ -1415,6 +1340,9 @@
 		case MACH_TYPE_IPQ6018_AP_CP01_C2:
 			config = "config@cp01-c2";
 			break;
+		case MACH_TYPE_IPQ6018_AP_CP01_C3:
+			config = "config@cp01-c3";
+			break;
 		case MACH_TYPE_IPQ6018_AP_CP01_C4:
 			config = "config@cp01-c4";
 			break;
@@ -1449,3 +1377,8 @@
 	parse_fdt_fixup("/soc/qcom_q6v5_wcss@CD00000%qcom,nosecure%1", blob);
 	parse_fdt_fixup("/soc/qcom_q6v5_wcss@CD00000%qca,wcss-aon-reset-seq%1", blob);
 }
+
+int get_soc_hw_version(void)
+{
+	return readl(TCSR_SOC_HW_VERSION_REG);
+}
diff --git a/board/qca/arm/ipq6018/ipq6018.h b/board/qca/arm/ipq6018/ipq6018.h
index 85cb3f7..c02fb9b 100644
--- a/board/qca/arm/ipq6018/ipq6018.h
+++ b/board/qca/arm/ipq6018/ipq6018.h
@@ -59,35 +59,9 @@
 #define SDCC1_N_VAL		0xFC
 #define SDCC1_D_VAL		0xFD
 
-#define GCC_BLSP1_UART1_APPS_CBCR       0x0180203c
 #define GCC_SDCC1_BCR		0x01842000
 #define GCC_SDCC1_AHB_CBCR	0x0184201C
 
-#define GCC_BLSP1_UART2_APPS_CFG_RCGR	0x01803038
-#define GCC_BLSP1_UART2_APPS_M		0x0180303C
-#define GCC_BLSP1_UART2_APPS_N		0x01803040
-#define GCC_BLSP1_UART2_APPS_D		0x01803044
-#define GCC_BLSP1_UART2_APPS_CMD_RCGR	0x01803034
-#define GCC_BLSP1_UART2_APPS_CBCR	0x0180302C
-
-#define GCC_UART_CFG_RCGR_MODE_MASK	0x3000
-#define GCC_UART_CFG_RCGR_SRCSEL_MASK	0x0700
-#define GCC_UART_CFG_RCGR_SRCDIV_MASK	0x001F
-
-#define GCC_UART_CFG_RCGR_MODE_SHIFT	12
-#define GCC_UART_CFG_RCGR_SRCSEL_SHIFT	8
-#define GCC_UART_CFG_RCGR_SRCDIV_SHIFT	0
-
-#define UART2_RCGR_SRC_SEL	0x1
-#define UART2_RCGR_SRC_DIV	0x0
-#define UART2_RCGR_MODE		0x2
-#define UART2_CMD_RCGR_UPDATE	0x1
-#define UART2_CBCR_CLK_ENABLE	0x1
-
-#define NOT_2D(two_d)		(~two_d)
-#define NOT_N_MINUS_M(n,m)	(~(n - m))
-#define CLOCK_UPDATE_TIMEOUT_US	1000
-
 #define CLOCK_UPDATE_TIMEOUT_US	1000
 #define KERNEL_AUTH_CMD		0x1E
 #define SCM_CMD_SEC_AUTH	0x1F
diff --git a/board/qca/arm/ipq807x/ipq807x.c b/board/qca/arm/ipq807x/ipq807x.c
index 713d221..a47aef1 100644
--- a/board/qca/arm/ipq807x/ipq807x.c
+++ b/board/qca/arm/ipq807x/ipq807x.c
@@ -59,6 +59,9 @@
 #define NOC_ERR_CLR_REG		0xb0002a0
 
 #define DLOAD_MAGIC_COOKIE	0x10
+
+#define TCSR_SOC_HW_VERSION_REG 0x194D000
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #define GCNT_PSHOLD             0x004AB000
@@ -1259,6 +1262,66 @@
 }
 #endif
 
+unsigned int get_dts_machid(unsigned int machid)
+{
+	switch (machid)
+	{
+		case MACH_TYPE_IPQ807x_AP_HK01_C3:
+		case MACH_TYPE_IPQ807x_AP_HK01_C6:
+		case MACH_TYPE_IPQ807x_AP_OAK03:
+			return MACH_TYPE_IPQ807x_AP_HK01_C1;
+		case MACH_TYPE_IPQ807x_AP_AC02:
+			return MACH_TYPE_IPQ807x_AP_AC01;
+		case MACH_TYPE_IPQ807x_AP_HK12_C1:
+			return MACH_TYPE_IPQ807x_AP_HK10_C2;
+		default:
+			return machid;
+	}
+}
+
+void ipq_uboot_fdt_fixup(void)
+{
+	int ret, len;
+	char *config = NULL;
+
+	switch (gd->bd->bi_arch_number)
+	{
+		case MACH_TYPE_IPQ807x_AP_HK01_C3:
+			config = "config@hk01.c3";
+			break;
+		case MACH_TYPE_IPQ807x_AP_HK01_C6:
+			config = "config@hk01.c6";
+			break;
+		case MACH_TYPE_IPQ807x_AP_HK12_C1:
+			config = "config@hk12";
+			break;
+		case MACH_TYPE_IPQ807x_AP_AC02:
+			config = "config@ac02";
+			break;
+		case MACH_TYPE_IPQ807x_AP_OAK03:
+			config = "config@oak03";
+			break;
+	}
+
+	if (config != NULL)
+	{
+		len = fdt_totalsize(gd->fdt_blob) + strlen(config) + 1;
+
+		/*
+		 * Open in place with a new length.
+		*/
+		ret = fdt_open_into(gd->fdt_blob, (void *)gd->fdt_blob, len);
+		if (ret)
+			 printf("uboot-fdt-fixup: Cannot expand FDT: %s\n", fdt_strerror(ret));
+
+		ret = fdt_setprop((void *)gd->fdt_blob, 0, "config_name",
+				config, (strlen(config)+1));
+		if (ret)
+			printf("uboot-fdt-fixup: unable to set config_name(%d)\n", ret);
+	}
+	return;
+}
+
 void ipq_fdt_fixup_socinfo(void *blob)
 {
 	uint32_t cpu_type;
@@ -1551,15 +1614,17 @@
 void fdt_fixup_set_dload_warm_reset(void *blob)
 {
 	int nodeoff, ret;
-	const char *dload_node = {"/soc/qca,scm_restart_reason"};
 	uint32_t setval = 1;
 
-	nodeoff = fdt_path_offset(blob, dload_node);
+	nodeoff = fdt_path_offset(blob, "/soc/qca,scm_restart_reason");
 	if (nodeoff < 0) {
-		printf("fixup_set_dload: unable to find node '%s'\n",
-		       dload_node);
-		return;
+		nodeoff = fdt_path_offset(blob, "/qti,scm_restart_reason");
+		if (nodeoff < 0) {
+			printf("fixup_set_dload: unable to find scm_restart_reason node\n");
+			return;
+		}
 	}
+
 	ret = fdt_setprop_u32(blob, nodeoff, "dload_status", setval);
 	if (ret)
 		printf("fixup_set_dload: 'dload_status' not set");
@@ -1725,20 +1790,6 @@
 	execute_tzt(address);
 }
 
-void set_platform_specific_default_env(void)
-{
-	uint32_t soc_ver_major, soc_ver_minor, soc_version;
-	int ret;
-
-	ret = ipq_smem_get_socinfo_version((uint32_t *)&soc_version);
-	if (!ret) {
-		soc_ver_major = SOCINFO_VERSION_MAJOR(soc_version);
-		soc_ver_minor = SOCINFO_VERSION_MINOR(soc_version);
-		setenv_ulong("soc_version_major", (unsigned long)soc_ver_major);
-		setenv_ulong("soc_version_minor", (unsigned long)soc_ver_minor);
-	}
-}
-
 void sdi_disable(void)
 {
 	qca_scm_sdi();
@@ -1819,3 +1870,8 @@
 	qgic_dist_init();
 	qgic_cpu_init();
 }
+
+int get_soc_hw_version(void)
+{
+	return readl(TCSR_SOC_HW_VERSION_REG);
+}
diff --git a/common/board_f.c b/common/board_f.c
index 9c2e1aa..26b1e64 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -842,12 +842,15 @@
 #endif
 	setup_mon_len,
 #ifdef CONFIG_OF_CONTROL
+#ifdef CONFIG_COMPRESSED_DTB_BASE
+	initf_pre_malloc,
+#endif
 	fdtdec_setup,
 #endif
+	initf_malloc,
 #ifdef CONFIG_TRACE
 	trace_early_init,
 #endif
-	initf_malloc,
 	initf_console_record,
 #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
 	/* TODO: can this go into arch_cpu_init()? */
diff --git a/common/cmd_aes.c b/common/cmd_aes.c
index 76da3ef..6ae6ecd 100644
--- a/common/cmd_aes.c
+++ b/common/cmd_aes.c
@@ -13,9 +13,149 @@
 #include <malloc.h>
 #include <asm/byteorder.h>
 #include <linux/compiler.h>
+#include <asm/arch-qca-common/scm.h>
+#include <errno.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifdef CONFIG_CMD_AES_256
+enum tz_crypto_service_aes_cmd_t {
+	TZ_CRYPTO_SERVICE_AES_ENC_ID = 0x7,
+	TZ_CRYPTO_SERVICE_AES_DEC_ID = 0x8,
+};
+
+enum tz_crypto_service_aes_type_t {
+	TZ_CRYPTO_SERVICE_AES_SHK = 0x1,
+	TZ_CRYPTO_SERVICE_AES_PHK = 0x2,
+	TZ_CRYPTO_SERVICE_AES_TYPE_MAX,
+
+};
+
+enum tz_crypto_service_aes_mode_t {
+       TZ_CRYPTO_SERVICE_AES_ECB = 0x0,
+       TZ_CRYPTO_SERVICE_AES_CBC = 0x1,
+	TZ_CRYPTO_SERVICE_AES_MODE_MAX,
+};
+
+struct crypto_aes_req_data_t {
+	uint64_t type;
+	uint64_t mode;
+        uint64_t req_buf;
+        uint64_t req_len;
+        uint64_t ivdata;
+        uint64_t iv_len;
+        uint64_t resp_buf;
+        uint64_t resp_len;
+};
+
+/**
+ * do_aes_256() - Handle the "aes" command-line command
+ * @cmdtp:	Command data struct pointer
+ * @flag:	Command flag
+ * @argc:	Command-line argument count
+ * @argv:	Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_aes_256(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	uint64_t src_addr, dst_addr, ivdata;
+	uint64_t req_len, iv_len, resp_len, type, mode;
+	struct crypto_aes_req_data_t *req_ptr = NULL;
+	int cmd_id = -1;
+	int ret = CMD_RET_USAGE;
+
+	if (argc != 10)
+		return ret;
+
+	if (!strncmp(argv[1], "enc", 3))
+		cmd_id = TZ_CRYPTO_SERVICE_AES_ENC_ID;
+	else if (!strncmp(argv[1], "dec", 3))
+		cmd_id = TZ_CRYPTO_SERVICE_AES_DEC_ID;
+	else
+		return ret;
+
+	type = simple_strtoul(argv[2], NULL, 16);
+	if (type >= TZ_CRYPTO_SERVICE_AES_TYPE_MAX) {
+		printf("unkown type specified, use 0x1 - SHK, 0x2 - PHK\n");
+		goto err;
+	}
+
+	mode = simple_strtoul(argv[3], NULL, 16);
+        if (mode >= TZ_CRYPTO_SERVICE_AES_MODE_MAX) {
+                printf("unkown mode specified, use 0x0 - ECB, 0x1 - CBC\n");
+                goto err;
+        }
+
+	src_addr = simple_strtoull(argv[4], NULL, 16);
+	req_len = simple_strtoul(argv[5], NULL, 16);
+	if (req_len <= 0 || (req_len % 16) != 0) {
+		printf("Invalid request buffer length, length "
+			"should be multiple of AES block size (16)\n");
+		goto err;
+	}
+
+	ivdata = simple_strtoull(argv[6], NULL, 16);
+	iv_len = simple_strtoul(argv[7], NULL, 16);
+	if (iv_len != 16) {
+		printf("Error: iv length should be equal to AES block size (16)\n");
+		goto err;
+	}
+
+	dst_addr = simple_strtoull(argv[8], NULL, 16);
+	resp_len =  simple_strtoul(argv[9], NULL, 16);
+	if (resp_len < req_len) {
+		printf("Error: response buffer cannot be less then request buffer\n");
+		goto err;
+	}
+
+	req_ptr = (struct crypto_aes_req_data_t *)memalign(ARCH_DMA_MINALIGN,
+					sizeof(struct crypto_aes_req_data_t));
+	if (!req_ptr) {
+		printf("Error allocating memory");
+		return -ENOMEM;
+	}
+
+	req_ptr->type = type;
+	req_ptr->mode = mode;
+	req_ptr->req_buf = (uint64_t)src_addr;
+	req_ptr->req_len = req_len;
+	req_ptr->ivdata = (mode == TZ_CRYPTO_SERVICE_AES_CBC) ? (uint64_t)ivdata : 0;
+	req_ptr->iv_len = iv_len;
+	req_ptr->resp_buf = (uint64_t)dst_addr;
+	req_ptr->resp_len = resp_len;
+	ret = qca_scm_crypto(cmd_id, (void *)req_ptr,
+					sizeof(struct crypto_aes_req_data_t));
+
+	if (req_ptr)
+		free(req_ptr);
+
+	if (ret) {
+		printf("Scm call failed with error code: %d\n", ret);
+		return ret;
+	}
+	return 0;
+
+err:
+	if (req_ptr)
+		free(req_ptr);
+	return CMD_RET_USAGE;
+}
+
+/***************************************************/
+U_BOOT_CMD(
+	aes_256, 10, 1, do_aes_256,
+	"AES 256 CBC/ECB encryption/decryption",
+	"Encryption: echo enc <type> <mode> <plain data address> <plain data len>"
+	"<iv data address> <iv len> <response buf address> <response buf len>"
+	"Decryption: echo dec <type> <mode> <Encrypted buf address> <encrypted"
+	"buf len> <iv data address> <iv len> <response buf address> <response buf len>"
+);
+#endif
+
+
+#ifdef CONFIG_CMD_AES_128
 /**
  * do_aes() - Handle the "aes" command-line command
  * @cmdtp:	Command data struct pointer
@@ -87,3 +227,4 @@
 	"AES 128 CBC encryption",
 	aes_help_text
 );
+#endif
diff --git a/common/cmd_flashwrite.c b/common/cmd_flashwrite.c
index 6e2be1a..50aeb3d 100644
--- a/common/cmd_flashwrite.c
+++ b/common/cmd_flashwrite.c
@@ -202,8 +202,9 @@
 #endif
 	disk_partition_t disk_info = {0};
 	qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
+#ifdef CONFIG_CMD_NAND
 	nand_info_t *nand = &nand_info[CONFIG_NAND_FLASH_INFO_IDX];
-
+#endif
 	if (strcmp(argv[0], "flash") == 0)
 		flash_cmd = 1;
 
@@ -350,7 +351,7 @@
 	}
 
 	if (flash_cmd) {
-
+#ifdef CONFIG_CMD_NAND
 		if (((flash_type == SMEM_BOOT_NAND_FLASH) ||
 			(flash_type == SMEM_BOOT_QSPI_NAND_FLASH))) {
 
@@ -358,7 +359,7 @@
 			if (adj_size)
 				file_size = file_size + (nand->writesize - adj_size);
 		}
-
+#endif
 		if (flash_type == SMEM_BOOT_MMC_FLASH) {
 
 			if (disk_info.blksz) {
diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c
index 380db53..ca7c9fc 100644
--- a/common/cmd_mtdparts.c
+++ b/common/cmd_mtdparts.c
@@ -809,6 +809,27 @@
 		index_partitions();
 }
 
+#ifdef CONFIG_IPQ_TINY
+int parse_nor_partition(const char *const partdef,
+			const char **ret, struct part_info **retpart)
+{
+	return  part_parse(partdef, ret, retpart);
+}
+
+void free_parse(struct list_head *head)
+{
+	struct list_head *entry, *n;
+	struct part_info *dev_tmp;
+
+	/* clean devices list */
+	list_for_each_safe(entry, n, head) {
+		dev_tmp = list_entry(entry, struct part_info, link);
+		list_del(entry);
+		free(dev_tmp);
+	}
+}
+#endif
+
 /**
  * Parse device type, name and mtd-id. If syntax is ok allocate memory and
  * return pointer to the device structure.
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index 69345db..14fae9c 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -19,6 +19,8 @@
 #include <asm/io.h>
 #include <dm/device-internal.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 static struct spi_flash *flash;
 
 /*
@@ -265,6 +267,7 @@
 	int ret = 1;
 	int dev = 0;
 	loff_t offset, len, maxsize;
+	unsigned long sram_end = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
 
 	if (argc < 3)
 		return -1;
@@ -283,6 +286,16 @@
 		       argv[0], flash->size);
 		return 1;
 	}
+	/* Validate DDR region address */
+	if ((addr < CONFIG_SYS_SDRAM_BASE) || (addr > (sram_end - 1))) {
+		puts("Invalid RAM address \n");
+		return 1;
+	}
+
+	if ((addr + len) > sram_end) {
+		puts("No space available\n");
+		return 1;
+	}
 
 	buf = map_physmem(addr, len, MAP_WRBACK);
 	if (!buf) {
diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index b5bb051..5a77be4 100644
--- a/common/dlmalloc.c
+++ b/common/dlmalloc.c
@@ -3261,17 +3261,34 @@
   }
 }
 
+#ifdef CONFIG_COMPRESSED_DTB_BASE
+unsigned long malloc_base;
+
+int initf_pre_malloc(void)
+{
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+	assert(gd->malloc_base);	/* Set up by crt0.S */
+	malloc_base = gd->malloc_base;
+	gd->malloc_limit = CONFIG_COMPRESSED_DTB_MAX_SIZE;
+	gd->malloc_base = CONFIG_COMPRESSED_DTB_BASE - CONFIG_COMPRESSED_DTB_MAX_SIZE;
+	gd->malloc_ptr = 0;
+#endif
+	return 0;
+}
+#endif
+
 int initf_malloc(void)
 {
 #ifdef CONFIG_SYS_MALLOC_F_LEN
 	assert(gd->malloc_base);	/* Set up by crt0.S */
 	gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
+#ifdef CONFIG_COMPRESSED_DTB_BASE
+	gd->malloc_base = malloc_base;
+#endif
 	gd->malloc_ptr = 0;
 #endif
-
 	return 0;
 }
-
 /*
 
 History:
diff --git a/common/env_fat.c b/common/env_fat.c
index d79d864..32ba497 100644
--- a/common/env_fat.c
+++ b/common/env_fat.c
@@ -76,12 +76,18 @@
 
 void env_relocate_spec(void)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
+	char *buf = NULL;
 	block_dev_desc_t *dev_desc = NULL;
 	disk_partition_t info;
 	int dev, part;
 	int err;
 
+	buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
+	if (!buf) {
+		printf("Error: Cannot allocate %d bytes\n", CONFIG_ENV_SIZE);
+		goto err_env_relocate;
+	}
+
 	part = get_device_and_partition(FAT_ENV_INTERFACE,
 					FAT_ENV_DEVICE_AND_PART,
 					&dev_desc, &info, 1);
@@ -103,8 +109,11 @@
 	}
 
 	env_import(buf, 1);
+	free(buf);
 	return;
 
 err_env_relocate:
 	set_default_env(NULL);
+	if (buf)
+		free(buf);
 }
diff --git a/common/env_mmc.c b/common/env_mmc.c
index 12f60ca..16aadcb 100644
--- a/common/env_mmc.c
+++ b/common/env_mmc.c
@@ -139,15 +139,21 @@
 
 int mmc_saveenv(void)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
 	struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
 	u32	offset;
 	int	ret, copy = 0;
 	const char *errmsg;
 
+	env_t *env_new = (env_t *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
+	if (!env_new) {
+		printf("Error: Cannot allocate %d bytes\n", CONFIG_ENV_SIZE);
+		return 1;
+	}
+
 	errmsg = init_mmc_for_env(mmc);
 	if (errmsg) {
 		printf("%s\n", errmsg);
+		free(env_new);
 		return 1;
 	}
 
@@ -184,6 +190,7 @@
 
 fini:
 	fini_mmc_for_env(mmc);
+	free(env_new);
 	return ret;
 }
 #endif /* CONFIG_CMD_SAVEENV */
@@ -298,12 +305,17 @@
 void mmc_env_relocate_spec(void)
 {
 #if !defined(ENV_IS_EMBEDDED)
-	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
 	struct mmc *mmc;
 	u32 offset;
 	int ret;
 	int dev = CONFIG_SYS_MMC_ENV_DEV;
-	const char *errmsg;
+	const char *errmsg = NULL;
+	char *buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
+	if (!buf) {
+		printf("Error: Cannot allocate %d bytes\n", CONFIG_ENV_SIZE);
+		ret = 1;
+		goto err;
+	}
 
 #ifdef CONFIG_SPL_BUILD
 	dev = 0;
@@ -336,6 +348,8 @@
 err:
 	if (ret)
 		set_default_env(errmsg);
+	if (buf)
+		free(buf);
 #endif
 }
 #endif /* CONFIG_ENV_OFFSET_REDUND */
diff --git a/common/env_nand.c b/common/env_nand.c
index d1f617a..3481a73 100644
--- a/common/env_nand.c
+++ b/common/env_nand.c
@@ -183,7 +183,6 @@
 int nand_saveenv(void)
 {
 	int	ret = 0;
-	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
 	int	env_idx = 0;
 	struct env_location location[] = {
 		{
@@ -204,13 +203,22 @@
 #endif
 	};
 
-
-	if (CONFIG_ENV_RANGE > board_env_size)
+	env_t *env_new = (env_t *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
+	if (!env_new) {
+		printf("Error: Cannot allocate %d bytes\n", CONFIG_ENV_SIZE);
 		return 1;
+	}
+
+	if (CONFIG_ENV_RANGE > board_env_size) {
+		free(env_new);
+		return 1;
+	}
 
 	ret = env_export(env_new);
-	if (ret)
+	if (ret) {
+		free(env_new);
 		return ret;
+	}
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
 	env_new->flags = ++env_flags; /* increase the serial */
@@ -221,6 +229,7 @@
 	if (!ret) {
 		/* preset other copy for next write */
 		gd->env_valid = gd->env_valid == 2 ? 1 : 2;
+		free(env_new);
 		return ret;
 	}
 
@@ -230,7 +239,7 @@
 		printf("Warning: primary env write failed,"
 				" redundancy is lost!\n");
 #endif
-
+	free(env_new);
 	return ret;
 }
 #endif /* CMD_SAVEENV */
@@ -385,7 +394,13 @@
 {
 #if !defined(ENV_IS_EMBEDDED)
 	int ret;
-	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
+	char *buf = NULL;
+	buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
+	if (!buf) {
+		printf("Error: Cannot allocate %d bytes\n", CONFIG_ENV_SIZE);
+		set_default_env(NULL);
+		return;
+        }
 
 #if defined(CONFIG_ENV_OFFSET_OOB)
 	ret = get_nand_env_oob(&nand_info[nand_env_device], &nand_env_oob_offset);
@@ -397,6 +412,7 @@
 		printf("Found Environment offset in OOB..\n");
 	} else {
 		set_default_env("!no env offset in OOB");
+		free(buf);
 		return;
 	}
 #endif
@@ -404,10 +420,12 @@
 	ret = readenv(CONFIG_ENV_OFFSET, (u_char *)buf);
 	if (ret) {
 		set_default_env("!readenv() failed");
+		free(buf);
 		return;
 	}
 
 	env_import(buf, 1);
+	free(buf);
 #endif /* ! ENV_IS_EMBEDDED */
 }
 #endif /* CONFIG_ENV_OFFSET_REDUND */
diff --git a/common/env_sf.c b/common/env_sf.c
index 21c2327..cbf0bc8 100644
--- a/common/env_sf.c
+++ b/common/env_sf.c
@@ -52,14 +52,12 @@
 	u32	saved_size, saved_offset, sector = 1;
 	int	ret;
 
+	env_flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+		CONFIG_SF_DEFAULT_CS,
+		CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
 	if (!env_flash) {
-		env_flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
-			CONFIG_SF_DEFAULT_CS,
-			CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
-		if (!env_flash) {
-			set_default_env("!spi_flash_probe() failed");
-			return 1;
-		}
+		set_default_env("!spi_flash_probe() failed");
+		return 1;
 	}
 
 	ret = env_export(&env_new);
@@ -226,14 +224,12 @@
 	int	ret = 1;
 	env_t	env_new;
 
+	env_flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+		CONFIG_SF_DEFAULT_CS,
+		CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
 	if (!env_flash) {
-		env_flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
-			CONFIG_SF_DEFAULT_CS,
-			CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
-		if (!env_flash) {
-			set_default_env("!spi_flash_probe() failed");
-			return 1;
-		}
+		set_default_env("!spi_flash_probe() failed");
+		return 1;
 	}
 
 	/* Is the sector larger than the env (i.e. embedded) */
diff --git a/common/env_ubi.c b/common/env_ubi.c
index e611199..50178a9 100644
--- a/common/env_ubi.c
+++ b/common/env_ubi.c
@@ -81,14 +81,21 @@
 #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
 int saveenv(void)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
 	int ret;
+	env_t *env_new = (env_t *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE)
+	if (!env_new) {
+		printf("Error: Cannot allocate %d bytes\n", CONFIG_ENV_SIZE);
+		return 1;
+        }
 
 	ret = env_export(env_new);
-	if (ret)
+	if (ret) {
+		free(env_new);
 		return ret;
+	}
 
 	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
+		free(env_new);
 		printf("\n** Cannot find mtd partition \"%s\"\n",
 		       CONFIG_ENV_UBI_PART);
 		return 1;
@@ -96,11 +103,13 @@
 
 	if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new,
 			     CONFIG_ENV_SIZE)) {
+		free(env_new);
 		printf("\n** Unable to write env to %s:%s **\n",
 		       CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
 		return 1;
 	}
 
+	free(env_new);
 	puts("done\n");
 	return 0;
 }
@@ -172,12 +181,20 @@
 #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
 void env_relocate_spec(void)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
+
+	char *buf = NULL;
+	buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
+	if (!buf) {
+		printf("Error: Cannot allocate %d bytes\n");
+		set_default_env(NULL);
+		return;
+	}
 
 	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
 		printf("\n** Cannot find mtd partition \"%s\"\n",
 		       CONFIG_ENV_UBI_PART);
 		set_default_env(NULL);
+		free(buf);
 		return;
 	}
 
@@ -185,9 +202,11 @@
 		printf("\n** Unable to read env from %s:%s **\n",
 		       CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
 		set_default_env(NULL);
+		free(buf);
 		return;
 	}
 
 	env_import(buf, 1);
+	free(buf);
 }
 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
diff --git a/configs/ipq5018_defconfig b/configs/ipq5018_defconfig
new file mode 100644
index 0000000..b10406f
--- /dev/null
+++ b/configs/ipq5018_defconfig
@@ -0,0 +1,335 @@
+CONFIG_ARM=y
+CONFIG_HAS_VBAR=y
+CONFIG_CPU_V7=y
+CONFIG_ARCH_IPQ5018=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
+CONFIG_SYS_MALLOC_F=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEFAULT_DEVICE_TREE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+CONFIG_SYS_MALLOC_CLEAR_ON_INIT=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+# CONFIG_FIT_SIGNATURE is not set
+CONFIG_SYS_EXTRA_OPTIONS=""
+CONFIG_SYS_PROMPT="IPQ5018# "
+
+#
+# Tiny support
+#
+# CONFIG_IPQ_TINY is not set
+
+#
+# Info commands
+#
+CONFIG_CMD_BDI=y
+CONFIG_CMD_CONSOLE=y
+
+#
+# Boot commands
+#
+# CONFIG_CMD_BOOTD is not set
+CONFIG_CMD_BOOTM=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_RUN=y
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_XIMG is not set
+
+#
+# Environment commands
+#
+CONFIG_CMD_EXPORTENV=y
+CONFIG_CMD_IMPORTENV=y
+CONFIG_CMD_EDITENV=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_ENV_EXISTS=y
+
+#
+# Memory commands
+#
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_CRC32=y
+# CONFIG_LOOPW is not set
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_MX_CYCLIC is not set
+# CONFIG_CMD_MEMINFO is not set
+
+#
+# Device access commands
+#
+
+CONFIG_CMD_DM=y
+# CONFIG_CMD_DEMO is not set
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADS=y
+CONFIG_CMD_FLASH=y
+# CONFIG_CMD_NAND is not set
+# CONFIG_CMD_SF is not set
+# CONFIG_CMD_SPI is not set
+# CONFIG_CMD_I2C is not set
+# CONFIG_CMD_USB is not set
+CONFIG_CMD_FPGA=y
+
+#
+# Shell scripting commands
+#
+CONFIG_CMD_ECHO=y
+CONFIG_CMD_ITEST=y
+CONFIG_CMD_SOURCE=y
+CONFIG_CMD_SETEXPR=y
+
+#
+# Network commands
+#
+
+#
+# Network PHY
+#
+CONFIG_QCA8081_PHY=y
+
+CONFIG_CMD_NET=y
+# CONFIG_CMD_TFTPPUT is not set
+# CONFIG_CMD_TFTPSRV is not set
+# CONFIG_CMD_RARP is not set
+# CONFIG_CMD_DHCP is not set
+CONFIG_CMD_NFS=y
+# CONFIG_CMD_PING is not set
+# CONFIG_CMD_CDP is not set
+# CONFIG_CMD_SNTP is not set
+# CONFIG_CMD_DNS is not set
+# CONFIG_CMD_LINK_LOCAL is not set
+
+#
+# Misc commands
+#
+# CONFIG_CMD_TIME is not set
+CONFIG_CMD_MISC=y
+CONFIG_CMD_PART=y
+CONFIG_PARTITION_UUIDS=y
+# CONFIG_CMD_TIMER is not set
+CONFIG_IPQ_TZT=y
+CONFIG_UBI_WRITE=y
+#
+# Boot timing
+#
+# CONFIG_BOOTSTAGE is not set
+CONFIG_BOOTSTAGE_USER_COUNT=20
+CONFIG_BOOTSTAGE_STASH_ADDR=0
+CONFIG_BOOTSTAGE_STASH_SIZE=4096
+
+#
+# Power commands
+#
+
+#
+# Security commands
+#
+CONFIG_SUPPORT_OF_CONTROL=y
+
+#
+# Device Tree Control
+#
+CONFIG_OF_CONTROL=y
+CONFIG_OF_SEPARATE=y
+# CONFIG_OF_EMBED is not set
+CONFIG_NET=y
+# CONFIG_NET_RANDOM_ETHADDR is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_DM=y
+CONFIG_DM_WARN=y
+CONFIG_DM_DEVICE_REMOVE=y
+CONFIG_DM_STDIO=y
+CONFIG_DM_SEQ_ALIAS=y
+# CONFIG_REGMAP is not set
+# CONFIG_DEVRES is not set
+CONFIG_SIMPLE_BUS=y
+# CONFIG_CLK is not set
+# CONFIG_CPU is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_FSL_CAAM is not set
+
+#
+# Demo for driver model
+#
+# CONFIG_DM_DEMO is not set
+
+#
+# DFU support
+#
+# CONFIG_DFU_TFTP is not set
+
+#
+# GPIO Support
+#
+# CONFIG_LPC32XX_GPIO is not set
+# CONFIG_VYBRID_GPIO is not set
+
+#
+# I2C support
+#
+# CONFIG_DM_I2C_COMPAT is not set
+# CONFIG_CROS_EC_KEYB is not set
+CONFIG_IPQ5018_I2C=y
+
+#
+# LED Support
+#
+# CONFIG_LED is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_CROS_EC is not set
+# CONFIG_FSL_SEC_MON is not set
+# CONFIG_PCA9551_LED is not set
+# CONFIG_RESET is not set
+
+#
+# MMC Host controller Support
+#
+# CONFIG_DM_MMC is not set
+CONFIG_MMC_FLASH=y
+
+#
+# NAND Device Support
+#
+# CONFIG_NAND_DENALI is not set
+# CONFIG_NAND_VF610_NFC is not set
+# CONFIG_NAND_PXA3XX is not set
+
+#
+# Generic NAND options
+#
+CONFIG_NAND_FLASH=y
+
+#
+# Serial NAND
+#
+CONFIG_QPIC_SERIAL=y
+
+#
+# SPI Flash Support
+
+#
+# CONFIG_SPI_FLASH is not set
+# CONFIG_DM_ETH is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_IPQ_MTD_NOR is not set
+# CONFIG_IPQ_TINY_SPI_NOR is not set
+
+#
+# PCI
+#
+# CONFIG_DM_PCI is not set
+CONFIG_PCI_IPQ=y
+
+#
+# Pin controllers
+#
+# CONFIG_PINCTRL is not set
+
+#
+# Power
+#
+# CONFIG_DM_PMIC is not set
+# CONFIG_DM_REGULATOR is not set
+# CONFIG_RAM is not set
+
+#
+# Real Time Clock
+#
+# CONFIG_DM_RTC is not set
+
+#
+# Serial drivers
+#
+CONFIG_REQUIRE_SERIAL_CONSOLE=y
+# CONFIG_DEBUG_UART is not set
+
+#
+
+# Sound support
+#
+# CONFIG_SOUND is not set
+
+#
+# SPI Support
+#
+# CONFIG_FSL_ESPI is not set
+# CONFIG_TI_QSPI is not set
+# CONFIG_DM_THERMAL is not set
+
+#
+# TPM support
+#
+
+#
+# USB support
+#
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_XHCI_IPQ=y
+
+#
+# Graphics support
+#
+# CONFIG_VIDEO_VESA is not set
+# CONFIG_VIDEO_LCD_ANX9804 is not set
+# CONFIG_VIDEO_LCD_SSD2828 is not set
+# CONFIG_DISPLAY_PORT is not set
+# CONFIG_VIDEO_TEGRA124 is not set
+# CONFIG_VIDEO_BRIDGE is not set
+# CONFIG_PHYS_TO_BUS is not set
+
+#
+# File systems
+#
+
+#
+# Library routines
+
+#
+# CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
+CONFIG_HAVE_PRIVATE_LIBGCC=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_SYS_HZ=1000
+# CONFIG_SYS_VSNPRINTF is not set
+CONFIG_REGEX=y
+# CONFIG_LIB_RAND is not set
+# CONFIG_CMD_DHRYSTONE is not set
+# CONFIG_RSA is not set
+# CONFIG_TPM is not set
+
+#
+# Hashing Support
+#
+# CONFIG_SHA1 is not set
+# CONFIG_SHA256 is not set
+# CONFIG_SHA_HW_ACCEL is not set
+
+#
+# Compression Support
+#
+# CONFIG_LZ4 is not set
+CONFIG_LZMA=y
+# CONFIG_ERRNO_STR is not set
+# CONFIG_UNIT_TEST is not set
+
+CONFIG_SYS_THUMB_BUILD=y
+CONFIG_HAS_THUMB2=y
diff --git a/configs/ipq5018_tiny_debug_defconfig b/configs/ipq5018_tiny_debug_defconfig
new file mode 100644
index 0000000..f699473
--- /dev/null
+++ b/configs/ipq5018_tiny_debug_defconfig
@@ -0,0 +1,342 @@
+CONFIG_ARM=y
+CONFIG_HAS_VBAR=y
+CONFIG_CPU_V7=y
+CONFIG_ARCH_IPQ5018=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
+CONFIG_SYS_MALLOC_F=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEFAULT_DEVICE_TREE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+CONFIG_SYS_MALLOC_CLEAR_ON_INIT=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+# CONFIG_FIT_SIGNATURE is not set
+CONFIG_SYS_EXTRA_OPTIONS=""
+CONFIG_SYS_PROMPT="IPQ5018# "
+
+#
+# Tiny support
+#
+CONFIG_IPQ_TINY=y
+
+#
+# Info commands
+#
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+
+#
+# Boot commands
+#
+# CONFIG_CMD_BOOTD is not set
+CONFIG_CMD_BOOTM=y
+# CONFIG_CMD_GO is not set
+CONFIG_CMD_RUN=y
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_XIMG is not set
+
+#
+# Environment commands
+#
+CONFIG_CMD_EXPORTENV=y
+CONFIG_CMD_IMPORTENV=y
+# CONFIG_CMD_EDITENV is not set
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_ENV_EXISTS=y
+
+#
+# Memory commands
+#
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_CRC32=y
+# CONFIG_LOOPW is not set
+# CONFIG_CMD_MEMTEST is not set
+# CONFIG_CMD_MX_CYCLIC is not set
+# CONFIG_CMD_MEMINFO is not set
+
+#
+# Device access commands
+#
+
+# CONFIG_CMD_DM is not set
+# CONFIG_CMD_DEMO is not set
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_NAND is not set
+# CONFIG_CMD_SF is not set
+# CONFIG_CMD_SPI is not set
+# CONFIG_CMD_I2C is not set
+# CONFIG_CMD_USB is not set
+# CONFIG_CMD_FPGA is not set
+
+#
+# Shell scripting commands
+#
+CONFIG_CMD_ECHO=y
+# CONFIG_CMD_ITEST is not set
+CONFIG_CMD_SOURCE=y
+# CONFIG_CMD_SETEXPR is not set
+
+#
+# Network commands
+#
+CONFIG_CMD_NET=y
+# CONFIG_CMD_TFTPPUT is not set
+# CONFIG_CMD_TFTPSRV is not set
+# CONFIG_CMD_RARP is not set
+# CONFIG_CMD_DHCP is not set
+# CONFIG_CMD_NFS is not set
+# CONFIG_CMD_PING is not set
+# CONFIG_CMD_CDP is not set
+# CONFIG_CMD_SNTP is not set
+# CONFIG_CMD_DNS is not set
+# CONFIG_CMD_LINK_LOCAL is not set
+
+#
+# Misc commands
+#
+# CONFIG_CMD_TIME is not set
+CONFIG_CMD_MISC=y
+# CONFIG_CMD_PART is not set
+# CONFIG_PARTITION_UUIDS is not set
+# CONFIG_CMD_TIMER is not set
+# CONFIG_IPQ_TZT is not set
+# CONFIG_UBI_WRITE is not set
+#
+# Boot timing
+#
+# CONFIG_BOOTSTAGE is not set
+CONFIG_BOOTSTAGE_USER_COUNT=20
+CONFIG_BOOTSTAGE_STASH_ADDR=0
+CONFIG_BOOTSTAGE_STASH_SIZE=4096
+
+#
+# Power commands
+#
+
+#
+# Security commands
+#
+CONFIG_SUPPORT_OF_CONTROL=y
+
+#
+# Device Tree Control
+#
+CONFIG_OF_CONTROL=y
+CONFIG_OF_SEPARATE=y
+# CONFIG_OF_EMBED is not set
+CONFIG_NET=y
+# CONFIG_NET_RANDOM_ETHADDR is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_DM=y
+CONFIG_DM_WARN=y
+CONFIG_DM_DEVICE_REMOVE=y
+CONFIG_DM_STDIO=y
+CONFIG_DM_SEQ_ALIAS=y
+# CONFIG_REGMAP is not set
+# CONFIG_DEVRES is not set
+CONFIG_SIMPLE_BUS=y
+# CONFIG_CLK is not set
+# CONFIG_CPU is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_FSL_CAAM is not set
+
+#
+# Demo for driver model
+#
+# CONFIG_DM_DEMO is not set
+
+#
+# DFU support
+#
+# CONFIG_DFU_TFTP is not set
+
+#
+# GPIO Support
+#
+# CONFIG_LPC32XX_GPIO is not set
+# CONFIG_VYBRID_GPIO is not set
+
+#
+# I2C support
+#
+# CONFIG_DM_I2C_COMPAT is not set
+# CONFIG_CROS_EC_KEYB is not set
+# CONFIG_IPQ5018_I2C is not set
+
+#
+# LED Support
+#
+# CONFIG_LED is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_CROS_EC is not set
+# CONFIG_FSL_SEC_MON is not set
+# CONFIG_PCA9551_LED is not set
+# CONFIG_RESET is not set
+
+#
+# MMC Host controller Support
+#
+# CONFIG_DM_MMC is not set
+# CONFIG_MMC_FLASH is not set
+
+#
+# NAND Device Support
+#
+# CONFIG_NAND_DENALI is not set
+# CONFIG_NAND_VF610_NFC is not set
+# CONFIG_NAND_PXA3XX is not set
+
+#
+# Generic NAND options
+#
+CONFIG_NAND_FLASH=y
+
+#
+# Serial NAND
+#
+CONFIG_QPIC_SERIAL=y
+
+#
+# SPI Flash Support
+
+#
+# CONFIG_SPI_FLASH is not set
+# CONFIG_DM_ETH is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_IPQ_MTD_NOR is not set
+CONFIG_IPQ_TINY_SPI_NOR=y
+
+#
+# PCI
+#
+# CONFIG_DM_PCI is not set
+# CONFIG_PCI_IPQ is not set
+
+#
+# Pin controllers
+#
+# CONFIG_PINCTRL is not set
+
+#
+# Power
+#
+# CONFIG_DM_PMIC is not set
+# CONFIG_DM_REGULATOR is not set
+# CONFIG_RAM is not set
+
+#
+# Real Time Clock
+#
+# CONFIG_DM_RTC is not set
+
+#
+# Serial drivers
+#
+CONFIG_REQUIRE_SERIAL_CONSOLE=y
+# CONFIG_DEBUG_UART is not set
+
+#
+
+# Sound support
+#
+# CONFIG_SOUND is not set
+
+#
+# SPI Support
+#
+# CONFIG_FSL_ESPI is not set
+# CONFIG_TI_QSPI is not set
+# CONFIG_DM_THERMAL is not set
+
+#
+# TPM support
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_DM_USB is not set
+# CONFIG_USB_XHCI_IPQ is not set
+
+#
+# Graphics support
+#
+# CONFIG_VIDEO_VESA is not set
+# CONFIG_VIDEO_LCD_ANX9804 is not set
+# CONFIG_VIDEO_LCD_SSD2828 is not set
+# CONFIG_DISPLAY_PORT is not set
+# CONFIG_VIDEO_TEGRA124 is not set
+# CONFIG_VIDEO_BRIDGE is not set
+# CONFIG_PHYS_TO_BUS is not set
+
+#
+# File systems
+#
+
+#
+# Ethernet PHY
+#
+CONFIG_QCA8033_PHY=y
+
+#
+# Library routines
+
+#
+# CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
+CONFIG_HAVE_PRIVATE_LIBGCC=y
+# CONFIG_USE_PRIVATE_LIBGCC is not set
+CONFIG_SYS_HZ=1000
+# CONFIG_SYS_VSNPRINTF is not set
+CONFIG_REGEX=y
+# CONFIG_LIB_RAND is not set
+# CONFIG_CMD_DHRYSTONE is not set
+# CONFIG_RSA is not set
+# CONFIG_TPM is not set
+
+#
+# Hashing Support
+#
+# CONFIG_SHA1 is not set
+# CONFIG_SHA256 is not set
+# CONFIG_SHA_HW_ACCEL is not set
+
+#
+# Compression Support
+#
+# CONFIG_LZ4 is not set
+CONFIG_LZMA=y
+# CONFIG_ERRNO_STR is not set
+# CONFIG_UNIT_TEST is not set
+
+#
+# Thumb2 mode support
+#
+CONFIG_SYS_THUMB_BUILD=y
+CONFIG_HAS_THUMB2=y
+
+#
+# ART uncompression support
+#
+CONFIG_ART_COMPRESSED=y
diff --git a/configs/ipq5018_tiny_defconfig b/configs/ipq5018_tiny_defconfig
new file mode 100644
index 0000000..40cf113
--- /dev/null
+++ b/configs/ipq5018_tiny_defconfig
@@ -0,0 +1,342 @@
+CONFIG_ARM=y
+CONFIG_HAS_VBAR=y
+CONFIG_CPU_V7=y
+CONFIG_ARCH_IPQ5018=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
+CONFIG_SYS_MALLOC_F=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEFAULT_DEVICE_TREE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+CONFIG_SYS_MALLOC_CLEAR_ON_INIT=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+# CONFIG_FIT_SIGNATURE is not set
+CONFIG_SYS_EXTRA_OPTIONS=""
+CONFIG_SYS_PROMPT="IPQ5018# "
+
+#
+# Tiny support
+#
+CONFIG_IPQ_TINY=y
+
+#
+# Info commands
+#
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+
+#
+# Boot commands
+#
+# CONFIG_CMD_BOOTD is not set
+CONFIG_CMD_BOOTM=y
+# CONFIG_CMD_GO is not set
+CONFIG_CMD_RUN=y
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_XIMG is not set
+
+#
+# Environment commands
+#
+CONFIG_CMD_EXPORTENV=y
+CONFIG_CMD_IMPORTENV=y
+# CONFIG_CMD_EDITENV is not set
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_ENV_EXISTS=y
+
+#
+# Memory commands
+#
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_CRC32=y
+# CONFIG_LOOPW is not set
+# CONFIG_CMD_MEMTEST is not set
+# CONFIG_CMD_MX_CYCLIC is not set
+# CONFIG_CMD_MEMINFO is not set
+
+#
+# Device access commands
+#
+
+# CONFIG_CMD_DM is not set
+# CONFIG_CMD_DEMO is not set
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_NAND is not set
+# CONFIG_CMD_SF is not set
+# CONFIG_CMD_SPI is not set
+# CONFIG_CMD_I2C is not set
+# CONFIG_CMD_USB is not set
+# CONFIG_CMD_FPGA is not set
+
+#
+# Shell scripting commands
+#
+CONFIG_CMD_ECHO=y
+# CONFIG_CMD_ITEST is not set
+CONFIG_CMD_SOURCE=y
+# CONFIG_CMD_SETEXPR is not set
+
+#
+# Network commands
+#
+CONFIG_CMD_NET=y
+# CONFIG_CMD_TFTPPUT is not set
+# CONFIG_CMD_TFTPSRV is not set
+# CONFIG_CMD_RARP is not set
+# CONFIG_CMD_DHCP is not set
+# CONFIG_CMD_NFS is not set
+# CONFIG_CMD_PING is not set
+# CONFIG_CMD_CDP is not set
+# CONFIG_CMD_SNTP is not set
+# CONFIG_CMD_DNS is not set
+# CONFIG_CMD_LINK_LOCAL is not set
+
+#
+# Misc commands
+#
+# CONFIG_CMD_TIME is not set
+CONFIG_CMD_MISC=y
+# CONFIG_CMD_PART is not set
+# CONFIG_PARTITION_UUIDS is not set
+# CONFIG_CMD_TIMER is not set
+# CONFIG_IPQ_TZT is not set
+# CONFIG_UBI_WRITE is not set
+#
+# Boot timing
+#
+# CONFIG_BOOTSTAGE is not set
+CONFIG_BOOTSTAGE_USER_COUNT=20
+CONFIG_BOOTSTAGE_STASH_ADDR=0
+CONFIG_BOOTSTAGE_STASH_SIZE=4096
+
+#
+# Power commands
+#
+
+#
+# Security commands
+#
+CONFIG_SUPPORT_OF_CONTROL=y
+
+#
+# Device Tree Control
+#
+CONFIG_OF_CONTROL=y
+CONFIG_OF_SEPARATE=y
+# CONFIG_OF_EMBED is not set
+CONFIG_NET=y
+# CONFIG_NET_RANDOM_ETHADDR is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_DM=y
+CONFIG_DM_WARN=y
+CONFIG_DM_DEVICE_REMOVE=y
+CONFIG_DM_STDIO=y
+CONFIG_DM_SEQ_ALIAS=y
+# CONFIG_REGMAP is not set
+# CONFIG_DEVRES is not set
+CONFIG_SIMPLE_BUS=y
+# CONFIG_CLK is not set
+# CONFIG_CPU is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_FSL_CAAM is not set
+
+#
+# Demo for driver model
+#
+# CONFIG_DM_DEMO is not set
+
+#
+# DFU support
+#
+# CONFIG_DFU_TFTP is not set
+
+#
+# GPIO Support
+#
+# CONFIG_LPC32XX_GPIO is not set
+# CONFIG_VYBRID_GPIO is not set
+
+#
+# I2C support
+#
+# CONFIG_DM_I2C_COMPAT is not set
+# CONFIG_CROS_EC_KEYB is not set
+# CONFIG_IPQ5018_I2C is not set
+
+#
+# LED Support
+#
+# CONFIG_LED is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_CROS_EC is not set
+# CONFIG_FSL_SEC_MON is not set
+# CONFIG_PCA9551_LED is not set
+# CONFIG_RESET is not set
+
+#
+# MMC Host controller Support
+#
+# CONFIG_DM_MMC is not set
+# CONFIG_MMC_FLASH is not set
+
+#
+# NAND Device Support
+#
+# CONFIG_NAND_DENALI is not set
+# CONFIG_NAND_VF610_NFC is not set
+# CONFIG_NAND_PXA3XX is not set
+
+#
+# Generic NAND options
+#
+# CONFIG_NAND_FLASH is not set
+
+#
+# Serial NAND
+#
+# CONFIG_QPIC_SERIAL is not set
+
+#
+# SPI Flash Support
+
+#
+# CONFIG_SPI_FLASH is not set
+# CONFIG_DM_ETH is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_IPQ_MTD_NOR is not set
+CONFIG_IPQ_TINY_SPI_NOR=y
+
+#
+# PCI
+#
+# CONFIG_DM_PCI is not set
+# CONFIG_PCI_IPQ is not set
+
+#
+# Pin controllers
+#
+# CONFIG_PINCTRL is not set
+
+#
+# Power
+#
+# CONFIG_DM_PMIC is not set
+# CONFIG_DM_REGULATOR is not set
+# CONFIG_RAM is not set
+
+#
+# Real Time Clock
+#
+# CONFIG_DM_RTC is not set
+
+#
+# Serial drivers
+#
+CONFIG_REQUIRE_SERIAL_CONSOLE=y
+# CONFIG_DEBUG_UART is not set
+
+#
+
+# Sound support
+#
+# CONFIG_SOUND is not set
+
+#
+# SPI Support
+#
+# CONFIG_FSL_ESPI is not set
+# CONFIG_TI_QSPI is not set
+# CONFIG_DM_THERMAL is not set
+
+#
+# TPM support
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_DM_USB is not set
+# CONFIG_USB_XHCI_IPQ is not set
+
+#
+# Graphics support
+#
+# CONFIG_VIDEO_VESA is not set
+# CONFIG_VIDEO_LCD_ANX9804 is not set
+# CONFIG_VIDEO_LCD_SSD2828 is not set
+# CONFIG_DISPLAY_PORT is not set
+# CONFIG_VIDEO_TEGRA124 is not set
+# CONFIG_VIDEO_BRIDGE is not set
+# CONFIG_PHYS_TO_BUS is not set
+
+#
+# File systems
+#
+
+#
+# Ethernet PHY
+#
+CONFIG_QCA8033_PHY=y
+
+#
+# Library routines
+
+#
+# CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
+CONFIG_HAVE_PRIVATE_LIBGCC=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_SYS_HZ=1000
+# CONFIG_SYS_VSNPRINTF is not set
+CONFIG_REGEX=y
+# CONFIG_LIB_RAND is not set
+# CONFIG_CMD_DHRYSTONE is not set
+# CONFIG_RSA is not set
+# CONFIG_TPM is not set
+
+#
+# Hashing Support
+#
+# CONFIG_SHA1 is not set
+# CONFIG_SHA256 is not set
+# CONFIG_SHA_HW_ACCEL is not set
+
+#
+# Compression Support
+#
+# CONFIG_LZ4 is not set
+CONFIG_LZMA=y
+# CONFIG_ERRNO_STR is not set
+# CONFIG_UNIT_TEST is not set
+
+#
+# Thumb2 mode support
+#
+CONFIG_SYS_THUMB_BUILD=y
+CONFIG_HAS_THUMB2=y
+
+#
+# ART uncompression support
+#
+CONFIG_ART_COMPRESSED=y
diff --git a/configs/ipq6018_defconfig b/configs/ipq6018_defconfig
index e3396ed..8b83a56 100644
--- a/configs/ipq6018_defconfig
+++ b/configs/ipq6018_defconfig
@@ -293,7 +293,7 @@
 #
 # CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
 CONFIG_HAVE_PRIVATE_LIBGCC=y
-# CONFIG_USE_PRIVATE_LIBGCC is not set
+CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_SYS_HZ=1000
 # CONFIG_SYS_VSNPRINTF is not set
 CONFIG_REGEX=y
@@ -313,5 +313,6 @@
 # Compression Support
 #
 # CONFIG_LZ4 is not set
+CONFIG_LZMA=y
 # CONFIG_ERRNO_STR is not set
 # CONFIG_UNIT_TEST is not set
diff --git a/configs/ipq6018_tiny_defconfig b/configs/ipq6018_tiny_defconfig
index e4dee21..30758e2 100644
--- a/configs/ipq6018_tiny_defconfig
+++ b/configs/ipq6018_tiny_defconfig
@@ -293,7 +293,7 @@
 #
 # CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
 CONFIG_HAVE_PRIVATE_LIBGCC=y
-# CONFIG_USE_PRIVATE_LIBGCC is not set
+CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_SYS_HZ=1000
 # CONFIG_SYS_VSNPRINTF is not set
 CONFIG_REGEX=y
diff --git a/configs/ipq807x_defconfig b/configs/ipq807x_defconfig
index 70b4183..6fa49f5 100644
--- a/configs/ipq807x_defconfig
+++ b/configs/ipq807x_defconfig
@@ -292,7 +292,7 @@
 #
 # CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
 CONFIG_HAVE_PRIVATE_LIBGCC=y
-# CONFIG_USE_PRIVATE_LIBGCC is not set
+CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_SYS_HZ=1000
 # CONFIG_SYS_VSNPRINTF is not set
 # CONFIG_REGEX is not set
@@ -312,5 +312,6 @@
 # Compression Support
 #
 # CONFIG_LZ4 is not set
+CONFIG_LZMA=y
 # CONFIG_ERRNO_STR is not set
 # CONFIG_UNIT_TEST is not set
diff --git a/configs/ipq807x_tiny_defconfig b/configs/ipq807x_tiny_defconfig
index becb277..b79e5da 100644
--- a/configs/ipq807x_tiny_defconfig
+++ b/configs/ipq807x_tiny_defconfig
@@ -292,7 +292,7 @@
 #
 # CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
 CONFIG_HAVE_PRIVATE_LIBGCC=y
-# CONFIG_USE_PRIVATE_LIBGCC is not set
+CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_SYS_HZ=1000
 # CONFIG_SYS_VSNPRINTF is not set
 # CONFIG_REGEX is not set
@@ -312,7 +312,8 @@
 # Compression Support
 #
 # CONFIG_LZ4 is not set
+CONFIG_LZMA=y
 # CONFIG_ERRNO_STR is not set
 # CONFIG_UNIT_TEST is not set
 CONFIG_HAS_THUMB2=y
-CONFIG_SYS_THUMB_BUILD=y
\ No newline at end of file
+CONFIG_SYS_THUMB_BUILD=y
diff --git a/disk/part.c b/disk/part.c
index 909712e..7fe2e7d 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -20,6 +20,9 @@
 #define PRINTF(fmt,args...)
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef HAVE_BLOCK_DEVICE
 struct block_drvr {
 	char *name;
 	block_dev_desc_t* (*get_dev)(int dev);
@@ -55,9 +58,6 @@
 	{ },
 };
 
-DECLARE_GLOBAL_DATA_PTR;
-
-#ifdef HAVE_BLOCK_DEVICE
 static block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
 {
 	const struct block_drvr *drvr = block_drvr;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 766be9c..eab03ba 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -272,7 +272,8 @@
 		dst += cur * mmc->read_bl_len;
 	} while (blocks_todo > 0);
 #if !defined(CONFIG_SYS_DCACHE_OFF)
-	flush_cache((unsigned long)dst, blkcnt * mmc->read_bl_len);
+	flush_cache((unsigned long)dst - ( blkcnt * mmc->read_bl_len),
+					blkcnt * mmc->read_bl_len);
 #endif
 
 	return blkcnt;
diff --git a/drivers/mtd/ipq_spi_flash.c b/drivers/mtd/ipq_spi_flash.c
index 573fd61..21e2fe2 100644
--- a/drivers/mtd/ipq_spi_flash.c
+++ b/drivers/mtd/ipq_spi_flash.c
@@ -132,7 +132,7 @@
 int ipq_spi_init(u16 idx)
 {
 	struct spi_flash *flash;
-	int ret;
+	int ret = 0;
 	struct mtd_info *mtd;
 
 	flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
@@ -165,14 +165,14 @@
 	mtd->_write_oob = ipq_spi_write_oob;
 	mtd->_block_isbad = ipq_spi_block_isbad;
 	mtd->_block_markbad = ipq_spi_block_markbad;
-
+#ifdef CONFIG_MTD_DEVICE
 	if ((ret = nand_register(idx)) < 0) {
 		spi_print("Failed to register with MTD subsystem\n");
 		return ret;
 	}
-
+#endif
 	spi_print("page_size: 0x%x, sector_size: 0x%x, size: 0x%x\n",
 		flash->page_size, flash->sector_size, flash->size);
 
-	return 0;
+	return ret;
 }
diff --git a/drivers/mtd/nand/qpic_nand.c b/drivers/mtd/nand/qpic_nand.c
index 59904c9..2d0aee0 100644
--- a/drivers/mtd/nand/qpic_nand.c
+++ b/drivers/mtd/nand/qpic_nand.c
@@ -115,10 +115,120 @@
 		.check_quad_config = false,
 		.name = "MT29F1G01ABBFDWB-IT",
 	},
+	{
+		.id = { 0xef, 0xbc },
+		.page_size = 2048,
+		.erase_blk_size = 0x00020000,
+		.pgs_per_blk = 64,
+		.no_of_blocks = 1024,
+		.spare_size = 64,
+		.density = 0x08000000,
+		.otp_region = 0x5000,
+		.no_of_addr_cycle = 0x3,
+		.num_bits_ecc_correctability = 4,
+		.timing_mode_support = 0,
+		.quad_mode = true,
+		.check_quad_config = true,
+		.name = "W25N01JW",
+	},
+	{
+		.id = { 0xc8, 0x11 },
+		.page_size = 2048,
+		.erase_blk_size = 0x00020000,
+		.pgs_per_blk = 64,
+		.no_of_blocks = 1024,
+		.spare_size = 64,
+		.density = 0x08000000,
+		.otp_region = 0x2000,
+		.no_of_addr_cycle = 0x3,
+		.num_bits_ecc_correctability = 4,
+		.timing_mode_support = 0,
+		.quad_mode = true,
+		.check_quad_config = false,
+		.name = "F50D1G41LB(2M)",
+	},
+	{
+		.id = { 0xc8, 0x41 },
+		.page_size = 2048,
+		.erase_blk_size = 0x00020000,
+		.pgs_per_blk = 64,
+		.no_of_blocks = 2048,
+		.spare_size = 128,
+		.density = 0x08000000,
+		.otp_region = 0x2000,
+		.no_of_addr_cycle = 0x3,
+		.num_bits_ecc_correctability = 8,
+		.timing_mode_support = 0,
+		.quad_mode = true,
+		.check_quad_config = true,
+		.name = "GD5F1GQ5REYIG",
+	},
+	{
+		.id = { 0xc8, 0x21 },
+		.page_size = 2048,
+		.erase_blk_size = 0x00020000,
+		.pgs_per_blk = 64,
+		.no_of_blocks = 1024,
+		.spare_size = 64,
+		.density = 0x08000000,
+		.otp_region = 0x2000,
+		.no_of_addr_cycle = 0x3,
+		.num_bits_ecc_correctability = 4,
+		.timing_mode_support = 0,
+		.quad_mode = true,
+		.check_quad_config = true,
+		.name = "GD5F1GQ5REYIH",
+	},
+	{
+		.id = { 0xef, 0xbf },
+		.page_size = 2048,
+		.erase_blk_size = 0x00020000,
+		.pgs_per_blk = 64,
+		.no_of_blocks = 2048,
+		.spare_size = 64,
+		.density = 0x10000000,
+		.otp_region = 0x2000,
+		.no_of_addr_cycle = 0x3,
+		.num_bits_ecc_correctability = 4,
+		.timing_mode_support = 0,
+		.quad_mode = true,
+		.check_quad_config = true,
+		.name = "W25N02JWZEIF",
+	},
+	{
+		.id = { 0xc2, 0x92 },
+		.page_size = 2048,
+		.erase_blk_size = 0x00020000,
+		.pgs_per_blk = 64,
+		.no_of_blocks = 1024,
+		.spare_size = 64,
+		.density = 0x08000000,
+		.otp_region = 0x2000,
+		.no_of_addr_cycle = 0x3,
+		.num_bits_ecc_correctability = 4,
+		.timing_mode_support = 0,
+		.quad_mode = true,
+		.check_quad_config = true,
+		.name = "MX35UF1GE4AC",
+	},
 };
 struct qpic_serial_nand_params *serial_params;
 #define MICRON_DEVICE_ID	0x152c152c
+#define WINBOND_DEVICE_ID	0x0021bcef
 #define CMD3_MASK		0xfff0ffff
+/*
+ * An array holding the fixed pattern to compare with
+ * training pattern.
+ */
+static const unsigned int training_block_64[] = {
+	0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F,
+	0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F,
+	0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F,
+	0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F,
+};
+#define TRAINING_PART_OFFSET	0x3c00000
+#define MAXIMUM_ALLOCATED_TRAINING_BLOCK	4
+#define TOTAL_NUM_PHASE	7
 #endif
 
 struct cmd_element ce_array[100]
@@ -769,9 +879,9 @@
 		mtd->ecc_strength = 8;
 	else
 		mtd->ecc_strength = 4;
-	printf("Serial NAND device Manufature:%s\n",serial_params->name);
-	printf("Device Size:%d MiB, Page size:%d, Spare Size:%d\n",
-		(int)(dev->density >> 20), dev->page_size, mtd->oobsize);
+	printf("Serial NAND device Manufacturer:%s\n",serial_params->name);
+	printf("Device Size:%d MiB, Page size:%d, Spare Size:%d, ECC:%d-bit\n",
+		(int)(dev->density >> 20), dev->page_size, mtd->oobsize, mtd->ecc_strength);
 }
 #endif
 
@@ -1008,10 +1118,9 @@
 	 * Feature value will get updated in [15:8]
 	 */
 	nand_ret = qpic_nand_read_reg(NAND_FLASH_FEATURES, 0);
-#ifdef QPIC_DEBUG_SERIAL
-	printf("NAND Feature Register Addr:0x%02x and Val:0x%08x\n",
+
+	qspi_debug("NAND Feature Register Addr:0x%02x and Val:0x%08x\n",
 			ftr_addr,nand_ret);
-#endif
 err:
 	return nand_ret;
 
@@ -1130,6 +1239,7 @@
 	uint32_t status = 0x0;
 	struct qpic_nand_dev *dev = MTD_QPIC_NAND_DEV(mtd);
 	uint32_t cmd3_val = NAND_FLASH_DEV_CMD3_VAL;
+
 	/* For micron device the READ_CACHE_SEQ command is different than
 	 * Giga device. for Giga 0x31 and for Micron 0x30.
 	 * so based on id update the command configuration register
@@ -1139,6 +1249,7 @@
 		cmd3_val = (NAND_FLASH_DEV_CMD3_VAL & CMD3_MASK);
 		writel(cmd3_val, SPI_NAND_DEV_CMD3);
 	}
+
 	/* Get the block protection status*/
 	status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_BLK_PROCT_ADDR);
 	if (status < 0) {
@@ -1147,8 +1258,8 @@
 	}
 
 	if ((status >> 8) & FLASH_SPI_NAND_BLK_PROCT_ENABLE) {
-		printf("%s: Block protection is enabled\n",__func__);
-		printf("%s: Issuing set feature command to disable it.\n",__func__);
+		qspi_debug("%s: Block protection is enabled\n",__func__);
+		qspi_debug("%s: Issuing set feature command to disable it.\n",__func__);
 
 		status  = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_BLK_PROCT_ADDR,
 				FLASH_SPI_NAND_BLK_PROCT_DISABLE);
@@ -1169,9 +1280,9 @@
 					__func__);
 			return -QPIC_SERIAL_ERROR;
 		} else
-			printf("%s : Block protection Disabled.\n",__func__);
+			qspi_debug("%s : Block protection Disabled.\n",__func__);
 	} else
-		printf("%s: Block protection Disabled on Power on.\n",__func__);
+		qspi_debug("%s: Block protection Disabled on Power on.\n",__func__);
 
 	/* Get Internal ECC status */
 	status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_FR_ADDR);
@@ -1181,7 +1292,7 @@
 	}
 
 	if ((status  >> 8) & FLASH_SPI_NAND_FR_ECC_ENABLE) {
-		printf("%s : Internal ECC enabled, disabling internal ECC\n",__func__);
+		qspi_debug("%s : Internal ECC enabled, disabling internal ECC\n",__func__);
 
 		status &= ~(FLASH_SPI_NAND_FR_ECC_ENABLE);
 		status = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_FR_ADDR,
@@ -1201,13 +1312,13 @@
 		}
 
 		if ((status  >> 8) & FLASH_SPI_NAND_FR_ECC_ENABLE) {
-			pr_info("%s: Failed to disabled device internal ECC\n",
+			printf("%s: Failed to disabled device internal ECC\n",
 					__func__);
 			return -QPIC_SERIAL_ERROR;
 		} else
-			printf("%s : Internal ECC disabled.\n",__func__);
+			qspi_debug("%s : Internal ECC disabled.\n",__func__);
 	} else
-		printf("%s : Internal ECC disabled on power on.\n",__func__);
+		qspi_debug("%s : Internal ECC disabled on power on.\n",__func__);
 
 	/* Enable QUAD mode if device supported. Check this condition only
 	 * if dev->quad_mode = true , means device will support Quad mode
@@ -1230,17 +1341,17 @@
 		}
 
 		if (!((status >> 8) & FLASH_SPI_NAND_FR_QUAD_ENABLE)) {
-			printf("%s : Quad bit not enabled.\n",__func__);
-			printf("%s : Issuning set feature command to enable it.\n",
+			qspi_debug("%s : Quad bit not enabled.\n",__func__);
+			qspi_debug("%s : Issuning set feature command to enable it.\n",
 					__func__);
-
 			/* Enable quad bit */
 			status = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_FR_ADDR,
 			FLASH_SPI_NAND_FR_QUAD_ENABLE);
 			if (status < 0) {
-			printf("%s : Error in enabling Quad bit.\n",__func__);
-			return status;
+				printf("%s : Error in enabling Quad bit.\n",__func__);
+				return status;
 			}
+
 			/* Read status again to know wether Quad bit enabled or not */
 			status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_FR_ADDR);
 				if (status < 0) {
@@ -1249,19 +1360,42 @@
 			}
 
 			if (!((status >> 8) & FLASH_SPI_NAND_FR_QUAD_ENABLE)) {
-				printf("%s:Quad mode not enabled,so use x1 Mode.\n",
+				qspi_debug("%s:Quad mode not enabled,so use x1 Mode.\n",
 					__func__);
 				dev->quad_mode = false;
-				return 0;
 			} else {
-				printf("%s: Quad mode enabled. using X4 mode\n",__func__);
-				return 0;
+				qspi_debug("%s: Quad mode enabled. using X4 mode\n",__func__);
 			}
 		} else {
-			printf("%s: Quad mode enabled on Opwer on.\n",__func__);
-			return 0;
+			qspi_debug("%s: Quad mode enabled on Opwer on.\n",__func__);
 		}
 	}
+
+	if (dev->id == WINBOND_DEVICE_ID) {
+		status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_FR_ADDR);
+		if (status < 0) {
+			printf("%s : Error in getting feature.\n",__func__);
+			return status;
+		}
+
+		if (!((status >> 8) & FLASH_SPI_NAND_FR_BUFF_ENABLE)) {
+			qspi_debug("%s :continous buffer mode disabled\n",
+				__func__);
+			qspi_debug("%s : Issuing set feature command to enable it\n",
+					__func__);
+			status = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_FR_ADDR,
+				(FLASH_SPI_NAND_FR_BUFF_ENABLE | (status >> 8)));
+			if (status < 0) {
+				printf("%s : Error in disabling continous buffer bit.\n",
+						__func__);
+				return status;
+			}
+		} else {
+			qspi_debug("%s : continous buffer mode enabled on power on\n",
+					__func__);
+		}
+	}
+
 	return 0;
 }
 #endif
@@ -1404,28 +1538,71 @@
 {
 	uint32_t xfer_start = NAND_XFR_STEPS_V1_5_20;
 	int i;
+	unsigned int default_clk_rate;
 
-	/* Enabel QPIC CLK*/
-	qpic_clk_enbale();
+	int num_desc = 0;
+	struct cmd_element *cmd_list_ptr = ce_array;
+	struct cmd_element *cmd_list_ptr_start = ce_array;
 
-	/* Configure the NAND_FLASH_SPI_CFG to load the timer CLK_CNTR_INIT_VAL_VEC
-	 * value, enable the LOAD_CLK_CNTR_INIT_EN bit and enable SPI_CFG mode.
-	 */
-	writel(0x0, NAND_FLASH_SPI_CFG);
+	unsigned int val;
 
-	/* Make bit-28 of NAND_FLASH_SPI_CFG register to load
-	 * CLK_CNTR_INIT_VAL_VEC into IO Macro clock generation
-	 * registers is its not worked then,
-	 * check with this val 0x1DB6C00D
+	val = readl(NAND_QSPI_MSTR_CONFIG);
+
+#if defined(QSPI_IO_MACRO_DEFAULT_CLK_320MHZ) && !defined(CONFIG_QSPI_SERIAL_TRAINING)
+	default_clk_rate = IO_MACRO_CLK_320_MHZ;
+	val &= ~FB_CLK_BIT;
+#else
+	default_clk_rate = IO_MACRO_CLK_200_MHZ;
+	val |= FB_CLK_BIT;
+#endif
+	if ((readl(QPIC_NAND_CTRL) & BAM_MODE_EN)) {
+
+		bam_add_cmd_element(cmd_list_ptr, NAND_QSPI_MSTR_CONFIG,
+				(uint32_t)val, CE_WRITE_TYPE);
+		cmd_list_ptr++;
+
+		bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_SPI_CFG,
+				(uint32_t)0, CE_WRITE_TYPE);
+		cmd_list_ptr++;
+
+		bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_SPI_CFG,
+				(uint32_t)SPI_CFG_VAL, CE_WRITE_TYPE);
+		cmd_list_ptr++;
+
+		val = SPI_CFG_VAL & ~SPI_LOAD_CLK_CNTR_INIT_EN;
+		bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_SPI_CFG,
+				(uint32_t)val, CE_WRITE_TYPE);
+		cmd_list_ptr++;
+
+		bam_add_one_desc(&bam,
+			CMD_PIPE_INDEX,
+			(unsigned char*)cmd_list_ptr_start,
+			((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
+			BAM_DESC_CMD_FLAG);
+		num_desc++;
+
+		/* Notify BAM HW about the newly added descriptors */
+		bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
+	} else {
+		writel(val, NAND_QSPI_MSTR_CONFIG);
+		writel(0x0, NAND_FLASH_SPI_CFG);
+		writel(SPI_CFG_VAL, NAND_FLASH_SPI_CFG);
+		val = SPI_CFG_VAL & ~SPI_LOAD_CLK_CNTR_INIT_EN;
+		writel(val, NAND_FLASH_SPI_CFG);
+	}
+
+	num_desc = 0;
+
+	/* set the FB_CLK_BIT of register QPIC_QSPI_MSTR_CONFIG
+	 * to by pass the serial training. if this FB_CLK_BIT
+	 * bit enabled then , we can apply upto maximum 200MHz
+	 * input to IO_MACRO_BLOCK.
 	 */
-	writel(SPI_CFG_VAL, NAND_FLASH_SPI_CFG);
-	/*Change LOAD_CLK_CNTR_INIT_EN to generate a pulse,
-	 * with CLK_CNTR_INIT_VAL_VEC loaded and SPI_CFG enabled
-	 * If not worked then,
-	 * Check with this val 0xDB6C00D
-	 */
-	writel((SPI_CFG_VAL & ~SPI_LOAD_CLK_CNTR_INIT_EN),
-			NAND_FLASH_SPI_CFG);
+	qpic_set_clk_rate(default_clk_rate, QPIC_IO_MACRO_CLK,
+			GPLL0_CLK_SRC);
+
+	/*qpic_set_clk_rate(IO_MACRO_CLK_200_MHZ, QPIC_IO_MACRO_CLK,
+			XO_CLK_SRC);*/
 
 	/* According to HPG Setting Xfer steps and spi_num_addr_cycles
 	 * is part of initialization flow before reset.However these
@@ -1464,9 +1641,31 @@
 	/* No of address cycle is same for Giga device & Micron so
 	 * configure no of address cycle now.
 	 */
-	writel(SPI_NUM_ADDR_CYCLES, NAND_SPI_NUM_ADDR_CYCLES);
+	if ((readl(QPIC_NAND_CTRL) & BAM_MODE_EN)) {
+		cmd_list_ptr = ce_array;
+		bam_add_cmd_element(cmd_list_ptr, NAND_SPI_NUM_ADDR_CYCLES,
+				(uint32_t)SPI_NUM_ADDR_CYCLES, CE_WRITE_TYPE);
 
-	writel(SPI_BUSY_CHECK_WAIT_CNT, NAND_SPI_BUSY_CHECK_WAIT_CNT);
+		cmd_list_ptr++;
+
+		bam_add_cmd_element(cmd_list_ptr, NAND_SPI_BUSY_CHECK_WAIT_CNT,
+				(uint32_t)SPI_BUSY_CHECK_WAIT_CNT, CE_WRITE_TYPE);
+
+		cmd_list_ptr++;
+
+		bam_add_one_desc(&bam,
+			CMD_PIPE_INDEX,
+			(unsigned char*)cmd_list_ptr_start,
+			((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
+			BAM_DESC_CMD_FLAG);
+		num_desc++;
+
+		/* Notify BAM HW about the newly added descriptors */
+		bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
+	} else {
+		writel(SPI_NUM_ADDR_CYCLES, NAND_SPI_NUM_ADDR_CYCLES);
+		writel(SPI_BUSY_CHECK_WAIT_CNT, NAND_SPI_BUSY_CHECK_WAIT_CNT);
+	}
 }
 #endif
 static int qpic_nand_reset(struct mtd_info *mtd)
@@ -2993,8 +3192,8 @@
 		}
 
 		if (uncorrectable_err_cws) {
-			nand_ret = qpic_nand_check_erased_page(mtd, page, (ops_datbuf + (j * mtd->writesize)),
-						       ops_oobbuf + j * 64,
+			nand_ret = qpic_nand_check_erased_page(mtd, page + j, (ops_datbuf + (j * mtd->writesize)),
+						       ops_oobbuf,
 						       uncorrectable_err_cws,
 						       &max_bitflips);
 			if (nand_ret < 0)
@@ -3361,7 +3560,6 @@
 
 	start_page = ((to >> chip->page_shift));
 	num_pages = qpic_get_read_page_count(mtd, ops, to);
-
 	while (1) {
 
 		if (num_pages > MAX_MULTI_PAGE) {
@@ -3758,6 +3956,7 @@
 	 * to do it again here.
 	 */
 	cfg.addr0 = page << 16;
+	cfg.addr1 = (page >> 16) & 0xffff;
 	cfg.cmd = 0xA;
 	cfg.cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET |
 			QPIC_SPI_TRANSFER_MODE_X1);
@@ -3915,6 +4114,324 @@
 	chip->scan_bbt = qpic_nand_scan_bbt_nop;
 }
 
+#ifdef CONFIG_QSPI_SERIAL_TRAINING
+static void qpic_reg_write_bam(unsigned int reg, unsigned int val)
+{
+	int num_desc = 0;
+	struct cmd_element *cmd_list_ptr = ce_array;
+	struct cmd_element *cmd_list_ptr_start = ce_array;
+
+	bam_add_cmd_element(cmd_list_ptr, reg,
+				(uint32_t)val, CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	bam_add_one_desc(&bam,
+			CMD_PIPE_INDEX,
+			(unsigned char*)cmd_list_ptr_start,
+			((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
+			BAM_DESC_CMD_FLAG);
+	num_desc++;
+
+	/* Notify BAM HW about the newly added descriptors */
+	bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
+}
+static void qpic_set_phase(int phase)
+{
+	int spi_flash_cfg_val = 0x0;
+
+	int num_desc = 0;
+	struct cmd_element *cmd_list_ptr = ce_array;
+	struct cmd_element *cmd_list_ptr_start = ce_array;
+
+	if (phase < 1 || phase > 7) {
+		printf("%s : wrong phase value\n", __func__);
+		return;
+	}
+	/* get the current value of NAND_FLASH_SPI_CFG register */
+	spi_flash_cfg_val = readl(NAND_FLASH_SPI_CFG);
+	/* set SPI_LOAD_CLK_CNTR_INIT_EN bit */
+	spi_flash_cfg_val |= SPI_LOAD_CLK_CNTR_INIT_EN;
+
+	if ((readl(QPIC_NAND_CTRL) & BAM_MODE_EN)) {
+
+		bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_SPI_CFG,
+				(uint32_t)spi_flash_cfg_val, CE_WRITE_TYPE);
+		cmd_list_ptr++;
+
+		spi_flash_cfg_val &= 0xf000ffff;
+		/* write the phase value for all the line */
+		spi_flash_cfg_val |= ((phase << 16) | (phase << 19) |
+			(phase << 22) | (phase << 25));
+
+		bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_SPI_CFG,
+				(uint32_t)spi_flash_cfg_val, CE_WRITE_TYPE);
+		cmd_list_ptr++;
+		/* clear the SPI_LOAD_CLK_CNTR_INIT_EN bit to load the required
+		 * phase value
+		 */
+		spi_flash_cfg_val &= ~SPI_LOAD_CLK_CNTR_INIT_EN;
+
+		bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_SPI_CFG,
+				(uint32_t)spi_flash_cfg_val, CE_WRITE_TYPE);
+		cmd_list_ptr++;
+
+		bam_add_one_desc(&bam,
+			CMD_PIPE_INDEX,
+			(unsigned char*)cmd_list_ptr_start,
+			((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
+			BAM_DESC_CMD_FLAG);
+		num_desc++;
+
+		/* Notify BAM HW about the newly added descriptors */
+		bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
+	} else {
+		writel(spi_flash_cfg_val, NAND_FLASH_SPI_CFG);
+
+		spi_flash_cfg_val &= 0xf000ffff;
+		/* write the phase value for all the line */
+		spi_flash_cfg_val |= ((phase << 16) | (phase << 19) |
+				(phase << 22) | (phase << 25));
+		writel(spi_flash_cfg_val, NAND_FLASH_SPI_CFG);
+
+		/* clear the SPI_LOAD_CLK_CNTR_INIT_EN bit to load the required
+		 * phase value
+		 */
+		spi_flash_cfg_val &= ~SPI_LOAD_CLK_CNTR_INIT_EN;
+		writel(spi_flash_cfg_val, NAND_FLASH_SPI_CFG);
+	}
+}
+
+static bool IsEven(int num)
+{
+	return (!(num & 1));
+}
+
+static int qpic_find_most_appropriate_phase(u8 *phase_table, int phase_count)
+{
+	int cnt = 0, i;
+	int phase = 0x0;
+	u8 phase_ranges[TOTAL_NUM_PHASE] = {'\0'};
+
+	/*currently we are considering continious 3 phase will
+	 * pass and tke the middle one out of passed three phase.
+	 * if all 7 phase passed so return middle phase i.e 4
+	 */
+	phase_count -= 2;
+	for (i = 0; i < phase_count; i++) {
+		if ((phase_table[i] + 1 == phase_table[i + 1]) &&
+				(phase_table[i + 1] + 1 == phase_table[i + 2])) {
+			phase_ranges[cnt++] = phase_table[i + 1];
+		}
+	}
+
+	/* filter out middle phase
+	 * if cnt is odd then one middle phase
+	 * if cnt is even then two middile phase
+	 * so select lower one
+	 */
+	if (IsEven(cnt)) {
+		phase = phase_ranges[cnt/2 - 1];
+	} else {
+		phase = phase_ranges[cnt/2];
+	}
+
+	return phase;
+}
+
+static int qpic_execute_serial_training(struct mtd_info *mtd)
+{
+	struct qpic_nand_dev *dev = MTD_QPIC_NAND_DEV(mtd);
+	struct nand_chip *chip = MTD_NAND_CHIP(mtd);
+
+	unsigned int start, blk_cnt = 0;
+	unsigned int offset, pageno, curr_freq;
+	int i;
+	unsigned int io_macro_freq_tbl[] = {24000000, 100000000, 200000000, 320000000};
+
+	unsigned char *data_buff, trained_phase[TOTAL_NUM_PHASE] = {'\0'};
+	int phase, phase_cnt, clk_src;
+	int training_seq_cnt = 4;
+	int index = 3, ret, phase_failed=0;
+	u32 start_blocks;
+	u32 size_blocks;
+	loff_t training_offset;
+
+	ret = smem_getpart("0:TRAINING", &start_blocks, &size_blocks);
+	if (ret < 0) {
+		printf("Serial Training part offset not found.\n");
+		return -EIO;
+	}
+
+	training_offset = ((loff_t) mtd->erasesize * start_blocks);
+
+	start = (training_offset >> chip->phys_erase_shift);
+	offset = (start << chip->phys_erase_shift);
+	pageno = (offset >> chip->page_shift);
+
+	clk_src = GPLL0_CLK_SRC;
+	/* At 50Mhz frequency check the bad blocks, if training
+	 * blocks is not bad then only start training else operate
+	 * at 50Mhz with bypassing software serial traning.
+	 */
+	while (qpic_nand_block_isbad(mtd, offset)) {
+		/* block is bad skip this block and goto next
+		 * block
+		 */
+		training_offset += mtd->erasesize;
+		start = (training_offset >> chip->phys_erase_shift);
+		offset = (start << chip->phys_erase_shift);
+		pageno = (offset >> chip->page_shift);
+		blk_cnt++;
+		if (blk_cnt == MAXIMUM_ALLOCATED_TRAINING_BLOCK)
+			break;
+	}
+
+	if (blk_cnt == MAXIMUM_ALLOCATED_TRAINING_BLOCK) {
+		printf("All training blocks are bad skipping serial training\n");
+		ret = -EIO;
+		goto err;
+	}
+
+	ret = qpic_nand_blk_erase(mtd, pageno);
+	if (ret) {
+		printf("error in erasing training block @%x\n",offset);
+		ret = -EIO;
+		goto err;
+	}
+
+	data_buff = (unsigned char *)malloc(mtd->writesize);
+	if (!data_buff) {
+		printf("Errorn in allocating memory.\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	/* prepare clean buffer */
+	memset(data_buff, 0xff, mtd->writesize);
+	for (i = 0; i < mtd->writesize; i += sizeof(training_block_64))
+		memcpy(data_buff + i, training_block_64, sizeof(training_block_64));
+
+	/*write training data to flash */
+	ret = NANDC_RESULT_SUCCESS;
+	struct mtd_oob_ops ops;
+
+	/* write this dumy byte in spare area to avoid bam
+	 * transaction error while writing.
+	 */
+	memset(dev->pad_oob, 0xFF, dev->oob_per_page);
+
+	ops.mode = MTD_OPS_AUTO_OOB;
+	ops.len =  mtd->writesize;
+	ops.retlen = 0;
+	ops.ooblen = dev->oob_per_page;
+	ops.oobretlen = 0;
+	ops.ooboffs = 0;
+	ops.datbuf = (uint8_t *)data_buff;
+	ops.oobbuf = (uint8_t *)dev->pad_oob;
+
+	/* write should be only once */
+	ret = qpic_nand_write_page(mtd, pageno, NAND_CFG, &ops);
+	if (ret) {
+		printf("Error in writing training data..\n");
+		goto free;
+	}
+	/* After write verify the the data with read @ lower frequency
+	 * after that only start serial tarining @ higher frequency
+	 */
+	memset(data_buff, 0xff, mtd->writesize);
+	ops.datbuf = (uint8_t *)data_buff;
+
+	ret = qpic_nand_read_page(mtd, pageno, NAND_CFG, &ops);
+	if (ret) {
+		printf("%s : Read training data failed before training start\n",__func__);
+		goto free;
+	}
+
+	/* compare original data and read data */
+	for (i = 0; i < mtd->writesize; i += sizeof(training_block_64)) {
+		if (memcmp(data_buff + i, training_block_64, sizeof(training_block_64))) {
+			printf("Training data read failed @ lower frequency\n");
+			goto free;
+		}
+	}
+
+	/* disable feed back clock bit to start serial training */
+	qpic_reg_write_bam(NAND_QSPI_MSTR_CONFIG,
+			(~FB_CLK_BIT & readl(NAND_QSPI_MSTR_CONFIG)));
+
+	/* start serial training here */
+	curr_freq = io_macro_freq_tbl[index];
+rettry:
+	phase = 1;
+	phase_cnt = 0;
+
+	/* set frequency, start from higer frequency */
+	if (curr_freq == IO_MACRO_CLK_24MHZ)
+		clk_src = XO_CLK_SRC;
+	qpic_set_clk_rate(curr_freq, QPIC_IO_MACRO_CLK, clk_src);
+
+	do {
+		/* set the phase */
+		qpic_set_phase(phase);
+
+		memset(data_buff, 0, mtd->writesize);
+		ops.datbuf = (uint8_t *)data_buff;
+
+		ret = qpic_nand_read_page(mtd, pageno, NAND_CFG, &ops);
+		if (ret) {
+			printf("%s : Read training data failed.\n",__func__);
+			goto free;
+		}
+		/* compare original data and read data */
+		for (i = 0; i < mtd->writesize; i += sizeof(training_block_64)) {
+			if (memcmp(data_buff + i, training_block_64, sizeof(training_block_64))) {
+				phase_failed++;
+				break;
+			}
+		}
+		if (i == mtd->writesize)
+			trained_phase[phase_cnt++] = phase;
+			/*printf("%s : Found good phase %d\n",__func__,phase);*/
+
+	} while (phase++ < TOTAL_NUM_PHASE);
+
+	if (phase_cnt) {
+		/* Get the appropriate phase */
+		phase = qpic_find_most_appropriate_phase(trained_phase, phase_cnt);
+		qpic_set_phase(phase);
+
+		/* update freq & phase to patch to the kernel */
+		qpic_frequency = curr_freq;
+		qpic_phase = phase;
+	} else {
+		/* lower the the clock frequency
+		 * and try again
+		 */
+		curr_freq = io_macro_freq_tbl[--index];
+		printf("Retry with lower frequency @:%d\n",curr_freq);
+		if (--training_seq_cnt)
+			goto rettry;
+
+		/* Training failed */
+		printf("%s : Serial training failed\n",__func__);
+		ret = -EIO;
+		goto free;
+	}
+
+	/* if phase_failed == 7 it means serial traing failed
+	 * on all the phase. so now we have to go via line by line
+	 * i.e first check for MISO_0, with all the phase value i.e
+	 * 1-7 and then MISO_1 and so on.
+	 * NOTE: But this is the worse case , and it this type of senario
+	 * will not come. if it will come then go with this design.
+	 * ======To DO=====
+	 */
+free:
+	free(data_buff);
+err:
+	return ret;
+}
+#endif
+
 static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
 
 void qpic_nand_init(qpic_nand_cfg_t *qpic_nand_cfg)
@@ -3971,27 +4488,10 @@
 		return;
 	}
 
-#ifdef CONFIG_QPIC_SERIAL
-
-	qpic_spi_init(mtd);
-
-	/* Read the Hardware Version register */
-	hw_ver = readl(NAND_VERSION);
-	/* Only maintain major number */
-	hw_ver >>= 28;
-	if (hw_ver >= QCA_QPIC_V2_1_1) {
-		printf("QPIC controller support serial NAND\n");
-	} else {
-		printf("%s : Qpic controller not support serial NAND\n",
-				__func__);
-		return;
-	}
-
 #ifdef CONFIG_PAGE_SCOPE_MULTI_PAGE_READ
 	config.pipes.status_pipe = NAND_BAM_STATUS_PIPE;
 	config.pipes.status_pipe_grp = NAND_BAM_STATUS_PIPE_GRP;
 #endif
-#endif
 	config.pipes.read_pipe = DATA_PRODUCER_PIPE;
 	config.pipes.write_pipe = DATA_CONSUMER_PIPE;
 	config.pipes.cmd_pipe = CMD_PIPE;
@@ -4007,6 +4507,21 @@
 
 	qpic_bam_init(&config);
 
+#ifdef CONFIG_QPIC_SERIAL
+	qpic_spi_init(mtd);
+
+	/* Read the Hardware Version register */
+	hw_ver = readl(NAND_VERSION);
+	/* Only maintain major number */
+	hw_ver >>= 28;
+	if (hw_ver >= QCA_QPIC_V2_1_1) {
+		printf("QPIC controller support serial NAND\n");
+	} else {
+		printf("%s : Qpic controller not support serial NAND\n",
+				__func__);
+		return;
+	}
+#endif
 	ret = qpic_nand_reset(mtd);
 	if (ret < 0)
 		return;
@@ -4103,6 +4618,36 @@
 	dev->tmp_oobbuf = buf;
 	buf += mtd->oobsize;
 
+#ifdef CONFIG_QSPI_SERIAL_TRAINING
+	/* start serial training here */
+	ret = qpic_execute_serial_training(mtd);
+	if (ret) {
+		printf("Error in serial training.\n");
+		printf("switch back to 50MHz with feed back clock bit enabled\n");
+		if ((readl(QPIC_NAND_CTRL) & BAM_MODE_EN)) {
+			qpic_reg_write_bam(NAND_QSPI_MSTR_CONFIG,
+				(FB_CLK_BIT | readl(NAND_QSPI_MSTR_CONFIG)));
+			qpic_set_clk_rate(IO_MACRO_CLK_200_MHZ, QPIC_IO_MACRO_CLK,
+					GPLL0_CLK_SRC);
+			qpic_reg_write_bam(NAND_FLASH_SPI_CFG, 0x0);
+			qpic_reg_write_bam(NAND_FLASH_SPI_CFG, SPI_CFG_VAL);
+			qpic_reg_write_bam(NAND_FLASH_SPI_CFG,
+					(SPI_CFG_VAL & ~SPI_LOAD_CLK_CNTR_INIT_EN));
+
+		} else {
+			writel((FB_CLK_BIT | readl(NAND_QSPI_MSTR_CONFIG)),
+				NAND_QSPI_MSTR_CONFIG);
+
+			qpic_set_clk_rate(IO_MACRO_CLK_200_MHZ, QPIC_IO_MACRO_CLK,
+					GPLL0_CLK_SRC);
+
+			writel(0x0, NAND_FLASH_SPI_CFG);
+			writel(SPI_CFG_VAL, NAND_FLASH_SPI_CFG);
+			writel((SPI_CFG_VAL & ~SPI_LOAD_CLK_CNTR_INIT_EN),
+				NAND_FLASH_SPI_CFG);
+		}
+	}
+#endif
 	/* Register with MTD subsystem. */
 	ret = nand_register(CONFIG_QPIC_NAND_NAND_INFO_IDX);
 	if (ret < 0) {
diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c
index 4608cba..d35aed2 100644
--- a/drivers/mtd/spi/sf_params.c
+++ b/drivers/mtd/spi/sf_params.c
@@ -37,6 +37,8 @@
 	{"GD25LQ32",	   0xc86016, 0x0,	64 * 1024,    64, RD_NORM,		    SECT_4K},
 	{"GD25Q128",	   0xc84018, 0x0,	64 * 1024,   256, RD_NORM,		    SECT_4K},
 	{"GD25Q256",	   0xc84019, 0x0,	64 * 1024,   512, RD_NORM,		    SECT_4K},
+	{"GD25LB128D",	   0xc86018, 0x0,	 4 * 1024,   4096, RD_NORM,		    SECT_4K},
+	{"GD25LB256E",	   0xc86719, 0x0,	 4 * 1024,   8192, RD_NORM,		    SECT_4K},
 #endif
 #ifdef CONFIG_SPI_FLASH_ISSI		/* ISSI */
 	{"IS25LP032",	   0x9d6016, 0x0,	64 * 1024,    64, RD_NORM,			  0},
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3270843..ee3de33 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -87,7 +87,11 @@
 obj-$(CONFIG_IPQ6018_EDMA) += ipq6018/ipq6018_ppe.o
 obj-$(CONFIG_IPQ6018_EDMA) += ipq6018/ipq6018_uniphy.o
 obj-$(CONFIG_IPQ5018_GMAC) += ipq5018/ipq5018_gmac.o
+obj-$(CONFIG_IPQ5018_GMAC) += ipq5018/ipq5018_uniphy.o
+obj-$(CONFIG_IPQ5018_MDIO) += ipq5018/ipq5018_mdio.o
+obj-$(CONFIG_IPQ5018_GMAC) += ipq5018/athrs17_phy.o
 obj-$(CONFIG_IPQ_MDIO) += ipq_common/ipq_mdio.o
+obj-$(CONFIG_GEPHY) += ipq_common/ipq_gephy.o
 obj-$(CONFIG_QCA8075_PHY) += ipq_common/ipq_qca8075.o
 obj-$(CONFIG_QCA8033_PHY) += ipq_common/ipq_qca8033.o
 obj-$(CONFIG_QCA8081_PHY) += ipq_common/ipq_qca8081.o
diff --git a/drivers/net/ipq5018/athrs17_phy.c b/drivers/net/ipq5018/athrs17_phy.c
new file mode 100644
index 0000000..dbc514f
--- /dev/null
+++ b/drivers/net/ipq5018/athrs17_phy.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2015-2016, 2020 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * Manage the atheros ethernet PHY.
+ *
+ * All definitions in this file are operating system independent!
+ */
+
+#include <common.h>
+#include <asm/arch-ipq5018/athrs17_phy.h>
+
+/*
+ * Externel Common mdio read, PHY Name : IPQ MDIO1
+ */
+
+extern int ipq_mdio_write(int mii_id,
+		int regnum, u16 value);
+extern int ipq_mdio_read(int mii_id,
+		int regnum, ushort *data);
+
+/******************************************************************************
+ * FUNCTION DESCRIPTION: Read switch internal register.
+ *                       Switch internal register is accessed through the
+ *                       MDIO interface. MDIO access is only 16 bits wide so
+ *                       it needs the two time access to complete the internal
+ *                       register access.
+ * INPUT               : register address
+ * OUTPUT              : Register value
+ *
+ *****************************************************************************/
+static uint32_t
+athrs17_reg_read(uint32_t reg_addr)
+{
+	uint32_t reg_word_addr;
+	uint32_t phy_addr, reg_val;
+	uint16_t phy_val;
+	uint16_t tmp_val;
+	uint8_t phy_reg;
+
+	/* change reg_addr to 16-bit word address, 32-bit aligned */
+	reg_word_addr = (reg_addr & 0xfffffffc) >> 1;
+
+	/* configure register high address */
+	phy_addr = 0x18;
+	phy_reg = 0x0;
+	phy_val = (uint16_t) ((reg_word_addr >> 8) & 0x1ff);  /* bit16-8 of reg address */
+	ipq_mdio_write(phy_addr, phy_reg, phy_val);
+	/*
+	 * For some registers such as MIBs, since it is read/clear, we should
+	 * read the lower 16-bit register then the higher one
+	 */
+
+	/* read register in lower address */
+	phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */
+	phy_reg = (uint8_t) (reg_word_addr & 0x1f);   /* bit4-0 of reg address */
+	ipq_mdio_read(phy_addr, phy_reg, &phy_val);
+
+	/* read register in higher address */
+	reg_word_addr++;
+	phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */
+	phy_reg = (uint8_t) (reg_word_addr & 0x1f);   /* bit4-0 of reg address */
+	ipq_mdio_read(phy_addr, phy_reg, &tmp_val);
+	reg_val = (tmp_val << 16 | phy_val);
+
+	return reg_val;
+}
+
+/******************************************************************************
+ * FUNCTION DESCRIPTION: Write switch internal register.
+ *                       Switch internal register is accessed through the
+ *                       MDIO interface. MDIO access is only 16 bits wide so
+ *                       it needs the two time access to complete the internal
+ *                       register access.
+ * INPUT               : register address, value to be written
+ * OUTPUT              : NONE
+ *
+ *****************************************************************************/
+static void
+athrs17_reg_write(uint32_t reg_addr, uint32_t reg_val)
+{
+	uint32_t reg_word_addr;
+	uint32_t phy_addr;
+	uint16_t phy_val;
+	uint8_t phy_reg;
+
+	/* change reg_addr to 16-bit word address, 32-bit aligned */
+	reg_word_addr = (reg_addr & 0xfffffffc) >> 1;
+
+	/* configure register high address */
+	phy_addr = 0x18;
+	phy_reg = 0x0;
+	phy_val = (uint16_t) ((reg_word_addr >> 8) & 0x1ff);  /* bit16-8 of reg address */
+	ipq_mdio_write(phy_addr, phy_reg, phy_val);
+
+	/*
+	 * For some registers such as ARL and VLAN, since they include BUSY bit
+	 * in lower address, we should write the higher 16-bit register then the
+	 * lower one
+	 */
+
+	/* read register in higher address */
+	reg_word_addr++;
+	phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */
+	phy_reg = (uint8_t) (reg_word_addr & 0x1f);   /* bit4-0 of reg address */
+	phy_val = (uint16_t) ((reg_val >> 16) & 0xffff);
+	ipq_mdio_write(phy_addr, phy_reg, phy_val);
+
+	/* write register in lower address */
+	reg_word_addr--;
+	phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */
+	phy_reg = (uint8_t) (reg_word_addr & 0x1f);   /* bit4-0 of reg address */
+	phy_val = (uint16_t) (reg_val & 0xffff);
+	ipq_mdio_write(phy_addr, phy_reg, phy_val);
+}
+
+/*********************************************************************
+ * FUNCTION DESCRIPTION: V-lan configuration given by Switch team
+			 Vlan 1:PHY0,1,2,3 and Mac 6 of s17c
+			 Vlan 2:PHY4 and Mac 0 of s17c
+ * INPUT : NONE
+ * OUTPUT: NONE
+ *********************************************************************/
+void athrs17_vlan_config(void)
+{
+	athrs17_reg_write(S17_P0LOOKUP_CTRL_REG, 0x00140020);
+	athrs17_reg_write(S17_P0VLAN_CTRL0_REG, 0x20001);
+
+	athrs17_reg_write(S17_P1LOOKUP_CTRL_REG, 0x0014005c);
+	athrs17_reg_write(S17_P1VLAN_CTRL0_REG, 0x10001);
+
+	athrs17_reg_write(S17_P2LOOKUP_CTRL_REG, 0x0014005a);
+	athrs17_reg_write(S17_P2VLAN_CTRL0_REG, 0x10001);
+
+	athrs17_reg_write(S17_P3LOOKUP_CTRL_REG, 0x00140056);
+	athrs17_reg_write(S17_P3VLAN_CTRL0_REG, 0x10001);
+
+	athrs17_reg_write(S17_P4LOOKUP_CTRL_REG, 0x0014004e);
+	athrs17_reg_write(S17_P4VLAN_CTRL0_REG, 0x10001);
+
+	athrs17_reg_write(S17_P5LOOKUP_CTRL_REG, 0x00140001);
+	athrs17_reg_write(S17_P5VLAN_CTRL0_REG, 0x20001);
+
+	athrs17_reg_write(S17_P6LOOKUP_CTRL_REG, 0x0014001e);
+	athrs17_reg_write(S17_P6VLAN_CTRL0_REG, 0x10001);
+	printf("%s ...done\n", __func__);
+}
+
+/*******************************************************************
+* FUNCTION DESCRIPTION: Reset S17 register
+* INPUT: NONE
+* OUTPUT: NONE
+*******************************************************************/
+int athrs17_init_switch(void)
+{
+	uint32_t data;
+	uint32_t i = 0;
+
+	/* Reset the switch before initialization */
+	athrs17_reg_write(S17_MASK_CTRL_REG, S17_MASK_CTRL_SOFT_RET);
+	do {
+		udelay(10);
+		data = athrs17_reg_read(S17_MASK_CTRL_REG);
+		i++;
+		if (i == 10){
+			printf("QCA_8337: Failed to reset\n");
+			return -1;
+		}
+	} while (data & S17_MASK_CTRL_SOFT_RET);
+
+	i = 0;
+
+	do {
+		udelay(10);
+		data = athrs17_reg_read(S17_GLOBAL_INT0_REG);
+		i++;
+		if (i == 10)
+			return -1;
+	} while ((data & S17_GLOBAL_INITIALIZED_STATUS) != S17_GLOBAL_INITIALIZED_STATUS);
+
+	return 0;
+}
+
+/*********************************************************************
+ * FUNCTION DESCRIPTION: Configure S17 register
+ * INPUT : NONE
+ * OUTPUT: NONE
+ *********************************************************************/
+void athrs17_reg_init(ipq_gmac_board_cfg_t *gmac_cfg)
+{
+	athrs17_reg_write(S17_MAC_PWR_REG, gmac_cfg->mac_pwr);
+
+	athrs17_reg_write(S17_P0STATUS_REG, (S17_SPEED_1000M |
+						S17_TXMAC_EN |
+						S17_RXMAC_EN |
+						S17_DUPLEX_FULL));
+
+	athrs17_reg_write(S17_GLOFW_CTRL1_REG, (S17_IGMP_JOIN_LEAVE_DPALL |
+						S17_BROAD_DPALL |
+						S17_MULTI_FLOOD_DPALL |
+						S17_UNI_FLOOD_DPALL));
+
+	athrs17_reg_write(S17_P5PAD_MODE_REG, S17_MAC0_RGMII_RXCLK_DELAY);
+
+	athrs17_reg_write(S17_P0PAD_MODE_REG, (S17_MAC0_RGMII_EN |
+						S17_MAC0_RGMII_TXCLK_DELAY |
+						S17_MAC0_RGMII_RXCLK_DELAY |
+					(0x1 << S17_MAC0_RGMII_TXCLK_SHIFT) |
+					(0x2 << S17_MAC0_RGMII_RXCLK_SHIFT)));
+
+	printf("%s: complete\n", __func__);
+}
+
+/*********************************************************************
+ * FUNCTION DESCRIPTION: Configure S17 register
+ * INPUT : NONE
+ * OUTPUT: NONE
+ *********************************************************************/
+void athrs17_reg_init_lan(ipq_gmac_board_cfg_t *gmac_cfg)
+{
+	uint32_t reg_val;
+
+	athrs17_reg_write(S17_P6STATUS_REG, (S17_SPEED_1000M |
+						S17_TXMAC_EN |
+						S17_RXMAC_EN |
+						S17_DUPLEX_FULL));
+
+	athrs17_reg_write(S17_MAC_PWR_REG, gmac_cfg->mac_pwr);
+	reg_val = athrs17_reg_read(S17_P6PAD_MODE_REG);
+	athrs17_reg_write(S17_P6PAD_MODE_REG, (reg_val | S17_MAC6_SGMII_EN));
+
+	athrs17_reg_write(S17_PWS_REG, 0x2613a0);
+
+	athrs17_reg_write(S17_SGMII_CTRL_REG,(S17c_SGMII_EN_PLL |
+					S17c_SGMII_EN_RX |
+					S17c_SGMII_EN_TX |
+					S17c_SGMII_EN_SD |
+					S17c_SGMII_BW_HIGH |
+					S17c_SGMII_SEL_CLK125M |
+					S17c_SGMII_TXDR_CTRL_600mV |
+					S17c_SGMII_CDR_BW_8 |
+					S17c_SGMII_DIS_AUTO_LPI_25M |
+					S17c_SGMII_MODE_CTRL_SGMII_PHY |
+					S17c_SGMII_PAUSE_SG_TX_EN_25M |
+					S17c_SGMII_ASYM_PAUSE_25M |
+					S17c_SGMII_PAUSE_25M |
+					S17c_SGMII_HALF_DUPLEX_25M |
+					S17c_SGMII_FULL_DUPLEX_25M));
+
+	athrs17_reg_write(S17_MODULE_EN_REG, S17_MIB_COUNTER_ENABLE);
+}
+
+struct athrs17_regmap {
+	uint32_t start;
+	uint32_t end;
+};
+
+struct athrs17_regmap regmap[] = {
+	{ 0x000,  0x0e4  },
+	{ 0x100,  0x168  },
+	{ 0x200,  0x270  },
+	{ 0x400,  0x454  },
+	{ 0x600,  0x718  },
+	{ 0x800,  0xb70  },
+	{ 0xC00,  0xC80  },
+	{ 0x1100, 0x11a7 },
+	{ 0x1200, 0x12a7 },
+	{ 0x1300, 0x13a7 },
+	{ 0x1400, 0x14a7 },
+	{ 0x1600, 0x16a7 },
+};
+
+int do_ar8xxx_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(regmap); i++) {
+		uint32_t reg;
+		struct athrs17_regmap *section = &regmap[i];
+
+		for (reg = section->start; reg <= section->end; reg += sizeof(uint32_t)) {
+			uint32_t val = athrs17_reg_read(reg);
+			printf("%03zx: %08zx\n", reg, val);
+		}
+	}
+
+	return 0;
+};
+U_BOOT_CMD(
+	ar8xxx_dump,    1,    1,    do_ar8xxx_dump,
+	"Dump ar8xxx registers",
+	"\n    - print all ar8xxx registers\n"
+);
+
+/*********************************************************************
+ *
+ * FUNCTION DESCRIPTION: This function invokes RGMII,
+ * 			SGMII switch init routines.
+ * INPUT : ipq_gmac_board_cfg_t *
+ * OUTPUT: NONE
+ *
+**********************************************************************/
+int ipq_athrs17_init(ipq_gmac_board_cfg_t *gmac_cfg)
+{
+	int ret;
+
+	if (gmac_cfg == NULL)
+		return -1;
+
+	ret = athrs17_init_switch();
+	if (ret != -1) {
+		athrs17_reg_init(gmac_cfg);
+		athrs17_reg_init_lan(gmac_cfg);
+		athrs17_vlan_config();
+		printf ("S17c init  done\n");
+	}
+
+	return ret;
+}
diff --git a/drivers/net/ipq5018/ipq5018_gmac.c b/drivers/net/ipq5018/ipq5018_gmac.c
new file mode 100644
index 0000000..76f552d
--- /dev/null
+++ b/drivers/net/ipq5018/ipq5018_gmac.c
@@ -0,0 +1,870 @@
+/*
+* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <common.h>
+#include <net.h>
+#include <asm-generic/errno.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <phy.h>
+#include <net.h>
+#include <asm/global_data.h>
+#include "ipq_phy.h"
+#include <asm/arch-ipq5018/ipq5018_gmac.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ipq_info        printf
+#define ipq_dbg         printf
+#define DESC_SIZE       (sizeof(ipq_gmac_desc_t))
+#define DESC_FLUSH_SIZE (((DESC_SIZE + (CONFIG_SYS_CACHELINE_SIZE - 1)) \
+                        / CONFIG_SYS_CACHELINE_SIZE) * \
+                        (CONFIG_SYS_CACHELINE_SIZE))
+
+static struct ipq_eth_dev *ipq_gmac_macs[IPQ5018_GMAC_PORT];
+
+uchar ipq_def_enetaddr[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
+phy_info_t *phy_info[IPQ5018_PHY_MAX] = {0};
+
+extern int ipq_mdio_read(int mii_id, int regnum, ushort *data);
+extern int ipq_mdio_write(int mii_id, int regnum, u16 value);
+extern int ipq5018_mdio_write(int mii_id, int regnum, u16 value);
+extern int ipq5018_mdio_read(int mii_id, int regnum, ushort *data);
+extern int ipq_qca8033_phy_init(struct phy_ops **ops, u32 phy_id);
+extern int ipq_qca8081_phy_init(struct phy_ops **ops, u32 phy_id);
+extern int ipq_gephy_phy_init(struct phy_ops **ops, u32 phy_id);
+extern int ipq_sw_mdio_init(const char *);
+extern int ipq5018_sw_mdio_init(const char *);
+extern void ppe_uniphy_mode_set(uint32_t mode);
+extern int ipq_athrs17_init(ipq_gmac_board_cfg_t *gmac_cfg);
+
+static int ipq_eth_wr_macaddr(struct eth_device *dev)
+{
+	struct ipq_eth_dev *priv = dev->priv;
+	struct eth_mac_regs *mac_p = (struct eth_mac_regs *)priv->mac_regs_p;
+	u32 macid_lo, macid_hi;
+	u8 *mac_id = &dev->enetaddr[0];
+
+	macid_lo = mac_id[0] + (mac_id[1] << 8) +
+		   (mac_id[2] << 16) + (mac_id[3] << 24);
+	macid_hi = mac_id[4] + (mac_id[5] << 8);
+
+	writel(macid_hi, &mac_p->macaddr0hi);
+	writel(macid_lo, &mac_p->macaddr0lo);
+
+	return 0;
+}
+
+static void ipq_mac_reset(struct eth_device *dev)
+{
+	struct ipq_eth_dev *priv = dev->priv;
+	struct eth_dma_regs *dma_reg = (struct eth_dma_regs *)priv->dma_regs_p;
+	u32 val;
+
+	writel(DMAMAC_SRST, &dma_reg->busmode);
+	do {
+		udelay(10);
+		val = readl(&dma_reg->busmode);
+	} while (val & DMAMAC_SRST);
+
+}
+
+static void ipq_eth_mac_cfg(struct eth_device *dev)
+{
+	struct ipq_eth_dev *priv = dev->priv;
+	struct eth_mac_regs *mac_reg = (struct eth_mac_regs *)priv->mac_regs_p;
+	uint speed = 0;
+	uint ipq_mac_cfg = 0;
+	uint ipq_mac_framefilter = 0;
+
+	ipq_mac_framefilter = PROMISCUOUS_MODE_ON;
+
+	if (priv->mac_unit) {
+		if (priv->phy_type == QCA8081_1_1_PHY || priv->phy_type == QCA8033_PHY)
+			speed = priv->speed;
+
+		ipq_mac_cfg |= (FRAME_BURST_ENABLE | JUMBO_FRAME_ENABLE | JABBER_DISABLE |
+				TX_ENABLE | RX_ENABLE | FULL_DUPLEX_ENABLE | speed);
+
+		writel(ipq_mac_cfg, &mac_reg->conf);
+	} else {
+		ipq_mac_cfg |= (priv->speed | FULL_DUPLEX_ENABLE | FRAME_BURST_ENABLE |
+				TX_ENABLE | RX_ENABLE);
+		writel(ipq_mac_cfg, &mac_reg->conf);
+	}
+
+	writel(ipq_mac_framefilter, &mac_reg->framefilt);
+
+}
+
+static void ipq_eth_dma_cfg(struct eth_device *dev)
+{
+	struct ipq_eth_dev *priv = dev->priv;
+	struct eth_dma_regs *dma_reg = (struct eth_dma_regs *)priv->dma_regs_p;
+	uint ipq_dma_bus_mode;
+	uint ipq_dma_op_mode;
+
+	ipq_dma_op_mode = DmaStoreAndForward | DmaRxThreshCtrl128 |
+				DmaTxSecondFrame;
+	ipq_dma_bus_mode = DmaFixedBurstEnable | DmaBurstLength16 |
+				DmaDescriptorSkip0 | DmaDescriptor8Words |
+				DmaArbitPr;
+
+	writel(ipq_dma_bus_mode, &dma_reg->busmode);
+	writel(ipq_dma_op_mode, &dma_reg->opmode);
+}
+
+static void ipq_eth_flw_cntl_cfg(struct eth_device *dev)
+{
+	struct ipq_eth_dev *priv = dev->priv;
+	struct eth_mac_regs *mac_reg = (struct eth_mac_regs *)priv->mac_regs_p;
+	struct eth_dma_regs *dma_reg = (struct eth_dma_regs *)priv->dma_regs_p;
+	uint ipq_dma_flw_cntl;
+	uint ipq_mac_flw_cntl;
+
+	ipq_dma_flw_cntl = DmaRxFlowCtrlAct3K | DmaRxFlowCtrlDeact4K |
+				DmaEnHwFlowCtrl;
+	ipq_mac_flw_cntl = GmacRxFlowControl | GmacTxFlowControl | 0xFFFF0000;
+
+	setbits_le32(&dma_reg->opmode, ipq_dma_flw_cntl);
+	setbits_le32(&mac_reg->flowcontrol, ipq_mac_flw_cntl);
+}
+
+static int ipq_gmac_alloc_fifo(int ndesc, ipq_gmac_desc_t **fifo)
+{
+	int i;
+	void *addr;
+
+	addr = memalign((CONFIG_SYS_CACHELINE_SIZE),
+			(ndesc * DESC_FLUSH_SIZE));
+
+	for (i = 0; i < ndesc; i++) {
+		fifo[i] = (ipq_gmac_desc_t *)((unsigned long)addr +
+			  (i * DESC_FLUSH_SIZE));
+		if (fifo[i] == NULL) {
+			ipq_info("Can't allocate desc fifos\n");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int ipq_gmac_rx_desc_setup(struct ipq_eth_dev  *priv)
+{
+	struct eth_dma_regs *dma_reg = (struct eth_dma_regs *)priv->dma_regs_p;
+	ipq_gmac_desc_t *rxdesc;
+	int i;
+
+	for (i = 0; i < NO_OF_RX_DESC; i++) {
+		rxdesc = priv->desc_rx[i];
+		rxdesc->length |= ((ETH_MAX_FRAME_LEN << DescSize1Shift) &
+					DescSize1Mask);
+		rxdesc->buffer1 = virt_to_phys(net_rx_packets[i]);
+		rxdesc->data1 = (unsigned long)priv->desc_rx[(i + 1) %
+				NO_OF_RX_DESC];
+
+		rxdesc->extstatus = 0;
+		rxdesc->reserved1 = 0;
+		rxdesc->timestamplow = 0;
+		rxdesc->timestamphigh = 0;
+		rxdesc->status = DescOwnByDma;
+
+
+		flush_dcache_range((unsigned long)rxdesc,
+			(unsigned long)rxdesc + DESC_SIZE);
+
+	}
+	/* Assign Descriptor base address to dmadesclist addr reg */
+	writel((uint)priv->desc_rx[0], &dma_reg->rxdesclistaddr);
+
+	return 0;
+}
+
+static int ipq_gmac_tx_rx_desc_ring(struct ipq_eth_dev  *priv)
+{
+	int i;
+	ipq_gmac_desc_t *desc;
+
+	if (ipq_gmac_alloc_fifo(NO_OF_TX_DESC, priv->desc_tx))
+		return -1;
+
+	for (i = 0; i < NO_OF_TX_DESC; i++) {
+		desc = priv->desc_tx[i];
+		memset(desc, 0, DESC_SIZE);
+
+		desc->status =
+		(i == (NO_OF_TX_DESC - 1)) ? TxDescEndOfRing : 0;
+
+		desc->status |= TxDescChain;
+
+		desc->data1 = (unsigned long)priv->desc_tx[(i + 1) %
+				NO_OF_TX_DESC ];
+
+		flush_dcache_range((unsigned long)desc,
+			(unsigned long)desc + DESC_SIZE);
+
+	}
+
+	if (ipq_gmac_alloc_fifo(NO_OF_RX_DESC, priv->desc_rx))
+		return -1;
+
+	for (i = 0; i < NO_OF_RX_DESC; i++) {
+		desc = priv->desc_rx[i];
+		memset(desc, 0, DESC_SIZE);
+		desc->length =
+		(i == (NO_OF_RX_DESC - 1)) ? RxDescEndOfRing : 0;
+		desc->length |= RxDescChain;
+
+		desc->data1 = (unsigned long)priv->desc_rx[(i + 1) %
+				NO_OF_RX_DESC];
+
+		flush_dcache_range((unsigned long)desc,
+			(unsigned long)desc + DESC_SIZE);
+
+	}
+
+	priv->next_tx = 0;
+	priv->next_rx = 0;
+
+	return 0;
+}
+
+static inline void ipq_gmac_give_to_dma(ipq_gmac_desc_t *fr)
+{
+	fr->status |= DescOwnByDma;
+}
+
+static inline u32 ipq_gmac_owned_by_dma(ipq_gmac_desc_t *fr)
+{
+	return (fr->status & DescOwnByDma);
+}
+
+static inline u32 ipq_gmac_is_desc_empty(ipq_gmac_desc_t *fr)
+{
+	return ((fr->length & DescSize1Mask) == 0);
+}
+
+static void ipq5018_gmac0_speed_clock_set(int speed_clock1,
+	int speed_clock2, int gmacid)
+{
+	int iTxRx;
+	uint32_t reg_value;
+	/*
+	 * iTxRx indicates Tx and RX register
+	 * 0 = Rx and 1 = Tx
+	 */
+	for (iTxRx = 0; iTxRx < 2; ++iTxRx){
+		/* gcc port first clock divider */
+		reg_value = 0;
+		reg_value = readl(GCC_GMAC0_RX_CFG_RCGR +
+				(iTxRx * 8) + (gmacid * 0x10));
+		reg_value &= ~0x1f;
+		reg_value |= speed_clock1;
+		writel(reg_value, GCC_GMAC0_RX_CFG_RCGR +
+				(iTxRx * 8) + (gmacid * 0x10));
+		/* gcc port second clock divider */
+		reg_value = 0;
+		reg_value = readl(GCC_GMAC0_RX_MISC +
+				(iTxRx * 4) + (gmacid * 0x10));
+		reg_value &= ~0xf;
+		reg_value |= speed_clock2;
+		writel(reg_value, GCC_GMAC0_RX_MISC +
+				(iTxRx * 4) + (gmacid * 0x10));
+		/* update above clock configuration */
+		reg_value = 0;
+		reg_value = readl(GCC_GMAC0_RX_CMD_RCGR +
+				(iTxRx * 8) + (gmacid * 0x10));
+		reg_value &= ~0x1;
+		reg_value |= 0x1;
+		writel(reg_value, GCC_GMAC0_RX_CMD_RCGR +
+				(iTxRx * 8) + (gmacid * 0x10));
+	}
+}
+
+static void ipq5018_enable_gephy(void)
+{
+	uint32_t reg_val;
+
+	reg_val = readl(GCC_GEPHY_RX_CBCR);
+	reg_val |= GCC_CBCR_CLK_ENABLE;
+	writel(reg_val, GCC_GEPHY_RX_CBCR);
+	mdelay(20);
+
+	reg_val = readl(GCC_GEPHY_TX_CBCR);
+	reg_val |= GCC_CBCR_CLK_ENABLE;
+	writel(reg_val, GCC_GEPHY_TX_CBCR);
+	mdelay(20);
+}
+
+static int ipq5018_s17c_Link_Update(struct ipq_eth_dev *priv)
+{
+	uint16_t phy_data;
+	int status = 1;
+
+	for(int i = 0;
+		i < priv->gmac_board_cfg->switch_port_count; ++i){
+		phy_data = ipq_mdio_read(
+			priv->gmac_board_cfg->switch_port_phy_address[i],
+			0x11,
+			NULL);
+
+		if (phy_data == 0x50)
+			continue;
+
+		/* Atleast one port should be link up*/
+		if (phy_data & LINK_UP)
+			status = 0;
+
+		printf("Port%d %s ", i + 1, LINK(phy_data));
+
+		switch(SPEED(phy_data)){
+		case SPEED_1000M:
+			printf("Speed :1000M ");
+			break;
+		case SPEED_100M:
+			printf("Speed :100M ");
+			break;
+		default:
+			printf("Speed :10M ");
+		}
+
+		printf ("%s \n", DUPLEX(phy_data));
+	}
+	return status;
+}
+
+static int ipq5018_phy_link_update(struct eth_device *dev)
+{
+	struct ipq_eth_dev *priv = dev->priv;
+	u8 status = 1;
+	struct phy_ops *phy_get_ops;
+	fal_port_speed_t speed;
+	fal_port_duplex_t duplex;
+	char *lstatus[] = {"up", "Down"};
+	char *dp[] = {"Half", "Full"};
+	int speed_clock1 = 0, speed_clock2 = 0;
+	int mode = PORT_WRAPPER_SGMII0_RGMII4;
+
+	phy_get_ops = priv->ops;
+
+	if (priv->ipq_swith) {
+		speed_clock1 = 1;
+		speed_clock2 = 0;
+		status = ipq5018_s17c_Link_Update(priv);
+	}
+
+	if (phy_get_ops != NULL &&
+		phy_get_ops->phy_get_link_status != NULL &&
+		phy_get_ops->phy_get_speed != NULL &&
+		phy_get_ops->phy_get_duplex != NULL){
+
+		status = phy_get_ops->phy_get_link_status(priv->mac_unit,
+				priv->phy_address);
+		phy_get_ops->phy_get_speed(priv->mac_unit,
+				priv->phy_address, &speed);
+		phy_get_ops->phy_get_duplex(priv->mac_unit,
+				priv->phy_address, &duplex);
+
+		switch (speed) {
+		case FAL_SPEED_10:
+			speed_clock1 = 9;
+			speed_clock2 = 9;
+			priv->speed = MII_PORT_SELECT;
+			printf ("eth%d  %s Speed :%d %s duplex\n",
+					priv->mac_unit,
+					lstatus[status], speed,
+					dp[duplex]);
+			break;
+		case FAL_SPEED_100:
+			priv->speed = MII_PORT_SELECT | FES_PORT_SPEED;
+			speed_clock1 = 9;
+			speed_clock2 = 0;
+			printf ("eth%d %s Speed :%d %s duplex\n",
+					priv->mac_unit,
+					lstatus[status], speed,
+					dp[duplex]);
+			break;
+		case FAL_SPEED_1000:
+			priv->speed = SGMII_PORT_SELECT;
+			speed_clock1 = 1;
+			speed_clock2 = 0;
+			printf ("eth%d %s Speed :%d %s duplex\n",
+					priv->mac_unit,
+					lstatus[status], speed,
+					dp[duplex]);
+			break;
+		case FAL_SPEED_2500:
+			priv->speed = SGMII_PORT_SELECT;
+			mode = PORT_WRAPPER_SGMII_PLUS;
+			speed_clock1 = 1;
+			speed_clock2 = 0;
+			printf ("eth%d %s Speed :%d %s duplex\n",
+					priv->mac_unit,
+					lstatus[status], speed,
+					dp[duplex]);
+			break;
+		default:
+			printf("Unknown speed\n");
+			break;
+		}
+	}
+
+	if (status) {
+		/* No PHY link is alive */
+		if (priv->ipq_swith == 0 && phy_get_ops == NULL)
+			printf("Link status/Get speed/Get duplex not mapped\n");
+		return -1;
+	}
+
+	if (priv->mac_unit){
+		ppe_uniphy_mode_set(mode);
+	} else {
+		ipq5018_enable_gephy();
+	}
+
+	ipq5018_gmac0_speed_clock_set(speed_clock1, speed_clock2, priv->mac_unit);
+
+	return 0;
+}
+
+int ipq_eth_init(struct eth_device *dev, bd_t *this)
+{
+	struct ipq_eth_dev *priv = dev->priv;
+	struct eth_dma_regs *dma_reg = (struct eth_dma_regs *)priv->dma_regs_p;
+	u32 data;
+
+	if(ipq5018_phy_link_update(dev) < 0) {
+		return -1;
+	}
+
+	priv->next_rx = 0;
+	priv->next_tx = 0;
+
+	ipq_mac_reset(dev);
+	ipq_eth_wr_macaddr(dev);
+
+	/* DMA, MAC configuration for Synopsys GMAC */
+	ipq_eth_dma_cfg(dev);
+	ipq_eth_mac_cfg(dev);
+	ipq_eth_flw_cntl_cfg(dev);
+
+	/* clear all pending interrupts if any */
+	data = readl(&dma_reg->status);
+	writel(data, &dma_reg->status);
+
+	/* Setup Rx fifos and assign base address to */
+	ipq_gmac_rx_desc_setup(priv);
+
+	writel((uint)priv->desc_tx[0], &dma_reg->txdesclistaddr);
+	setbits_le32(&dma_reg->opmode, (RXSTART));
+	setbits_le32(&dma_reg->opmode, (TXSTART));
+
+	return 1;
+}
+
+static int ipq_eth_send(struct eth_device *dev, void *packet, int length)
+{
+	struct ipq_eth_dev *priv = dev->priv;
+	struct eth_dma_regs *dma_p = (struct eth_dma_regs *)priv->dma_regs_p;
+	ipq_gmac_desc_t *txdesc = priv->desc_tx[priv->next_tx];
+	int i;
+
+	invalidate_dcache_range((unsigned long)txdesc,
+		       (unsigned long)txdesc + DESC_FLUSH_SIZE);
+
+	/* Check if the dma descriptor is still owned by DMA */
+	if (ipq_gmac_owned_by_dma(txdesc)) {
+		ipq_info("BUG: Tx descriptor is owned by DMA %p\n", txdesc);
+		return NETDEV_TX_BUSY;
+	}
+
+	txdesc->length |= ((length <<DescSize1Shift) & DescSize1Mask);
+	txdesc->status |= (DescTxFirst | DescTxLast | DescTxIntEnable);
+	txdesc->buffer1 = virt_to_phys(packet);
+	ipq_gmac_give_to_dma(txdesc);
+
+	flush_dcache_range((unsigned long)txdesc,
+			(unsigned long)txdesc + DESC_SIZE);
+
+	flush_dcache_range((unsigned long)(txdesc->buffer1),
+		(unsigned long)(txdesc->buffer1) + PKTSIZE_ALIGN);
+
+	/* Start the transmission */
+	writel(POLL_DATA, &dma_p->txpolldemand);
+
+	for (i = 0; i < MAX_WAIT; i++) {
+
+		udelay(10);
+
+		invalidate_dcache_range((unsigned long)txdesc,
+		(unsigned long)txdesc + DESC_FLUSH_SIZE);
+
+		if (!ipq_gmac_owned_by_dma(txdesc))
+			break;
+	}
+
+	if (i == MAX_WAIT) {
+		ipq_info("Tx Timed out\n");
+	}
+
+	/* reset the descriptors */
+	txdesc->status = (priv->next_tx == (NO_OF_TX_DESC - 1)) ?
+	TxDescEndOfRing : 0;
+	txdesc->status |= TxDescChain;
+	txdesc->length = 0;
+	txdesc->buffer1 = 0;
+
+	priv->next_tx = (priv->next_tx + 1) % NO_OF_TX_DESC;
+
+	txdesc->data1 = (unsigned long)priv->desc_tx[priv->next_tx];
+
+
+	flush_dcache_range((unsigned long)txdesc,
+			(unsigned long)txdesc + DESC_SIZE);
+
+	return 0;
+}
+
+static int ipq_eth_recv(struct eth_device *dev)
+{
+	struct ipq_eth_dev *priv = dev->priv;
+	struct eth_dma_regs *dma_p = (struct eth_dma_regs *)priv->dma_regs_p;
+	int length = 0;
+	ipq_gmac_desc_t *rxdesc = priv->desc_rx[priv->next_rx];
+	uint status;
+
+	invalidate_dcache_range((unsigned long)(priv->desc_rx[0]),
+			(unsigned long)(priv->desc_rx[NO_OF_RX_DESC - 1]) +
+			DESC_FLUSH_SIZE);
+
+	for (rxdesc = priv->desc_rx[priv->next_rx];
+		!ipq_gmac_owned_by_dma(rxdesc);
+		rxdesc = priv->desc_rx[priv->next_rx]) {
+
+		status = rxdesc->status;
+		length = ((status & DescFrameLengthMask) >>
+				DescFrameLengthShift);
+
+		invalidate_dcache_range(
+			(unsigned long)(net_rx_packets[priv->next_rx]),
+			(unsigned long)(net_rx_packets[priv->next_rx]) +
+			PKTSIZE_ALIGN);
+		net_process_received_packet(net_rx_packets[priv->next_rx], length - 4);
+
+		rxdesc->length = ((ETH_MAX_FRAME_LEN << DescSize1Shift) &
+				   DescSize1Mask);
+
+		rxdesc->length |= (priv->next_rx == (NO_OF_RX_DESC - 1)) ?
+					RxDescEndOfRing : 0;
+		rxdesc->length |= RxDescChain;
+
+		rxdesc->buffer1 = virt_to_phys(net_rx_packets[priv->next_rx]);
+
+		priv->next_rx = (priv->next_rx + 1) % NO_OF_RX_DESC;
+
+		rxdesc->data1 = (unsigned long)priv->desc_rx[priv->next_rx];
+
+		rxdesc->extstatus = 0;
+		rxdesc->reserved1 = 0;
+		rxdesc->timestamplow = 0;
+		rxdesc->timestamphigh = 0;
+		rxdesc->status = DescOwnByDma;
+
+		flush_dcache_range((unsigned long)rxdesc,
+			(unsigned long)rxdesc + DESC_SIZE);
+
+		writel(POLL_DATA, &dma_p->rxpolldemand);
+	}
+
+	return length;
+}
+
+static void ipq_eth_halt(struct eth_device *dev)
+{
+	if (dev->state != ETH_STATE_ACTIVE)
+		return;
+	/* reset the mac */
+	ipq_mac_reset(dev);
+}
+
+static int QCA8337_switch_init(ipq_gmac_board_cfg_t *gmac_cfg)
+{
+	for (int port = 0;
+		port < gmac_cfg->switch_port_count;
+		++port) {
+		u32 phy_val;
+		/* phy powerdown */
+		ipq_mdio_write(
+			gmac_cfg->switch_port_phy_address[port],
+			0x0,
+			0x0800
+			);
+		phy_val = ipq_mdio_read(
+				gmac_cfg->switch_port_phy_address[port],
+				0x3d,
+				NULL
+				);
+		phy_val &= ~0x0040;
+		ipq_mdio_write(
+			gmac_cfg->switch_port_phy_address[port],
+			0x3d,
+			phy_val
+			);
+		/*
+		* PHY will stop the tx clock for a while when link is down
+		* en_anychange  debug port 0xb bit13 = 0  //speed up link down tx_clk
+		* sel_rst_80us  debug port 0xb bit10 = 0  //speed up speed mode change to 2'b10 tx_clk
+		*/
+		phy_val = ipq_mdio_read(
+				gmac_cfg->switch_port_phy_address[port],
+				0xb,
+				NULL
+				);
+		phy_val &= ~0x2400;
+		ipq_mdio_write(
+			gmac_cfg->switch_port_phy_address[port],
+			0xb,
+			phy_val
+			);
+		mdelay(100);
+	}
+	if (ipq_athrs17_init(gmac_cfg) != 0){
+		printf("QCA_8337 switch init failed \n");
+		return 0;
+	}
+	for (int port = 0;
+		port < gmac_cfg->switch_port_count;
+		++port) {
+		ipq_mdio_write(
+			gmac_cfg->switch_port_phy_address[port],
+			MII_ADVERTISE,
+			ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM
+			);
+		/* phy reg 0x9, b10,1 = Prefer multi-port device (master) */
+		ipq_mdio_write(
+			gmac_cfg->switch_port_phy_address[port],
+			MII_CTRL1000,
+			(0x0400|ADVERTISE_1000FULL)
+			);
+		ipq_mdio_write(
+			gmac_cfg->switch_port_phy_address[port],
+			MII_BMCR,
+			BMCR_RESET | BMCR_ANENABLE
+			);
+		mdelay(100);
+	}
+	return 1;
+}
+
+static void gephy_mdac_edac_config(ipq_gmac_board_cfg_t *gmac_cfg)
+{
+	uint16_t phy_data;
+	uint32_t phy_dac = PHY_DAC(0x10);
+	uint32_t C45_id = QCA808X_REG_C45_ADDRESS(MPGE_PHY_MMD1_NUM,
+				MPGE_PHY_MMD1_DAC);
+	/*set mdac value*/
+	phy_data = ipq5018_mdio_read(
+			gmac_cfg->phy_addr,
+			C45_id,
+			NULL
+			);
+	phy_data &= ~(MPGE_PHY_MMD1_DAC_MASK);
+	ipq5018_mdio_write(
+		gmac_cfg->phy_addr,
+		C45_id,
+		(phy_data | phy_dac)
+		);
+	mdelay(1);
+	/*set edac value*/
+	phy_data = ipq5018_mdio_read(
+			gmac_cfg->phy_addr,
+			MPGE_PHY_DEBUG_EDAC,
+			NULL
+			);
+	phy_data &= ~(MPGE_PHY_MMD1_DAC_MASK);
+	ipq5018_mdio_write(
+		gmac_cfg->phy_addr,
+		MPGE_PHY_DEBUG_EDAC,
+		(phy_data | phy_dac)
+		);
+	mdelay(1);
+}
+
+static void mdio_init(void)
+{
+	if(ipq5018_sw_mdio_init("IPQ MDIO0"))
+		printf("MDIO Failed to init for GMAC0\n");
+
+	if(ipq_sw_mdio_init("IPQ MDIO1"))
+		printf("MDIO Failed to init for GMAC1\n");
+}
+
+int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg)
+{
+	struct eth_device *dev[CONFIG_IPQ_NO_MACS];
+	uchar enet_addr[CONFIG_IPQ_NO_MACS * 6];
+	int i;
+	uint32_t phy_chip_id, phy_chip_id1, phy_chip_id2;
+	int ret;
+	memset(enet_addr, 0, sizeof(enet_addr));
+
+	/* Mdio init */
+	mdio_init();
+
+	/* Getting the MAC address from ART partition */
+	ret = get_eth_mac_address(enet_addr, CONFIG_IPQ_NO_MACS);
+
+	for (i = 0; gmac_cfg_is_valid(gmac_cfg); gmac_cfg++, i++) {
+
+		dev[i] = malloc(sizeof(struct eth_device));
+		if (dev[i] == NULL)
+			goto init_failed;
+
+		ipq_gmac_macs[i] = malloc(sizeof(struct ipq_eth_dev));
+		if (ipq_gmac_macs[i] == NULL)
+			goto init_failed;
+
+		memset(dev[i], 0, sizeof(struct eth_device));
+		memset(ipq_gmac_macs[i], 0, sizeof(struct ipq_eth_dev));
+
+		dev[i]->iobase = gmac_cfg->base;
+		dev[i]->init = ipq_eth_init;
+		dev[i]->halt = ipq_eth_halt;
+		dev[i]->recv = ipq_eth_recv;
+		dev[i]->send = ipq_eth_send;
+		dev[i]->write_hwaddr = ipq_eth_wr_macaddr;
+		dev[i]->priv = (void *) ipq_gmac_macs[i];
+		/*
+		 * Setting the Default MAC address
+		 * if the MAC read from ART partition is invalid
+		 */
+		if ((ret < 0) ||
+			(!is_valid_ethaddr(&enet_addr[i * 6]))) {
+				memcpy(&dev[i]->enetaddr[0], ipq_def_enetaddr, 6);
+				dev[i]->enetaddr[5] = dev[i]->enetaddr[5] +  i;
+		} else {
+			memcpy(&dev[i]->enetaddr[0], &enet_addr[i * 6], 6);
+		}
+
+		ipq_info("MAC%x addr:%x:%x:%x:%x:%x:%x\n",
+			gmac_cfg->unit, dev[i]->enetaddr[0],
+			dev[i]->enetaddr[1],
+			dev[i]->enetaddr[2],
+			dev[i]->enetaddr[3],
+			dev[i]->enetaddr[4],
+			dev[i]->enetaddr[5]);
+
+		snprintf(dev[i]->name, sizeof(dev[i]->name), "eth%d", i);
+
+		ipq_gmac_macs[i]->dev = dev[i];
+		ipq_gmac_macs[i]->mac_unit = gmac_cfg->unit;
+		ipq_gmac_macs[i]->mac_regs_p =
+			(struct eth_mac_regs *)(gmac_cfg->base);
+		ipq_gmac_macs[i]->dma_regs_p =
+			(struct eth_dma_regs *)(gmac_cfg->base + DW_DMA_BASE_OFFSET);
+		ipq_gmac_macs[i]->phy_address = gmac_cfg->phy_addr;
+		ipq_gmac_macs[i]->gmac_board_cfg = gmac_cfg;
+		ipq_gmac_macs[i]->interface = gmac_cfg->phy_interface_mode;
+		ipq_gmac_macs[i]->phy_type = gmac_cfg->phy_type;
+		ipq_gmac_macs[i]->phy_external_link = gmac_cfg->phy_external_link;
+
+		snprintf((char *)ipq_gmac_macs[i]->phy_name,
+				sizeof(ipq_gmac_macs[i]->phy_name), "IPQ MDIO%d", i);
+
+		if (gmac_cfg->unit){
+			phy_chip_id1 = ipq_mdio_read(
+					ipq_gmac_macs[i]->phy_address,
+					QCA_PHY_ID1,
+					NULL);
+			phy_chip_id2 = ipq_mdio_read(
+					ipq_gmac_macs[i]->phy_address,
+					QCA_PHY_ID2,
+					NULL);
+			phy_chip_id = (phy_chip_id1 << 16) | phy_chip_id2;
+		} else {
+			phy_chip_id1 = ipq5018_mdio_read(
+					ipq_gmac_macs[i]->phy_address,
+					QCA_PHY_ID1,
+					NULL);
+			phy_chip_id2 = ipq5018_mdio_read(
+					ipq_gmac_macs[i]->phy_address,
+					QCA_PHY_ID2,
+					NULL);
+			phy_chip_id = (phy_chip_id1 << 16) | phy_chip_id2;
+		}
+		switch(phy_chip_id) {
+#ifdef CONFIG_QCA8081_PHY
+			/* NAPA PHY For GMAC1 */
+			case QCA8081_PHY:
+			case QCA8081_1_1_PHY:
+				ipq_gmac_macs[i]->phy_type = QCA8081_1_1_PHY;
+				ipq_qca8081_phy_init(
+					&ipq_gmac_macs[i]->ops,
+					ipq_gmac_macs[i]->phy_address);
+				break;
+#endif
+			/* Internel GEPHY only for GMAC0 */
+			case GEPHY:
+				ipq_gmac_macs[i]->phy_type = GEPHY;
+				ipq_gephy_phy_init(
+					&ipq_gmac_macs[i]->ops,
+					ipq_gmac_macs[i]->phy_address);
+				if(ipq_gmac_macs[i]->phy_external_link)
+					gephy_mdac_edac_config(gmac_cfg);
+				break;
+#ifdef CONFIG_QCA8033_PHY
+			/* 1G PHY */
+			case QCA8033_PHY:
+				ipq_gmac_macs[i]->phy_type = QCA8033_PHY;
+				ipq_qca8033_phy_init(
+					&ipq_gmac_macs[i]->ops,
+					ipq_gmac_macs[i]->phy_address);
+				break;
+#endif
+			case QCA_8337:
+				if(gmac_cfg->ipq_swith){
+					ipq_gmac_macs[i]->ipq_swith =
+						QCA8337_switch_init(gmac_cfg);
+				}
+				break;
+			default:
+				printf("GMAC%d:Invalid PHY ID \n", i);
+				break;
+		}
+		/* Initialize 8337 switch */
+		if (gmac_cfg->ipq_swith &&
+			ipq_gmac_macs[i]->phy_external_link &&
+			!ipq_gmac_macs[i]->ipq_swith){
+			ipq_gmac_macs[i]->ipq_swith =
+				QCA8337_switch_init(gmac_cfg);
+		}
+		/* Tx/Rx Descriptor initialization */
+		if (ipq_gmac_tx_rx_desc_ring(dev[i]->priv) == -1)
+			goto init_failed;
+
+		eth_register(dev[i]);
+	}
+	return 0;
+
+init_failed:
+	for (i = 0; i < IPQ5018_GMAC_PORT; i++) {
+		if (dev[i]) {
+			free(dev[i]);
+		}
+		if (ipq_gmac_macs[i])
+			free(ipq_gmac_macs[i]);
+	}
+
+	return -ENOMEM;
+}
+
diff --git a/drivers/net/ipq5018/ipq5018_mdio.c b/drivers/net/ipq5018/ipq5018_mdio.c
new file mode 100644
index 0000000..8f4bf24
--- /dev/null
+++ b/drivers/net/ipq5018/ipq5018_mdio.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2015-2017, 2020 The Linux Foundation. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <common.h>
+#include <command.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <asm/io.h>
+#include <errno.h>
+#include "ipq5018_mdio.h"
+
+struct ipq5018_mdio_data {
+	struct mii_bus *bus;
+	int phy_irq[PHY_MAX_ADDR];
+};
+
+static int ipq5018_mdio_wait_busy(void)
+{
+	int i;
+	u32 busy;
+	for (i = 0; i < IPQ5018_MDIO_RETRY; i++) {
+		udelay(IPQ5018_MDIO_DELAY);
+		busy = readl(IPQ5018_MDIO_BASE +
+			MDIO_CTRL_4_REG) &
+			MDIO_CTRL_4_ACCESS_BUSY;
+
+		if (!busy)
+			return 0;
+		udelay(IPQ5018_MDIO_DELAY);
+	}
+	printf("%s: MDIO operation timed out\n",
+			__func__);
+	return -ETIMEDOUT;
+}
+
+int ipq5018_mdio_write(int mii_id, int regnum, u16 value)
+{
+	u32 cmd;
+	if (ipq5018_mdio_wait_busy())
+		return -ETIMEDOUT;
+
+
+	if (regnum & MII_ADDR_C45) {
+		unsigned int mmd = (regnum >> 16) & 0x1F;
+	        unsigned int reg = regnum & 0xFFFF;
+
+		writel(CTRL_0_REG_C45_DEFAULT_VALUE,
+			IPQ5018_MDIO_BASE + MDIO_CTRL_0_REG);
+
+		/* Issue the phy address and reg */
+		writel((mii_id << 8) | mmd,
+			IPQ5018_MDIO_BASE + MDIO_CTRL_1_REG);
+
+		writel(reg, IPQ5018_MDIO_BASE + MDIO_CTRL_2_REG);
+
+		/* issue read command */
+		cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_C45_ADDR;
+
+		writel(cmd, IPQ5018_MDIO_BASE + MDIO_CTRL_4_REG);
+
+		if (ipq5018_mdio_wait_busy())
+			return -ETIMEDOUT;
+	} else {
+		writel(CTRL_0_REG_DEFAULT_VALUE,
+			IPQ5018_MDIO_BASE + MDIO_CTRL_0_REG);
+
+		/* Issue the phy addreass and reg */
+		writel((mii_id << 8 | regnum),
+			IPQ5018_MDIO_BASE + MDIO_CTRL_1_REG);
+	}
+
+	/* Issue a write data */
+	writel(value, IPQ5018_MDIO_BASE + MDIO_CTRL_2_REG);
+
+	if (regnum & MII_ADDR_C45) {
+		cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_C45_WRITE ;
+	} else {
+		cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_WRITE ;
+	}
+
+	writel(cmd, IPQ5018_MDIO_BASE + MDIO_CTRL_4_REG);
+	/* Wait for write complete */
+
+	if (ipq5018_mdio_wait_busy())
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+int ipq5018_mdio_read(int mii_id, int regnum, ushort *data)
+{
+	u32 val,cmd;
+	if (ipq5018_mdio_wait_busy())
+		return -ETIMEDOUT;
+
+	if (regnum & MII_ADDR_C45) {
+
+		unsigned int mmd = (regnum >> 16) & 0x1F;
+	        unsigned int reg = regnum & 0xFFFF;
+
+		writel(CTRL_0_REG_C45_DEFAULT_VALUE,
+			IPQ5018_MDIO_BASE + MDIO_CTRL_0_REG);
+
+		/* Issue the phy address and reg */
+		writel((mii_id << 8) | mmd,
+			IPQ5018_MDIO_BASE + MDIO_CTRL_1_REG);
+
+
+		writel(reg, IPQ5018_MDIO_BASE + MDIO_CTRL_2_REG);
+
+		/* issue read command */
+		cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_C45_ADDR;
+	} else {
+
+		writel(CTRL_0_REG_DEFAULT_VALUE,
+			IPQ5018_MDIO_BASE + MDIO_CTRL_0_REG);
+
+		/* Issue the phy address and reg */
+		writel((mii_id << 8 | regnum ) ,
+			IPQ5018_MDIO_BASE + MDIO_CTRL_1_REG);
+
+		/* issue read command */
+		cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_READ ;
+	}
+
+	/* issue read command */
+	writel(cmd, IPQ5018_MDIO_BASE + MDIO_CTRL_4_REG);
+
+	if (ipq5018_mdio_wait_busy())
+		return -ETIMEDOUT;
+
+
+	 if (regnum & MII_ADDR_C45) {
+		cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_C45_READ;
+		writel(cmd, IPQ5018_MDIO_BASE + MDIO_CTRL_4_REG);
+
+		if (ipq5018_mdio_wait_busy())
+			return -ETIMEDOUT;
+	}
+
+	/* Read data */
+	val = readl(IPQ5018_MDIO_BASE + MDIO_CTRL_3_REG);
+
+	if (data != NULL)
+		*data = val;
+
+	return val;
+}
+
+int ipq5018_phy_write(struct mii_dev *bus,
+		int addr, int dev_addr,
+		int regnum, ushort value)
+{
+	return ipq5018_mdio_write(addr, regnum, value);
+}
+
+int ipq5018_phy_read(struct mii_dev *bus,
+		int addr, int dev_addr, int regnum)
+{
+	return ipq5018_mdio_read(addr, regnum, NULL);
+}
+
+int ipq5018_sw_mdio_init(const char *name)
+{
+	struct mii_dev *bus = mdio_alloc();
+	if(!bus) {
+		printf("Failed to allocate IPQ5018 MDIO bus\n");
+		return -1;
+	}
+	bus->read = ipq5018_phy_read;
+	bus->write = ipq5018_phy_write;
+	bus->reset = NULL;
+	snprintf(bus->name, MDIO_NAME_LEN, name);
+	return mdio_register(bus);
+}
+
+static int do_ipq5018_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char		op[2];
+	unsigned int	addr = 0, reg = 0;
+	unsigned short	data = 0;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	op[0] = argv[1][0];
+	if (strlen(argv[1]) > 1)
+		op[1] = argv[1][1];
+	else
+		op[1] = '\0';
+
+	if (argc >= 3)
+		addr = simple_strtoul(argv[2], NULL, 16);
+	if (argc >= 4)
+		reg = simple_strtoul(argv[3], NULL, 16);
+	if (argc >= 5)
+		data = simple_strtoul(argv[4], NULL, 16);
+
+	if (op[0] == 'r') {
+		data = ipq5018_mdio_read(addr, reg, NULL);
+		printf("0x%x\n", data);
+	} else if (op[0] == 'w') {
+		ipq5018_mdio_write(addr, reg, data);
+	} else {
+		return CMD_RET_USAGE;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	ipq5018_mdio, 5, 1, do_ipq5018_mdio,
+	"IPQ5018 mdio utility commands",
+	"ipq5018_mdio read   <addr> <reg>               - read  IPQ5018 MDIO PHY <addr> register <reg>\n"
+	"ipq5018_mdio write  <addr> <reg> <data>        - write IPQ5018 MDIO PHY <addr> register <reg>\n"
+	"Addr and/or reg may be ranges, e.g. 0-7."
+);
diff --git a/drivers/net/ipq5018/ipq5018_mdio.h b/drivers/net/ipq5018/ipq5018_mdio.h
new file mode 100644
index 0000000..857dfe1
--- /dev/null
+++ b/drivers/net/ipq5018/ipq5018_mdio.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015-2017, 2020 The Linux Foundation. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+#ifndef _IPQ5018_MDIO_H
+#define _IPQ5018_MDIO_H
+
+#define IPQ5018_MDIO_BASE			0x88000
+#define MDIO_CTRL_0_REG				0x40
+#define MDIO_CTRL_1_REG				0x44
+#define MDIO_CTRL_2_REG				0x48
+#define MDIO_CTRL_3_REG				0x4c
+#define MDIO_CTRL_4_REG				0x50
+#define MDIO_CTRL_4_ACCESS_BUSY			(1 << 16)
+#define MDIO_CTRL_4_ACCESS_START		(1 << 8)
+#define MDIO_CTRL_4_ACCESS_CODE_READ		0
+#define MDIO_CTRL_4_ACCESS_CODE_WRITE		1
+#define MDIO_CTRL_4_ACCESS_CODE_C45_ADDR        0
+#define MDIO_CTRL_4_ACCESS_CODE_C45_WRITE       1
+#define MDIO_CTRL_4_ACCESS_CODE_C45_READ        2
+#define CTRL_0_REG_DEFAULT_VALUE	        0x1500F
+#ifdef MDIO_12_5_MHZ
+#define CTRL_0_REG_C45_DEFAULT_VALUE	        0x15107
+#else
+#define CTRL_0_REG_C45_DEFAULT_VALUE		0x1510F
+#endif
+#define IPQ5018_MDIO_RETRY				1000
+#define IPQ5018_MDIO_DELAY				5
+#endif /* End _IPQ5018_MDIO_H */
diff --git a/drivers/net/ipq5018/ipq5018_uniphy.c b/drivers/net/ipq5018/ipq5018_uniphy.c
new file mode 100644
index 0000000..7daeec0
--- /dev/null
+++ b/drivers/net/ipq5018/ipq5018_uniphy.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <net.h>
+#include <asm-generic/errno.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <phy.h>
+#include <net.h>
+#include <miiphy.h>
+#include "ipq5018_uniphy.h"
+#include "ipq_phy.h"
+
+static uint32_t cur_mode;
+
+static int ppe_uniphy_calibration(void)
+{
+	int retries = 100, calibration_done = 0;
+	uint32_t reg_value = 0;
+
+	while(calibration_done != UNIPHY_CALIBRATION_DONE) {
+		mdelay(1);
+		if (retries-- == 0) {
+			printf("uniphy callibration time out!\n");
+			return -1;
+		}
+		reg_value = readl(PPE_UNIPHY_BASE + PPE_UNIPHY_OFFSET_CALIB_4);
+		calibration_done = (reg_value >> 0x7) & 0x1;
+	}
+
+	return 0;
+}
+
+static void ppe_gcc_uniphy_soft_reset(void)
+{
+	uint32_t reg_value;
+
+	reg_value = readl(GCC_UNIPHY0_MISC);
+
+	reg_value |= GCC_UNIPHY_SGMII_SOFT_RESET;
+
+	writel(reg_value, GCC_UNIPHY0_MISC);
+
+	udelay(500);
+
+	reg_value &= ~GCC_UNIPHY_SGMII_SOFT_RESET;
+
+	writel(reg_value, GCC_UNIPHY0_MISC);
+}
+
+static void ppe_uniphy_sgmii_mode_set(uint32_t mode)
+{
+	uint32_t phy_mode = 0x70;
+	writel(UNIPHY_MISC2_REG_SGMII_MODE,
+		PPE_UNIPHY_BASE + UNIPHY_MISC2_REG_OFFSET);
+
+	writel(UNIPHY_PLL_RESET_REG_VALUE, PPE_UNIPHY_BASE +
+		UNIPHY_PLL_RESET_REG_OFFSET);
+	mdelay(10);
+	writel(UNIPHY_PLL_RESET_REG_DEFAULT_VALUE, PPE_UNIPHY_BASE +
+		UNIPHY_PLL_RESET_REG_OFFSET);
+	mdelay(10);
+
+	writel(0x0, GCC_UNIPHY_RX_CBCR);
+	udelay(500);
+	writel(0x0, GCC_UNIPHY_TX_CBCR);
+	udelay(500);
+	writel(0x0, GCC_GMAC1_RX_CBCR);
+	udelay(500);
+	writel(0x0, GCC_GMAC1_TX_CBCR);
+	udelay(500);
+
+	switch (mode) {
+		case PORT_WRAPPER_SGMII_FIBER:
+			writel(UNIPHY_SG_MODE, PPE_UNIPHY_BASE + PPE_UNIPHY_MODE_CONTROL);
+			break;
+
+		case PORT_WRAPPER_SGMII0_RGMII4:
+		case PORT_WRAPPER_SGMII1_RGMII4:
+		case PORT_WRAPPER_SGMII4_RGMII4:
+			writel((UNIPHY_SG_MODE | UNIPHY_PSGMII_MAC_MODE),
+					PPE_UNIPHY_BASE + PPE_UNIPHY_MODE_CONTROL);
+			break;
+
+		case PORT_WRAPPER_SGMII_PLUS:
+			writel((UNIPHY_SG_PLUS_MODE | UNIPHY_PSGMII_MAC_MODE),
+					PPE_UNIPHY_BASE + PPE_UNIPHY_MODE_CONTROL);
+			phy_mode = 0x30;
+			break;
+
+		default:
+			printf("SGMII Config. wrongly");
+			break;
+	}
+	if ((cur_mode == PORT_WRAPPER_SGMII_PLUS) ||
+		(mode == PORT_WRAPPER_SGMII_PLUS)){
+		cur_mode = mode;
+		ppe_gcc_uniphy_soft_reset();
+	}
+
+	writel(phy_mode, PPE_UNIPHY_BASE + PPE_UNIPHY_ALLREG_DEC_MISC2);
+
+	writel(0x1, GCC_UNIPHY_RX_CBCR);
+	udelay(500);
+	writel(0x1, GCC_UNIPHY_TX_CBCR);
+	udelay(500);
+	writel(0x1, GCC_GMAC1_RX_CBCR);
+	udelay(500);
+	writel(0x1, GCC_GMAC1_TX_CBCR);
+	udelay(500);
+
+	ppe_uniphy_calibration();
+}
+
+void ppe_uniphy_mode_set(uint32_t mode)
+{
+	/*
+	 * SGMII and SHMII plus confugure in same function
+	 */
+	ppe_uniphy_sgmii_mode_set(mode);
+}
+
+void ppe_uniphy_set_forceMode(void)
+{
+	uint32_t reg_value;
+
+	reg_value = readl(PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4);
+	reg_value |= UNIPHY_FORCE_SPEED_25M;
+
+	writel(reg_value, PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4);
+
+}
+
+void ppe_uniphy_refclk_set(void)
+{
+/*
+ * This function drive the uniphy ref clock
+ * DEC_REFCLKOUTPUTCONTROLREGISTERS
+ * Its is configured as 25 MHZ
+ */
+
+	u32 reg_val = readl(PPE_UNIPHY_BASE | UNIPHY_REF_CLK_CTRL_REG);
+	reg_val |= 0x2;
+	writel(reg_val, PPE_UNIPHY_BASE | UNIPHY_REF_CLK_CTRL_REG);
+	mdelay(200);
+}
diff --git a/drivers/net/ipq5018/ipq5018_uniphy.h b/drivers/net/ipq5018/ipq5018_uniphy.h
new file mode 100644
index 0000000..da08281
--- /dev/null
+++ b/drivers/net/ipq5018/ipq5018_uniphy.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _IPQ5018_UNIPHY_H_
+#define _IPQ5018_UNIPHY_H
+
+#define PPE_UNIPHY_INSTANCE0			0
+
+#define GCC_UNIPHY_RX_CBCR			0x01856110
+#define GCC_UNIPHY_TX_CBCR			0x01856114
+
+#define GCC_GMAC1_RX_CBCR			0x01868248
+#define GCC_GMAC1_TX_CBCR			0x0186824C
+
+#define GCC_UNIPHY0_MISC			0x01856104
+
+#define PPE_UNIPHY_OFFSET_CALIB_4		0x1E0
+#define UNIPHY_CALIBRATION_DONE			0x1
+
+#define GCC_UNIPHY_PSGMII_SOFT_RESET 		0x3ff2
+#define GCC_UNIPHY_SGMII_SOFT_RESET 		0x32
+
+#define PPE_UNIPHY_BASE				0x00098000
+#define PPE_UNIPHY_MODE_CONTROL			0x46C
+#define PPE_UNIPHY_ALLREG_DEC_MISC2		0x218
+#define UNIPHY_XPCS_MODE			(1 << 12)
+#define UNIPHY_SG_PLUS_MODE			(1 << 11)
+#define UNIPHY_SG_MODE				(1 << 10)
+#define UNIPHY_CH0_PSGMII_QSGMII		(1 << 9)
+#define UNIPHY_CH0_QSGMII_SGMII			(1 << 8)
+#define UNIPHY_PSGMII_MAC_MODE			(1 << 5)
+#define UNIPHY_CH4_CH1_0_SGMII			(1 << 2)
+#define UNIPHY_CH1_CH0_SGMII			(1 << 1)
+#define UNIPHY_CH0_ATHR_CSCO_MODE_25M		(1 << 0)
+
+#define UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4	0x480
+#define UNIPHY_FORCE_SPEED_25M			(1 << 3)
+
+#define UNIPHY_REF_CLK_CTRL_REG			0x74
+
+#define UNIPHY_INSTANCE_LINK_DETECT		0x570
+
+#define UNIPHY_MISC2_REG_OFFSET 		0x218
+#define UNIPHY_MISC2_REG_SGMII_MODE 		0x30
+#define UNIPHY_MISC2_REG_SGMII_PLUS_MODE 	0x50
+
+#define UNIPHY_MISC2_REG_VALUE			0x70
+
+#define UNIPHY_PLL_RESET_REG_OFFSET 		0x780
+#define UNIPHY_PLL_RESET_REG_VALUE 		0x02bf
+#define UNIPHY_PLL_RESET_REG_DEFAULT_VALUE 	0x02ff
+
+void ppe_uniphy_mode_set(uint32_t mode);
+void ppe_uniphy_set_forceMode(void);
+void ppe_uniphy_refclk_set(void);
+#endif
diff --git a/drivers/net/ipq6018/ipq6018_ppe.h b/drivers/net/ipq6018/ipq6018_ppe.h
index b7a2877..cd8130e 100644
--- a/drivers/net/ipq6018/ipq6018_ppe.h
+++ b/drivers/net/ipq6018/ipq6018_ppe.h
@@ -200,9 +200,9 @@
 #define IPQ6018_PPE_PORT_QCOM1			0x1
 #define IPQ6018_PPE_PORT_QCOM2			0x2
 #define IPQ6018_PPE_PORT_QCOM3			0x3
-#define IPQ6018_PPE_PORT_QCOM4			0x4
-#define IPQ6018_PPE_PORT_XGMAC1			0x5
-#define IPQ6018_PPE_PORT_XGMAC2			0x6
+#define IPQ6018_PPE_PORT_QCOM4			0x6
+#define IPQ6018_PPE_PORT_XGMAC1			0x4
+#define IPQ6018_PPE_PORT_XGMAC2			0x5
 #define IPQ6018_PPE_PORT_CRYPTO1		0x7
 #define IPQ6018_PPE_PORT_BRIDGE_CTRL_PROMISC_EN	0x20000
 #define IPQ6018_PPE_PORT_BRIDGE_CTRL_TXMAC_EN	0x10000
diff --git a/drivers/net/ipq807x/ipq807x_uniphy.c b/drivers/net/ipq807x/ipq807x_uniphy.c
index e5d955a..1a22cf2 100644
--- a/drivers/net/ipq807x/ipq807x_uniphy.c
+++ b/drivers/net/ipq807x/ipq807x_uniphy.c
@@ -237,9 +237,6 @@
 	reg_value &= ~SS5;
 	reg_value |= SS6 | SS13 | DUPLEX_MODE;
 	csr1_write(uniphy_index, SR_MII_CTRL_ADDRESS, reg_value);
-	if (uniphy_index == PPE_UNIPHY_INSTANCE2) {
-		ipq_mdio_write(0x7, ((1<<30) | (4<<16) | 0xc441), 8);
-	}
 }
 
 void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode)
diff --git a/drivers/net/ipq_common/ipq_gephy.c b/drivers/net/ipq_common/ipq_gephy.c
new file mode 100644
index 0000000..90b1c13
--- /dev/null
+++ b/drivers/net/ipq_common/ipq_gephy.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+#include <common.h>
+#include <net.h>
+#include <asm-generic/errno.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <phy.h>
+#include "ipq_gephy.h"
+#include "ipq_phy.h"
+
+extern int ipq5018_mdio_read(int mii_id,
+		int regnum, ushort *data);
+extern int ipq5018_mdio_write(int mii_id,
+		int regnum, u16 data);
+
+u16 gephy_phy_reg_read(u32 dev_id, u32 phy_id, u32 reg_id)
+{
+	return ipq5018_mdio_read(phy_id, reg_id, NULL);
+}
+
+u16 gephy_phy_reg_write(u32 dev_id, u32 phy_id, u32 reg_id, u16 value)
+{
+	return ipq5018_mdio_write(phy_id, reg_id, value);
+}
+
+u8 gephy_phy_get_link_status(u32 dev_id, u32 phy_id)
+{
+	u16 phy_data;
+	phy_data = gephy_phy_reg_read(dev_id,
+			phy_id, GEPHY_PHY_SPEC_STATUS);
+	if (phy_data & GEPHY_STATUS_LINK_PASS)
+		return 0;
+
+	return 1;
+}
+
+u32 gephy_phy_get_duplex(u32 dev_id, u32 phy_id, fal_port_duplex_t *duplex)
+{
+	u16 phy_data;
+
+	phy_data = gephy_phy_reg_read(dev_id, phy_id,
+				GEPHY_PHY_SPEC_STATUS);
+
+	/*
+	 * Read duplex
+	 */
+	if (phy_data & GEPHY_STATUS_FULL_DUPLEX)
+		*duplex = FAL_FULL_DUPLEX;
+	else
+		*duplex = FAL_HALF_DUPLEX;
+
+	return 0;
+}
+
+u32 gephy_phy_get_speed(u32 dev_id, u32 phy_id, fal_port_speed_t *speed)
+{
+	u16 phy_data;
+
+	phy_data = gephy_phy_reg_read(dev_id,
+			phy_id, GEPHY_PHY_SPEC_STATUS);
+
+	switch (phy_data & GEPHY_STATUS_SPEED_MASK) {
+	case GEPHY_STATUS_SPEED_2500MBS:
+		*speed = FAL_SPEED_2500;
+		break;
+	case GEPHY_STATUS_SPEED_1000MBS:
+		*speed = FAL_SPEED_1000;
+		break;
+	case GEPHY_STATUS_SPEED_100MBS:
+		*speed = FAL_SPEED_100;
+		break;
+	case GEPHY_STATUS_SPEED_10MBS:
+		*speed = FAL_SPEED_10;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int ipq_gephy_phy_init(struct phy_ops **ops, u32 phy_id)
+{
+	u16 phy_data;
+	struct phy_ops *gephy_ops;
+
+	gephy_ops = (struct phy_ops *)malloc(sizeof(struct phy_ops));
+	if (!gephy_ops)
+		return -ENOMEM;
+	gephy_ops->phy_get_link_status = gephy_phy_get_link_status;
+	gephy_ops->phy_get_speed = gephy_phy_get_speed;
+	gephy_ops->phy_get_duplex = gephy_phy_get_duplex;
+	*ops = gephy_ops;
+
+	phy_data = gephy_phy_reg_read(0x0, phy_id, GEPHY_PHY_ID1);
+	printf ("PHY ID1: 0x%x\n", phy_data);
+	phy_data = gephy_phy_reg_read(0x0, phy_id, GEPHY_PHY_ID2);
+	printf ("PHY ID2: 0x%x\n", phy_data);
+
+	/*enable vga when init napa to fix 8023az issue*/
+	phy_data = gephy_phy_reg_read(0x0, phy_id, QCA808X_8023AZ_ENABLE_VGA);
+	phy_data &= (~QCA808X_PHY_8023AZ_AFE_CTRL_MASK);
+	phy_data |= QCA808X_PHY_8023AZ_AFE_EN;
+	phy_data = gephy_phy_reg_write(0x0, phy_id, QCA808X_8023AZ_ENABLE_VGA, phy_data);
+	if (phy_data != 0)
+		return phy_data;
+
+	/*special configuration for AZ under 1G speed mode*/
+	phy_data = QCA808X_PHY_MMD3_AZ_TRAINING_VAL;
+	phy_data = gephy_phy_reg_write(0x0, phy_id, QCA808X_AZ_CONFIG_UNDER_1G_SPEED,
+					phy_data);
+	return phy_data;
+}
diff --git a/drivers/net/ipq_common/ipq_gephy.h b/drivers/net/ipq_common/ipq_gephy.h
new file mode 100644
index 0000000..1491bfd
--- /dev/null
+++ b/drivers/net/ipq_common/ipq_gephy.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#ifndef _IPQ_GEPHY_H_
+#define _IPQ_GEPHY_H_
+
+/* PHY Registers */
+#define GEPHY_PHY_CONTROL			0
+#define GEPHY_PHY_STATUS			1
+#define GEPHY_PHY_SPEC_STATUS			17
+
+#define GEPHY_PHY_ID1				2
+#define GEPHY_PHY_ID2				3
+#define GEPHY_AUTONEG_ADVERT			4
+#define GEPHY_LINK_PARTNER_ABILITY		5
+#define GEPHY_1000BASET_CONTROL		9
+#define GEPHY_1000BASET_STATUS		10
+#define GEPHY_MMD_CTRL_REG			13
+#define GEPHY_MMD_DATA_REG			14
+#define GEPHY_EXTENDED_STATUS			15
+#define GEPHY_PHY_SPEC_CONTROL		16
+#define GEPHY_PHY_INTR_MASK			18
+#define GEPHY_PHY_INTR_STATUS			19
+#define GEPHY_PHY_CDT_CONTROL			22
+#define GEPHY_DEBUG_PORT_ADDRESS		29
+#define GEPHY_DEBUG_PORT_DATA			30
+
+#define GEPHY_STATUS_LINK_PASS		0x0400
+
+#define GEPHY_STATUS_FULL_DUPLEX		0x2000
+
+#define GEPHY_STATUS_SPEED_MASK		0x380
+#define GEPHY_STATUS_SPEED_2500MBS		0x200
+#define GEPHY_STATUS_SPEED_1000MBS		0x100
+#define GEPHY_STATUS_SPEED_100MBS		0x80
+#define GEPHY_STATUS_SPEED_10MBS		0x0000
+
+#define QCA808X_PHY_MMD3_AZ_TRAINING_VAL	0x1c32
+#define QCA808X_PHY_MMD3_NUM			3
+#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7		0x8007
+#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL	0x8008
+#define QCA808X_PHY_8023AZ_AFE_CTRL_MASK	0x01f0
+#define QCA808X_PHY_8023AZ_AFE_EN		0x0090
+#define QCA808X_MII_ADDR_C45			(1<<30)
+#define QCA808X_REG_C45_ADDRESS(dev_type, reg_num) (QCA808X_MII_ADDR_C45 | \
+                        ((dev_type & 0x1f) << 16) | (reg_num & 0xffff))
+#define QCA808X_8023AZ_ENABLE_VGA QCA808X_REG_C45_ADDRESS(QCA808X_PHY_MMD3_NUM, \
+			QCA808X_PHY_MMD3_ADDR_CLD_CTRL7)
+#define QCA808X_AZ_CONFIG_UNDER_1G_SPEED QCA808X_REG_C45_ADDRESS(QCA808X_PHY_MMD3_NUM, \
+			QCA808X_PHY_MMD3_AZ_TRAINING_CTRL)
+
+#endif				/* _GEPHY_PHY_H_ */
diff --git a/drivers/net/ipq_common/ipq_phy.h b/drivers/net/ipq_common/ipq_phy.h
index 9439e6c..653df90 100755
--- a/drivers/net/ipq_common/ipq_phy.h
+++ b/drivers/net/ipq_common/ipq_phy.h
@@ -104,6 +104,7 @@
 	QCA8081_PHY_TYPE = 2,
 	AQ_PHY_TYPE = 3,
 	QCA8033_PHY_TYPE = 4,
+	SFP_PHY_TYPE = 5,
 };
 
 typedef struct {
diff --git a/drivers/pci/pci_ipq.c b/drivers/pci/pci_ipq.c
index b57fba3..f9f8ba2 100644
--- a/drivers/pci/pci_ipq.c
+++ b/drivers/pci/pci_ipq.c
@@ -625,6 +625,7 @@
 	int is_gen3;
 	int linkup;
 	int version;
+	int skip_phy_init;
 };
 
 static void ipq_pcie_write_mask(uint32_t addr,
@@ -1130,11 +1131,13 @@
 					if (err < 0)
 						goto err;
 					pcie->is_gen3 = 1;
-				} 
+				}
 			} else {
 				goto err;
 			}
 		}
+		pcie->skip_phy_init =
+				fdtdec_get_int(fdt, node, "skip_phy_int", 0);
 	}
 	rst_gpio = fdtdec_get_int(fdt, node, "perst_gpio", 0);
 	if (rst_gpio <= 0) {
@@ -1333,17 +1336,18 @@
 
 void pcie_phy_v2_init(struct ipq_pcie *pcie)
 {
-	const struct phy_regs *regs = pcie_phy_v2_init_seq_ipq;
-	int i, size = ARRAY_SIZE(pcie_phy_v2_init_seq_ipq);
+	if (!pcie->skip_phy_init) {
+		const struct phy_regs *regs = pcie_phy_v2_init_seq_ipq;
+		int i, size = ARRAY_SIZE(pcie_phy_v2_init_seq_ipq);
 
-	for (i = 0; i < size; i++) {
-		if (regs[i].reg_offset == PCIE_PHY_DELAY_MS)
-			mdelay(regs[i].val);
-		else
-			writel(regs[i].val, pcie->pci_phy.start + regs[i].reg_offset);
+		for (i = 0; i < size; i++) {
+			if (regs[i].reg_offset == PCIE_PHY_DELAY_MS)
+				mdelay(regs[i].val);
+			else
+				writel(regs[i].val, pcie->pci_phy.start + regs[i].reg_offset);
+		}
+		mdelay(5);
 	}
-
-	mdelay(5);
 	return;
 }
 
diff --git a/drivers/serial/qca_uart.c b/drivers/serial/qca_uart.c
index 49fc066..77acd78 100644
--- a/drivers/serial/qca_uart.c
+++ b/drivers/serial/qca_uart.c
@@ -453,6 +453,8 @@
 	plat->n_value = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "n_value", -1);
 	plat->d_value = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "d_value", -1);
 
+	plat->gpio_node = fdt_subnode_offset(gd->fdt_blob, dev->of_offset, "serial_gpio");
+
 	return 0;
 }
 
@@ -559,6 +561,7 @@
 	uart2.n_value = fdtdec_get_int(gd->fdt_blob, node, "n_value", -1);
 	uart2.d_value = fdtdec_get_int(gd->fdt_blob, node, "d_value", -1);
 
+	uart2.gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "serial_gpio");
 	ipq_serial_init(&uart2,  uart2.reg_base);
 }
 
diff --git a/include/configs/ipq40xx.h b/include/configs/ipq40xx.h
index 45a1941..b133658 100644
--- a/include/configs/ipq40xx.h
+++ b/include/configs/ipq40xx.h
@@ -195,7 +195,6 @@
  * Cache flush and invalidation based on L1 cache, so the cache line
  * size is configured to 64 */
 #define CONFIG_SYS_CACHELINE_SIZE	64
-#define CONFIG_CMD_CACHE
 
 #define CONFIG_QCA_BAM                 1
 /*
diff --git a/include/configs/ipq5018.h b/include/configs/ipq5018.h
new file mode 100644
index 0000000..8dc6aec
--- /dev/null
+++ b/include/configs/ipq5018.h
@@ -0,0 +1,429 @@
+/*
+* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _IPQ5018_H
+#define _IPQ5018_H
+
+#ifndef DO_DEPS_ONLY
+#include <generated/asm-offsets.h>
+#endif
+
+#define CONFIG_IPQ5018
+#undef	CONFIG_QCA_DISABLE_SCM
+#define CONFIG_SPI_FLASH_CYPRESS
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_SYS_CACHELINE_SIZE		64
+#define CONFIG_IPQ_NO_RELOC
+
+#define CONFIG_SYS_VSNPRINTF
+
+/*
+ * Enable Early and Late init
+ * This config needs for secondary boot and to set BADOFF5E
+ * This config also need for spi-nor boot,
+ * set size and offset of hlos and rootfs
+*/
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_LATE_INIT
+
+#define CONFIG_IPQ5018_UART
+#define CONFIG_NR_DRAM_BANKS			1
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+#define CONFIG_SYS_BOOTM_LEN			0x4000000
+
+#define CONFIG_ENV_SIZE_MAX			(256 << 10) /* 256 KB */
+
+/*
+* PSCI Calls enable
+*/
+#define CONFIG_ARMV7_PSCI
+
+/*
+ * Enable Flashwrite command
+ */
+#define CONFIG_CMD_FLASHWRITE
+
+/*
+ * Enable Env overwrite support
+ */
+#define CONFIG_ENV_OVERWRITE
+
+/*
+ * select serial console configuration
+*/
+#define CONFIG_CONS_INDEX			1
+#define CONFIG_SYS_DEVICE_NULLDEV
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_BAUDRATE				115200
+#define CONFIG_SYS_BAUDRATE_TABLE		{4800, 9600, 19200, 38400, 57600,\
+						115200}
+
+#define CONFIG_SYS_CBSIZE			(512 * 2) /* Console I/O Buffer Size */
+/*
+
+		svc_sp     --> --------------
+		irq_sp     --> |            |
+		fiq_sp     --> |            |
+		bd         --> |            |
+		gd         --> |            |
+		pgt        --> |            |
+		malloc     --> |            |
+		text_base  --> |------------|
+*/
+
+#define CONFIG_SYS_INIT_SP_ADDR         	(CONFIG_SYS_TEXT_BASE -\
+						CONFIG_SYS_MALLOC_LEN - CONFIG_ENV_SIZE -\
+						GENERATED_BD_INFO_SIZE)
+
+#define CONFIG_SYS_MAXARGS			16
+#define CONFIG_SYS_PBSIZE			(CONFIG_SYS_CBSIZE + \
+							sizeof(CONFIG_SYS_PROMPT) + 16)
+
+#define TLMM_BASE				0x01000000
+#define GPIO_CONFIG_ADDR(x)			(TLMM_BASE + (x)*0x1000)
+#define GPIO_IN_OUT_ADDR(x)			(TLMM_BASE + 0x4 + (x)*0x1000)
+
+#define CONFIG_SYS_SDRAM_BASE			0x40000000
+#define CONFIG_SYS_TEXT_BASE			0x4A920000
+#define CONFIG_SYS_SDRAM_SIZE			0x10000000
+#define CONFIG_MAX_RAM_BANK_SIZE		CONFIG_SYS_SDRAM_SIZE
+#define CONFIG_SYS_LOAD_ADDR			(CONFIG_SYS_SDRAM_BASE + (64 << 20))
+
+#define QCA_KERNEL_START_ADDR			CONFIG_SYS_SDRAM_BASE
+#define QCA_DRAM_KERNEL_SIZE			CONFIG_SYS_SDRAM_SIZE
+#define QCA_BOOT_PARAMS_ADDR			(QCA_KERNEL_START_ADDR + 0x100)
+
+#define CONFIG_OF_COMBINE			1
+
+
+#define CONFIG_QCA_SMEM_BASE			0x4AB00000
+
+#define CONFIG_IPQ_FDT_HIGH			0x4A400000
+#define CONFIG_ENV_IS_IN_SPI_FLASH		1
+#define CONFIG_ENV_SECT_SIZE			(64 * 1024)
+
+#define CONFIG_QCA_UBOOT_OFFSET			0xA800000
+#define CONFIG_UBOOT_END_ADDR			0x4AA00000
+
+/*
+* IPQ_TFTP_MIN_ADDR: Starting address of Linux HLOS region.
+* CONFIG_TZ_END_ADDR: Ending address of Trust Zone and starting
+* address of WLAN Area.
+* TFTP file can only be written in Linux HLOS region and WLAN AREA.
+*/
+#define IPQ_TFTP_MIN_ADDR			(CONFIG_SYS_SDRAM_BASE + (16 << 20))
+#define CONFIG_TZ_END_ADDR			(CONFIG_SYS_SDRAM_BASE + (88 << 21))
+#define CONFIG_SYS_SDRAM_END			((long long)CONFIG_SYS_SDRAM_BASE + gd->ram_size)
+
+#ifndef __ASSEMBLY__
+#include <compiler.h>
+extern loff_t board_env_offset;
+extern loff_t board_env_range;
+extern loff_t board_env_size;
+#endif
+
+#define CONFIG_IPQ5018_ENV			1
+#define CONFIG_ENV_OFFSET			board_env_offset
+#define CONFIG_ENV_SIZE				CONFIG_ENV_SIZE_MAX
+#define CONFIG_ENV_RANGE			board_env_range
+#define CONFIG_SYS_MALLOC_LEN			(CONFIG_ENV_SIZE_MAX + (500 << 10))
+
+/*
+ * NAND Flash Configs
+*/
+
+/* CONFIG_QPIC_NAND: QPIC NAND in BAM mode
+ * CONFIG_IPQ_NAND: QPIC NAND in FIFO/block mode.
+ * BAM is enabled by default.
+ */
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_SYS_NAND_SELF_INIT
+
+#ifdef CONFIG_NAND_FLASH
+#define CONFIG_CMD_NAND
+#define CONFIG_ENV_IS_IN_NAND			1
+#define CONFIG_QPIC_NAND
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+#define CONFIG_CMD_NAND_YAFFS
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+#endif
+
+#ifdef CONFIG_QPIC_SERIAL
+#ifdef QSPI_SERIAL_DEBUG /* QSPI DEBUG */
+#define qspi_debug(fmt,args...)	printf (fmt ,##args)
+#else
+#define qspi_debug(fmt,args...)
+#endif /* QSPI DEBUG */
+#define CONFIG_PAGE_SCOPE_MULTI_PAGE_READ
+#define CONFIG_QSPI_SERIAL_TRAINING
+#endif
+
+/*
+* SPI Flash Configs
+*/
+#define CONFIG_QCA_SPI
+#define CONFIG_SPI_FLASH
+#define CONFIG_CMD_SF
+#define CONFIG_SPI_FLASH_STMICRO
+#define CONFIG_SPI_FLASH_WINBOND
+#define CONFIG_SPI_FLASH_MACRONIX
+#define CONFIG_SPI_FLASH_GIGADEVICE
+#define CONFIG_SPI_FLASH_SPANSION
+#define CONFIG_SF_DEFAULT_BUS			0
+#define CONFIG_SF_DEFAULT_CS			0
+#define CONFIG_SF_DEFAULT_MODE			SPI_MODE_0
+#define CONFIG_SF_DEFAULT_SPEED			(48 * 1000 * 1000)
+#define CONFIG_SPI_FLASH_BAR			1
+#define CONFIG_SPI_FLASH_USE_4K_SECTORS
+#define CONFIG_IPQ_4B_ADDR_SWITCH_REQD
+
+#define CONFIG_QUP_SPI_USE_DMA			1
+#define CONFIG_QCA_BAM				1
+
+/*
+ * MMC configs
+ */
+#ifdef CONFIG_MMC_FLASH
+#define CONFIG_QCA_MMC
+#define CONFIG_MMC
+#define CONFIG_CMD_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_SDHCI
+#define CONFIG_SDHCI_QCA
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV			0
+#define CONFIG_SDHCI_SUPPORT
+#define CONFIG_MMC_ADMA
+#define CONFIG_EFI_PARTITION
+/*
+* eMMC controller support only 4-bit
+* force SDHC driver to 4-bit mode
+*/
+#define CONFIG_MMC_FORCE_CAP_4BIT_BUSWIDTH
+#endif
+
+/*
+* I2C Enable
+*/
+#ifdef CONFIG_IPQ5018_I2C
+#define CONFIG_SYS_I2C_QUP
+#define CONFIG_CMD_I2C
+#define CONFIG_DM_I2C
+#endif
+
+/*
+* GMAC Enable
+*/
+
+#define CONFIG_IPQ5018_GMAC
+#define CONFIG_IPQ5018_MDIO
+
+#define CONFIG_NET_RETRY_COUNT			5
+#define CONFIG_SYS_RX_ETH_BUFFER		16
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_MII
+#define CONFIG_IPADDR				192.168.10.10
+#define CONFIG_NETMASK				255.255.255.0
+#define CONFIG_SERVERIP				192.168.10.19
+#define CONFIG_CMD_TFTPPUT
+#define CONFIG_IPQ_MDIO				1
+#define CONFIG_IPQ_ETH_INIT_DEFER
+#define CONFIG_IPQ_NO_MACS			2
+
+/*
+ * GEPHY
+ */
+#define CONFIG_GEPHY
+
+/*
+ * USB Support
+ */
+#ifdef CONFIG_USB_XHCI_IPQ
+#define CONFIG_USB_XHCI
+#define CONFIG_USB_XHCI_DWC3
+#define CONFIG_CMD_USB
+#define CONFIG_USB_STORAGE
+#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS      2
+#define CONFIG_USB_MAX_CONTROLLER_COUNT         1
+
+/*
+ * USB crashdump collection
+ */
+#define CONFIG_FS_FAT
+#define CONFIG_FAT_WRITE
+#define CONFIG_CMD_FAT
+
+/*
+ * Block Device & Disk  Partition Config
+ */
+#define HAVE_BLOCK_DEVICE
+#define CONFIG_DOS_PARTITION
+#endif
+
+/*
+ * PCIE Enable
+ */
+#define PCI_MAX_DEVICES				2
+#if defined(CONFIG_PCI_IPQ)
+#define CONFIG_PCI
+#define CONFIG_CMD_PCI
+#define CONFIG_PCI_SCAN_SHOW
+#endif
+
+/*
+* Expose SPI driver as a pseudo NAND driver to make use
+* of U-Boot's MTD framework.
+*/
+#define CONFIG_SYS_MAX_NAND_DEVICE		CONFIG_IPQ_MAX_NAND_DEVICE + \
+							CONFIG_IPQ_MAX_SPI_DEVICE
+
+#define CONFIG_IPQ_MAX_NAND_DEVICE		1
+#define CONFIG_IPQ_MAX_SPI_DEVICE		1
+
+#define CONFIG_QPIC_NAND_NAND_INFO_IDX		0
+#define CONFIG_IPQ_SPI_NOR_INFO_IDX		1
+
+#define CONFIG_NAND_FLASH_INFO_IDX		CONFIG_QPIC_NAND_NAND_INFO_IDX
+#define CONFIG_SPI_FLASH_INFO_IDX		CONFIG_IPQ_SPI_NOR_INFO_IDX
+
+#define QCA_SPI_NOR_DEVICE			"spi0.0"
+
+/*
+* U-Boot Env Configs
+*/
+#define CONFIG_OF_LIBFDT			1
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_CMD_XIMG
+
+/* MTEST */
+#define CONFIG_SYS_MEMTEST_START		CONFIG_SYS_SDRAM_BASE + 0x1300000
+#define CONFIG_SYS_MEMTEST_END			CONFIG_SYS_MEMTEST_START + 0x100
+
+/* NSS firmware loaded using bootm */
+#define CONFIG_BOOTCOMMAND			"bootipq"
+#define CONFIG_BOOTARGS				"console=ttyMSM0,115200n8"
+#define QCA_ROOT_FS_PART_NAME			"rootfs"
+
+#define CONFIG_BOOTDELAY			5
+
+#define NUM_ALT_PARTITION			16
+
+#ifdef CONFIG_IPQ_TINY
+/* undef gzip lib */
+#undef CONFIG_GZIP
+#undef CONFIG_ZLIB
+
+#else
+#define CONFIG_CMD_BOOTZ
+
+/* Multicore CPU support */
+#define CONFIG_SMP_CMD_SUPPORT
+
+/* Mii command support */
+#define CONFIG_CMD_MII
+
+/* compress crash dump support */
+#define CONFIG_CMD_ZIP
+#define CONFIG_GZIP_COMPRESSED
+
+/* Enable DTB compress */
+#define CONFIG_COMPRESSED_DTB_MAX_SIZE		0x40000
+#define CONFIG_COMPRESSED_DTB_BASE		CONFIG_SYS_TEXT_BASE -\
+						CONFIG_COMPRESSED_DTB_MAX_SIZE
+#endif
+
+#define CONFIG_FDT_FIXUP_PARTITIONS
+
+#define CONFIG_IPQ_FDT_FIXUP
+/*
+* Below Configs need to be updated after enabling reset_crashdump
+* Included now to avoid build failure
+*/
+#define CONFIG_OF_BOARD_SETUP
+
+#ifdef CONFIG_OF_BOARD_SETUP
+#define DLOAD_DISABLE				0x1
+#define SET_MAGIC				0x1
+#define CLEAR_MAGIC				0x0
+#define SCM_CMD_TZ_CONFIG_HW_FOR_RAM_DUMP_ID	0x9
+#define SCM_CMD_TZ_FORCE_DLOAD_ID		0x10
+#define SCM_CMD_TZ_PSHOLD			0x16
+#define BOOT_VERSION				0
+#define TZ_VERSION				1
+#endif
+
+
+#define CONFIG_IPQ5018_TZ_WONCE_4_ADDR		0x193d010
+/*
+* CRASH DUMP ENABLE
+*/
+#define CONFIG_QCA_APPSBL_DLOAD
+#define CONFIG_IPQ5018_DMAGIC_ADDR		0x193D100
+#ifdef CONFIG_QCA_APPSBL_DLOAD
+
+#undef CONFIG_NET_RETRY_COUNT
+#define CONFIG_NET_RETRY_COUNT  500
+
+#define IPQ_TEMP_DUMP_ADDR 0x44000000
+#endif
+
+#define CONFIG_QCA_KERNEL_CRASHDUMP_ADDRESS	*((unsigned int *)0x08600658)
+#define CONFIG_CPU_CONTEXT_DUMP_SIZE		4096
+#define TLV_BUF_OFFSET				1012 * 1024
+#define CONFIG_TLV_DUMP_SIZE			12 * 1024
+
+/* L1 cache line size is 64 bytes, L2 cache line size is 128 bytes
+* Cache flush and invalidation based on L1 cache, so the cache line
+* size is configured to 64 */
+#define CONFIG_SYS_CACHELINE_SIZE		64
+
+/*
+ * UBI write command
+ */
+#ifdef CONFIG_UBI_WRITE
+#define CONFIG_CMD_UBI
+#define CONFIG_RBTREE
+#define IPQ_UBI_VOL_WRITE_SUPPORT
+#endif
+
+#undef CONFIG_BOOTM_NETBSD
+#undef CONFIG_BOOTM_PLAN9
+#undef CONFIG_BOOTM_RTEMS
+#undef CONFIG_BOOTM_VXWORKS
+
+#ifdef CONFIG_ART_COMPRESSED
+/*
+ * This location use to keep comprssed data for
+ * uncompress process.
+ * default location is CONFIG_SYS_LOAD_ADDR if not defined.
+ */
+#define CONFIG_COMPRESSED_LOAD_ADDR (CONFIG_SYS_LOAD_ADDR + (1 << 22))
+#endif
+
+#ifdef CONFIG_SMP_CMD_SUPPORT
+#define NR_CPUS				2
+#endif
+
+/*
+ * 96 MHz
+ */
+
+#define INTERNAL_96MHZ
+
+/*#define CONFIG_IPQ_BT_SUPPORT*/
+
+#endif /* _IPQ5018_H */
diff --git a/include/configs/ipq6018.h b/include/configs/ipq6018.h
index ab51e46..99456a5 100644
--- a/include/configs/ipq6018.h
+++ b/include/configs/ipq6018.h
@@ -363,7 +363,6 @@
  * Cache flush and invalidation based on L1 cache, so the cache line
  * size is configured to 64 */
 #define CONFIG_SYS_CACHELINE_SIZE	64
-#define CONFIG_CMD_CACHE
 /*#define CONFIG_SYS_DCACHE_OFF*/
 
 /* Enabling this flag will report any L2 errors.
diff --git a/include/configs/ipq806x.h b/include/configs/ipq806x.h
index 4db1850..616efb6 100644
--- a/include/configs/ipq806x.h
+++ b/include/configs/ipq806x.h
@@ -346,7 +346,6 @@
  * Cache flush and invalidation based on L1 cache, so the cache line
  * size is configured to 64 */
 #define CONFIG_SYS_CACHELINE_SIZE  64
-#define CONFIG_CMD_CACHE
 /*#define CONFIG_SYS_DCACHE_OFF*/
 
 /* Enabling this flag will report any L2 errors.
diff --git a/include/configs/ipq807x.h b/include/configs/ipq807x.h
index 70ccde1..126a81a 100644
--- a/include/configs/ipq807x.h
+++ b/include/configs/ipq807x.h
@@ -28,6 +28,9 @@
  * #define CONFIG_RUMI
  */
 
+#define CONFIG_CMD_AES
+#define CONFIG_CMD_AES_256
+
 #define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_IPQ_NO_RELOC
 #define CONFIG_BOARD_LATE_INIT
@@ -341,7 +344,6 @@
  * Cache flush and invalidation based on L1 cache, so the cache line
  * size is configured to 64 */
 #define CONFIG_SYS_CACHELINE_SIZE  64
-#define CONFIG_CMD_CACHE
 
 /* Enabling this flag will report any L2 errors.
  * By default we are disabling it */
diff --git a/include/dt-bindings/qcom/gpio-ipq5018.h b/include/dt-bindings/qcom/gpio-ipq5018.h
new file mode 100644
index 0000000..1744a16
--- /dev/null
+++ b/include/dt-bindings/qcom/gpio-ipq5018.h
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef __DT_BINDINGS_IPQ5018_GPIO_H__
+#define __DT_BINDINGS_IPQ5018_GPIO_H__
+
+/* GPIO TLMM: Direction */
+#define GPIO_INPUT              0
+#define GPIO_OUTPUT             1
+
+/* GPIO TLMM: Output value */
+#define GPIO_OUT_LOW            0
+#define GPIO_OUT_HIGH           1
+
+/* GPIO TLMM: Pullup/Pulldown */
+#define GPIO_NO_PULL            0
+#define GPIO_PULL_DOWN          1
+#define GPIO_KEEPER             2
+#define GPIO_PULL_UP            3
+
+/* GPIO TLMM: Drive Strength */
+#define GPIO_2MA                0
+#define GPIO_4MA                1
+#define GPIO_6MA                2
+#define GPIO_8MA                3
+#define GPIO_10MA               4
+#define GPIO_12MA               5
+#define GPIO_14MA               6
+#define GPIO_16MA               7
+
+/* GPIO TLMM: Status */
+#define GPIO_OE_DISABLE         0
+#define GPIO_OE_ENABLE          1
+
+/* GPIO OD */
+#define GPIO_OD_ENABLE          1
+#define GPIO_OD_DISABLE         0
+
+/* GPIO SR */
+#define GPIO_SR_ENABLE          1
+#define GPIO_SR_DISABLE         0
+
+/* GPIO PULLUP RES */
+#define GPIO_PULL_RES0          0
+#define GPIO_PULL_RES1          1
+#define GPIO_PULL_RES2          2
+#define GPIO_PULL_RES3          3
+
+#endif
+
diff --git a/include/malloc.h b/include/malloc.h
index f20e4d3..e5c6561 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -909,6 +909,9 @@
 /* Set up pre-relocation malloc() ready for use */
 int initf_malloc(void);
 
+# ifdef CONFIG_COMPRESSED_DTB_BASE
+int initf_pre_malloc(void);
+# endif
 /* Public routines */
 
 /* Simple versions which can be used when space is tight */
diff --git a/include/net.h b/include/net.h
index f7039e3..b1a9bc22 100644
--- a/include/net.h
+++ b/include/net.h
@@ -278,7 +278,7 @@
 	u8		et_dest[6];	/* Destination node		*/
 	u8		et_src[6];	/* Source node			*/
 	u16		et_protlen;	/* Protocol or length		*/
-};
+} __attribute__((packed));
 
 /* Ethernet header size */
 #define ETHER_HDR_SIZE	(sizeof(struct ethernet_hdr))
@@ -296,7 +296,7 @@
 	u8		et_snap2;
 	u8		et_snap3;
 	u16		et_prot;	/* 802 protocol			*/
-};
+} __attribute__((packed));
 
 /* 802 + SNAP + ethernet header size */
 #define E802_HDR_SIZE	(sizeof(struct e802_hdr))
@@ -310,7 +310,7 @@
 	u16		vet_vlan_type;	/* PROT_VLAN			*/
 	u16		vet_tag;	/* TAG of VLAN			*/
 	u16		vet_type;	/* protocol type		*/
-};
+} __attribute__((packed));
 
 /* VLAN Ethernet header size */
 #define VLAN_ETHER_HDR_SIZE	(sizeof(struct vlan_ethernet_hdr))
@@ -337,7 +337,7 @@
 	u16		ip_sum;		/* checksum			*/
 	struct in_addr	ip_src;		/* Source IP address		*/
 	struct in_addr	ip_dst;		/* Destination IP address	*/
-};
+} __attribute__((packed));
 
 #define IP_OFFS		0x1fff /* ip offset *= 8 */
 #define IP_FLAGS	0xe000 /* first 3 bits */
@@ -365,7 +365,7 @@
 	u16		udp_dst;	/* UDP destination port		*/
 	u16		udp_len;	/* Length of UDP packet		*/
 	u16		udp_xsum;	/* Checksum			*/
-};
+} __attribute__((packed));
 
 #define IP_UDP_HDR_SIZE		(sizeof(struct ip_udp_hdr))
 #define UDP_HDR_SIZE		(IP_UDP_HDR_SIZE - IP_HDR_SIZE)
@@ -404,7 +404,7 @@
 	u8		ar_tha[];	/* Target hardware address	*/
 	u8		ar_tpa[];	/* Target protocol address	*/
 #endif /* 0 */
-};
+} __attribute__((packed));
 
 #define ARP_HDR_SIZE	(8+20)		/* Size assuming ethernet	*/
 
@@ -439,7 +439,7 @@
 		} frag;
 		u8 data[0];
 	} un;
-};
+} __attribute__((packed));
 
 #define ICMP_HDR_SIZE		(sizeof(struct icmp_hdr))
 #define IP_ICMP_HDR_SIZE	(IP_HDR_SIZE + ICMP_HDR_SIZE)
diff --git a/lib/Kconfig b/lib/Kconfig
index 9d580e4..ff53702 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -127,6 +127,14 @@
 	  frame format currently (2015) implemented in the Linux kernel
 	  (generated by 'lz4 -l'). The two formats are incompatible.
 
+config LZMA
+	bool "Enable LZMA decompression support"
+	help
+	  If this option is set, support for LZMA compressed images
+	  is included. The LZMA algorithm can run in-place as long as the
+	  compressed image is loaded to the end of the output buffer, and
+	  trades high compression ratios and fairly fast decompression speed.
+
 endmenu
 
 config ERRNO_STR
diff --git a/net/bootp.h b/net/bootp.h
index fcb0a64..567340e 100644
--- a/net/bootp.h
+++ b/net/bootp.h
@@ -49,7 +49,7 @@
 	char		bp_sname[64];	/* Server host name		*/
 	char		bp_file[128];	/* Boot file name		*/
 	char		bp_vend[OPT_FIELD_SIZE]; /* Vendor information	*/
-};
+} __attribute__((packed));
 
 #define BOOTP_HDR_SIZE	sizeof(struct bootp_hdr)
 
diff --git a/net/dns.h b/net/dns.h
index c4e96af..c55a5c1 100644
--- a/net/dns.h
+++ b/net/dns.h
@@ -29,7 +29,7 @@
 	uint16_t	nauth;		/* Authority PRs */
 	uint16_t	nother;		/* Other PRs */
 	unsigned char	data[1];	/* Data, variable length */
-};
+} __attribute__((packed));
 
 void dns_start(void);		/* Begin DNS */
 
diff --git a/net/nfs.h b/net/nfs.h
index d69b422..09b387e 100644
--- a/net/nfs.h
+++ b/net/nfs.h
@@ -68,7 +68,7 @@
 			uint32_t data[19];
 		} reply;
 	} u;
-};
+} __attribute__((packed));
 void nfs_start(void);	/* Begin NFS */
 
 
diff --git a/net/sntp.h b/net/sntp.h
index 6a9c6bb..c38bcee 100644
--- a/net/sntp.h
+++ b/net/sntp.h
@@ -51,7 +51,7 @@
 	unsigned long long originate_timestamp;
 	unsigned long long receive_timestamp;
 	unsigned long long transmit_timestamp;
-};
+} __attribute__((packed));
 
 void sntp_start(void);	/* Begin SNTP */
 
diff --git a/tools/pack.py b/tools/pack.py
index 8dea6c3..b5fbce0 100644
--- a/tools/pack.py
+++ b/tools/pack.py
@@ -87,6 +87,16 @@
 image_type = "all"
 memory_size = "default"
 lk = "false"
+skip_4k_nand = "false"
+atf = "false"
+qcn6122 = "false"
+tiny_16m = "false"
+
+# Note: ipq806x didn't expose any relevant version */
+soc_hw_version_ipq40xx = { 0x20050100 };
+soc_hw_version_ipq807x = { 0x200D0100, 0x200D0101, 0x200D0102, 0x200D0200 };
+soc_hw_version_ipq6018 = { 0x20170100 };
+soc_hw_version_ipq5018 = { 0x20180100, 0x20180101 };
 
 #
 # Python 2.6 and earlier did not have OrderedDict use the backport
@@ -429,6 +439,25 @@
         self.append('if test "$%s" = "%s"; then\n' % (var, value),
                     fatal=False)
 
+    def start_if_or(self, var, val_list):
+        """Generate code, to check an environment variable.
+
+        var -- string, variable to check
+        value -- string, the list of values to compare with
+        """
+
+	n_val = len(val_list)
+	item = 1
+	cmd_str = "if "
+	for val in val_list:
+	    cmd_str = cmd_str + str('test "$%s" = "%s"' % (var, val))
+	    #cmd_str = cmd_str + "\"$" + var + "\"" + "=" + "\"" + val + "\""
+	    if item <= (n_val - 1):
+		cmd_str = cmd_str + " || "
+	    item = item + 1
+
+	self.append('%s; then\n' % cmd_str, fatal=False)
+
     def end_if(self):
         """Generate code, to end if statement."""
 
@@ -594,7 +623,6 @@
     def __gen_flash_script_cdt(self, entries, partition, flinfo, script):
 	global ARCH_NAME
         for section in entries:
-
             machid = int(section.find(".//machid").text, 0)
             machid = "%x" % machid
             board = section.find(".//board").text
@@ -711,10 +739,254 @@
                 script.end_if()
 
         return 1
+    def __gen_flash_script_wififw_ubi_volume(self, entries, fw_filename, wifi_fw_type, script):
+
+	machid_list = []
+	for section in entries:
+
+	    wififw_type = section.find('.//wififw_type')
+	    if wififw_type == None:
+		continue
+	    wififw_type = str(section.find(".//wififw_type").text)
+
+	    if str(wifi_fw_type) != str(wififw_type):
+		continue
+
+	    machid = int(section.find(".//machid").text, 0)
+	    machid = "%x" % machid
+
+	    machid_list.append(machid)
+
+	script.start_if_or("machid", machid_list)
+	script.start_activity("Flashing " + fw_filename[:-13] + ":")
+	script.imxtract(fw_filename[:-13] + "-" + sha1(fw_filename))
+
+	rootfs_info = self.__get_part_info("rootfs")
+	rootfs_offset = rootfs_info.offset
+	rootfs_len = rootfs_info.length
+
+	wifi_fw_cmd = "setenv mtdids nand0=nand0\n"
+	wifi_fw_cmd += "setenv mtdparts mtdparts=nand0:0x%x@0x%x(rootfs)\n" % (rootfs_len,rootfs_offset)
+	wifi_fw_cmd += "ubi part rootfs\n"
+	img_size = self.__get_img_size(fw_filename)
+	wifi_fw_cmd += "ubi write $fileaddr wifi_fw %x" % img_size
+	script.append(wifi_fw_cmd, fatal=False)
+
+	#Enable the below lines for debugging purpose
+	"""
+	script.append("mtdparts", fatal=False)
+	script.append("ubi info layout", fatal=False)
+	"""
+
+	script.finish_activity()
+	script.end_if()
+
+	return 1
+
+    def __gen_flash_script_wififw(self, entries, partition, filename, wifi_fw_type, flinfo, script):
+
+	machid_list = []
+	for section in entries:
+
+	    wififw_type = section.find('.//wififw_type')
+	    if wififw_type == None:
+		continue
+	    wififw_type = str(section.find(".//wififw_type").text)
+
+	    if str(wifi_fw_type) != str(wififw_type):
+		continue
+
+	    machid = int(section.find(".//machid").text, 0)
+	    machid = "%x" % machid
+
+	    machid_list.append(machid)
+
+	img_size = self.__get_img_size(filename)
+	part_info = self.__get_part_info(partition)
+
+	section_label = partition.split(":")
+        if len(section_label) != 1:
+	    section_conf = section_label[1]
+	else:
+	    section_conf = section_label[0]
+	section_conf = section_conf.lower()
+
+	if self.flinfo.type == 'nand':
+	    size = roundup(img_size, flinfo.pagesize)
+	    tr = ' | tr \"\\000\" \"\\377\"'
+
+	if self.flinfo.type == 'emmc':
+	    size = roundup(img_size, flinfo.blocksize)
+	    tr = ''
+
+	if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
+	    pad_size = size - img_size
+	    filename_abs = os.path.join(self.images_dname, filename)
+	    filename_abs_pad = filename_abs + ".padded"
+	    cmd = 'cat %s > %s' % (filename_abs, filename_abs_pad)
+	    ret = subprocess.call(cmd, shell=True)
+	    if ret != 0:
+		error("failed to copy image")
+	    cmd = 'dd if=/dev/zero count=1 bs=%s %s >> %s' % (pad_size, tr, filename_abs_pad)
+	    cmd = '(' + cmd + ') 1>/dev/null 2>/dev/null'
+	    ret = subprocess.call(cmd, shell=True)
+	    if ret != 0:
+		error("failed to create padded image from script")
+
+	if self.flinfo.type != "emmc":
+	    if part_info == None:
+		if self.flinfo.type == 'norplusnand':
+		    if count > 2:
+			error("More than 2 NAND images for NOR+NAND is not allowed")
+	    elif img_size > part_info.length:
+		print "img size is larger than part. len in '%s'" % section_conf
+		return 0
+	else:
+	    if part_info != None:
+		if (img_size > 0):
+		    if img_size > (part_info.length * self.flinfo.blocksize):
+			print "img size is larger than part. len in '%s'" % section_conf
+			return 0
+
+	if part_info == None and self.flinfo.type != 'norplusnand':
+	    print "Flash type is norplusemmc"
+	    return 1
+
+	script.start_if_or("machid", machid_list)
+	script.start_activity("Flashing %s:" % ( filename[:-13] ))
+
+	if img_size > 0:
+	    filename_pad = filename + ".padded"
+	    if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
+		script.imxtract(filename[:-13] + "-" + sha1(filename_pad))
+	    else:
+		script.imxtract(filename[:-13] + "-" + sha1(filename))
+
+	part_size = Pack.norplusnand_rootfs_img_size
+	if part_info == None:
+	    if self.flinfo.type == 'norplusnand':
+		offset = count * Pack.norplusnand_rootfs_img_size
+		script.nand_write(offset, part_size, img_size, spi_nand)
+		count = count + 1
+	else:
+	    if part_info.which_flash == 0:
+		offset = part_info.offset
+		script.erase(offset, part_info.length)
+		script.write(offset, img_size)
+	    else:
+		offset = part_info.offset
+		script.nand_write(offset, part_info.length, img_size, spi_nand)
+
+	script.finish_activity()
+	script.end_if()
+
+        return 1
+
+    def __gen_flash_script_bootldr(self, entries, partition, flinfo, script):
+        for section in entries:
+
+            machid = int(section.find(".//machid").text, 0)
+            machid = "%x" % machid
+            board = section.find(".//board").text
+            memory = section.find(".//memory").text
+            tiny_image = section.find('.//tiny_image')
+
+            if tiny_image == None:
+                continue
+
+	    if memory_size != "default":
+                filename = "bootldr1_" + board + "_" + memory + "_LM" + memory_size + ".mbn"
+	    else:
+                filename = "bootldr1_" + board + "_" + memory + ".mbn"
+
+            img_size = self.__get_img_size(filename)
+            part_info = self.__get_part_info(partition)
+
+            section_label = partition.split(":")
+            if len(section_label) != 1:
+                section_conf = section_label[1]
+            else:
+                section_conf = section_label[0]
+
+            section_conf = section_conf.lower()
+
+            if self.flinfo.type == 'nand':
+                size = roundup(img_size, flinfo.pagesize)
+                tr = ' | tr \"\\000\" \"\\377\"'
+
+            if self.flinfo.type == 'emmc':
+                size = roundup(img_size, flinfo.blocksize)
+                tr = ''
+
+            if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
+                pad_size = size - img_size
+                filename_abs = os.path.join(self.images_dname, filename)
+                filename_abs_pad = filename_abs + ".padded"
+                cmd = 'cat %s > %s' % (filename_abs, filename_abs_pad)
+                ret = subprocess.call(cmd, shell=True)
+                if ret != 0:
+                    error("failed to copy image")
+                cmd = 'dd if=/dev/zero count=1 bs=%s %s >> %s' % (pad_size, tr, filename_abs_pad)
+                cmd = '(' + cmd + ') 1>/dev/null 2>/dev/null'
+                ret = subprocess.call(cmd, shell=True)
+                if ret != 0:
+                    error("failed to create padded image from script")
+
+            if self.flinfo.type != "emmc":
+               if part_info == None:
+                   if self.flinfo.type == 'norplusnand':
+                       if count > 2:
+                           error("More than 2 NAND images for NOR+NAND is not allowed")
+               elif img_size > part_info.length:
+                   print "img size is larger than part. len in '%s'" % section_conf
+                   return 0
+            else:
+                if part_info != None:
+                    if (img_size > 0):
+                        if img_size > (part_info.length * self.flinfo.blocksize):
+                            print "img size is larger than part. len in '%s'" % section_conf
+                            return 0
+
+            if part_info == None and self.flinfo.type != 'norplusnand':
+                print "Flash type is norplusemmc"
+                continue
+
+            if machid:
+                script.start_if("machid", machid)
+
+            script.start_activity("Flashing bootldr1-%s_%s:" % ( board, memory ))
+            if img_size > 0:
+                filename_pad = filename + ".padded"
+                if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
+                    script.imxtract("bootldr1_" + board + "_" + memory + "-" + sha1(filename_pad))
+                else:
+                    script.imxtract("bootldr1_" + board + "_" + memory + "-" + sha1(filename))
+
+            part_size = Pack.norplusnand_rootfs_img_size
+            if part_info == None:
+                if self.flinfo.type == 'norplusnand':
+                    offset = count * Pack.norplusnand_rootfs_img_size
+                    script.nand_write(offset, part_size, img_size, spi_nand)
+                    count = count + 1
+            else:
+                if part_info.which_flash == 0:
+                    offset = part_info.offset
+                    script.erase(offset, part_info.length)
+                    script.write(offset, img_size)
+                else:
+                    offset = part_info.offset
+                    script.nand_write(offset, part_info.length, img_size, spi_nand)
+
+            script.finish_activity()
+
+            if machid:
+                script.end_if()
+
+        return 1
 
     def __gen_flash_script_image(self, filename, soc_version, file_exists, machid, partition, flinfo, script):
 
-	    global IF_HK10
+	    global IF_QCN9000
 
 	    img_size = 0
 	    if file_exists == 1:
@@ -774,8 +1046,8 @@
 	    if machid:
 		script.start_if("machid", machid)
 
-            if section_conf == "mibib" and IF_HK10:
-                section_conf = "mibib_hk10"
+            if section_conf == "mibib" and IF_QCN9000:
+                section_conf = "mibib_qcn9000"
             if section_conf == "qsee":
                 section_conf = "tz"
             elif section_conf == "appsbl":
@@ -787,8 +1059,8 @@
                 section_conf = "ubi"
             elif section_conf == "wififw" and self.flash_type in ["nand", "nand-4k", "nand-audio", "nand-audio-4k", "norplusnand", "norplusnand-4k"]:
                 section_conf = "wififw_ubi"
-                if IF_HK10:
-                    section_conf = "wififw_ubi_hk10"
+                if IF_QCN9000:
+                    section_conf = "wififw_ubi_qcn9000"
 
 	    if soc_version:
 		section_conf = section_conf + "_v" + str(soc_version)
@@ -840,7 +1112,7 @@
 
             return 1
 
-    def __gen_flash_script(self, script, flinfo, root):
+    def __gen_flash_script(self, script, flinfo, root, testmachid=False):
         """Generate the script to flash the images.
 
         info -- ConfigParser object, containing image flashing info
@@ -849,19 +1121,22 @@
 	global MODE
 	global SRC_DIR
 	global ARCH_NAME
-	global IF_HK10
+	global IF_QCN9000
 
 	diff_files = ""
         count = 0
 	soc_version = 0
 	diff_soc_ver_files = 0
 	file_exists = 1
+	wifi_fw_type = ""
+	wifi_fw_type_min = ""
+	wifi_fw_type_max = ""
 
         if self.flash_type == "norplusemmc" and flinfo.type == "emmc":
             srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + flinfo.type + "-partition.xml"
         else:
-            if IF_HK10:
-                srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + self.flash_type.lower() + "-partition-hk10.xml"
+            if IF_QCN9000:
+                srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + self.flash_type.lower() + "-partition-qcn9000.xml"
             else:
                 srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + self.flash_type.lower() + "-partition.xml"
 
@@ -878,6 +1153,53 @@
             parts_length = len(parts)
         entries = root.findall(".//data[@type='MACH_ID_BOARD_MAP']/entry")
 
+        # Note: Skipping validation for ipq806x. It didn't expose any relevant ID. */
+	if ARCH_NAME == "ipq40xx":
+            soc_hw_versions = soc_hw_version_ipq40xx
+	if ARCH_NAME == "ipq807x" or ARCH_NAME == "ipq807x_64":
+            soc_hw_versions = soc_hw_version_ipq807x
+	if ARCH_NAME == "ipq6018" or ARCH_NAME == "ipq6018_64":
+            soc_hw_versions = soc_hw_version_ipq6018
+	if ARCH_NAME == "ipq5018" or ARCH_NAME == "ipq5018_64":
+            soc_hw_versions = soc_hw_version_ipq5018
+
+        chip_count = 0
+        for soc_hw_version in soc_hw_versions:
+            chip_count = chip_count + 1
+            if chip_count == 1:
+                script.script.append('if test -n $soc_hw_version')
+                script.script.append('; then\n')
+                script.script.append('if test "$soc_hw_version" = "%x" ' % soc_hw_version)
+            else:
+                script.script.append('|| test "$soc_hw_version" = "%x" ' % soc_hw_version)
+        if chip_count >= 1:
+            script.script.append('; then\n')
+            script.script.append('echo \'soc_hw_version : Validation success\'\n')
+            script.script.append('else\n')
+            script.script.append('echo \'soc_hw_version : did not match, aborting upgrade\'\n')
+            script.script.append('exit 1\n')
+            script.script.append('fi\n')
+            script.script.append('else\n')
+            script.script.append('echo \'soc_hw_version : unknown, skipping validation\'\n')
+            script.script.append('fi\n')
+
+	if testmachid:
+	    machid_count = 0
+	    for section in entries:
+		machid = int(section.find(".//machid").text, 0)
+		machid = "%x" % machid
+		machid_count =  machid_count + 1
+		if machid_count == 1:
+		    script.script.append('if test "$machid" = "%s" ' % machid)
+		else:
+		    script.script.append('|| test "$machid" = "%s" ' % machid)
+	    if machid_count >= 1:
+		    script.script.append('; then\n')
+		    script.script.append('echo \'machid : Validation success\'\n')
+		    script.script.append('else\n')
+		    script.script.append('echo \'machid : unknown, aborting upgrade\'\n')
+		    script.script.append('exit 1\n')
+		    script.script.append('fi\n')
         first = False
         section = None
         part_index = 0
@@ -941,17 +1263,21 @@
 			try:
 			    diff_soc_ver_files = section.attrib['diff_soc_ver_files']
 			except KeyError, e:
-			    try:
-				if image_type == "all" or section.attrib['image_type'] == image_type:
-                                	filename = section.attrib['filename']
-                                        if lk == "true" and "u-boot" in filename:
-                                            filename = filename.replace("u-boot", "lkboot")
-                                	partition = section.attrib['label']
-				if filename == "":
-					continue
-			    except KeyError, e:
-                                print "Skipping partition '%s'" % section.attrib['label']
-				pass
+			    if (qcn6122 == "true" or tiny_16m == "true") and 'wififw_type_min' in section.attrib:
+				wifi_fw_type_min = section.attrib['wififw_type_min']
+				wifi_fw_type_max = section.attrib['wififw_type_max']
+			    else:
+				try:
+				    if image_type == "all" or section.attrib['image_type'] == image_type:
+					filename = section.attrib['filename']
+					if filename == "":
+					    continue
+					partition = section.attrib['label']
+					if lk == "true" and "u-boot" in filename:
+					    filename = filename.replace("u-boot", "lkboot")
+				except KeyError, e:
+				    print "Skipping partition '%s'" % section.attrib['label']
+				    pass
 
 		    if diff_files == "true":
 			try:
@@ -983,6 +1309,13 @@
 		except KeyError, e:
 			continue
 
+            if partition == "0:BOOTLDR1":
+                if image_type == "all" or section.attrib['image_type'] == image_type:
+                        ret = self.__gen_flash_script_bootldr(entries, partition, flinfo, script)
+                        if ret == 0:
+                            return 0
+                        continue
+
             if ARCH_NAME == "ipq806x":
             # Get Layout
                 try:
@@ -994,10 +1327,26 @@
                     error("invalid layout in '%s'" % section)
 
             if flinfo.type != "emmc":
-
 		img = section.find('img_name')
-		if img != None and 'soc_version' in img.attrib:
 
+		if img != None and 'wififw_type' in img.attrib and (qcn6122 == "true" or tiny_16m == "true"):
+		    imgs = section.findall('img_name')
+		    try:
+			for img in imgs:
+			    filename = img.text
+			    if 'optional' in img.attrib:
+				if not os.path.exists(os.path.join(self.images_dname, filename)):
+				    continue
+			    wifi_fw_type = img.get('wififw_type')
+			    ret = self.__gen_flash_script_wififw(entries, partition, filename, wifi_fw_type, flinfo, script)
+			    if ret == 0:
+				return 0
+			    wifi_fw_type = ""
+			continue
+		    except KeyError, e:
+			continue
+
+		if img != None and 'soc_version' in img.attrib:
 		    imgs = section.findall('img_name')
 		    try:
 			for img in imgs:
@@ -1016,7 +1365,35 @@
 		    except KeyError, e:
 			continue
 
+		imgs = section.findall('img_name')
+		for img in imgs:
+			memory_attr = img.get('memory')
+			if memory_attr != None and memory_attr == memory_size:
+				filename = img.text;
+
+			atf_image = img.get('atf')
+			if atf_image != None and atf == "true":
+				filename = img.text;
+
 	    else:
+		if wifi_fw_type_min:
+		   partition = section.attrib['label']
+
+		   for fw_type in range(int(wifi_fw_type_min), int(wifi_fw_type_max) + 1):
+			if image_type == "all" or section.attrib['image_type'] == image_type:
+			   filename = section.attrib['filename_img' + str(fw_type)]
+			   if filename == "":
+				continue
+			   wifi_fw_type = str(fw_type)
+			   ret = self.__gen_flash_script_wififw(entries, partition, filename, wifi_fw_type, flinfo, script)
+			   if ret == 0:
+				return 0
+			   wifi_fw_type = ""
+
+		   wifi_fw_type_min = ""
+		   wifi_fw_type_max = "" # Clear for next partition
+		   continue
+
 		if diff_soc_ver_files:
                    try:
                         for version in range(1, int(diff_soc_ver_files)+1):
@@ -1025,7 +1402,7 @@
                                 partition = section.attrib['label']
                            if filename == "":
                                 continue
-			   if section.attrib['optional']:
+			   if 'optional' in section.attrib:
 				if not os.path.exists(os.path.join(self.images_dname, filename)):
 				     file_exists = 0
                            ret = self.__gen_flash_script_image(filename, version, file_exists, machid, partition, flinfo, script)
@@ -1038,11 +1415,31 @@
                         print "Skipping partition '%s'" % section.attrib['label']
                         pass
 
+		if section != None and filename != "" and section.get('filename_mem' + memory_size) != None:
+			filename = section.get('filename_mem' + memory_size)
+
+		if section != None and atf == "true" and section.get('filename_atf') != None:
+			filename = section.get('filename_atf')
+
             if filename != "":
                 ret = self.__gen_flash_script_image(filename, soc_version, file_exists, machid, partition, flinfo, script)
                 if ret == 0:
                     return 0
 
+	    if self.flash_type in [ "nand", "nand-4k", "norplusnand", "norplusnand-4k" ] and partition == "rootfs" and qcn6122 == "true":
+
+		fw_imgs = section.findall('img_name')
+		for fw_img in fw_imgs:
+		    wifi_fw_type = fw_img.get('wififw_type')
+		    if wifi_fw_type != None:
+			fw_filename = fw_img.text
+			if fw_filename != "":
+			    ret = self.__gen_flash_script_wififw_ubi_volume(entries, fw_filename, wifi_fw_type, script)
+			    if ret == 0:
+				return 0
+			wifi_fw_type = ""
+		continue
+
         return 1
 
     def __gen_script_cdt(self, images, flinfo, root, section_conf, partition):
@@ -1089,9 +1486,59 @@
                 if image_info not in images:
 		    images.append(image_info)
 
-    def __gen_script_append_images(self, filename, soc_version, images, flinfo, root, section_conf, partition):
+    def __gen_script_bootldr(self, images, flinfo, root, section_conf, partition):
+        global ARCH_NAME
 
-        global HK10
+        entries = root.findall(".//data[@type='MACH_ID_BOARD_MAP']/entry")
+
+        for section in entries:
+
+            board = section.find(".//board").text
+            tiny_image = section.find('.//tiny_image')
+
+            if tiny_image == None:
+                continue
+
+            if ARCH_NAME != "ipq806x":
+                try:
+                    memory = section.find(".//memory").text
+                except AttributeError, e:
+                    memory = "128M16"
+
+                if memory_size != "default":
+                    filename = "bootldr1_" + board + "_" + memory + "_LM" + memory_size + ".mbn"
+                else:
+                    filename = "bootldr1_" + board + "_" + memory + ".mbn"
+                file_info = "bootldr1_" + board + "_" + memory
+            else:
+                filename = "bootldr1_" + board + ".mbn"
+                file_info = "bootldr1_" + board
+
+            part_info = self.__get_part_info(partition)
+
+            if part_info == None and self.flinfo.type != 'norplusnand':
+                continue
+
+            if self.flinfo.type == 'nand':
+                img_size = self.__get_img_size(filename)
+                size = roundup(img_size, flinfo.pagesize)
+                if ( size != img_size ):
+                    filename = filename + ".padded"
+            if self.flinfo.type == 'emmc':
+                img_size = self.__get_img_size(filename)
+                size = roundup(img_size, flinfo.blocksize)
+                if ( size != img_size ):
+                    filename = filename + ".padded"
+            image_info = ImageInfo(file_info + "-" + sha1(filename),
+                                   filename, "firmware")
+            if filename.lower() != "none":
+                if image_info not in images:
+		    images.append(image_info)
+
+
+    def __gen_script_append_images(self, filename, soc_version, wifi_fw_type, images, flinfo, root, section_conf, partition):
+
+        global QCN9000
 
 	part_info = self.__get_part_info(partition)
 	if part_info == None and self.flinfo.type != 'norplusnand':
@@ -1119,6 +1566,8 @@
 	    section_conf = "ubi"
 	elif section_conf == "wififw" and self.flash_type in ["nand", "nand-4k", "nand-audio", "nand-audio-4k", "norplusnand", "norplusnand-4k"]:
 	    section_conf = "wififw_ubi"
+	elif section_conf == "wififw" and wifi_fw_type:
+	    section_conf = filename[:-13]
 
 	if soc_version:
 	    section_conf = section_conf + "_v" + str(soc_version)
@@ -1129,6 +1578,14 @@
 	    if image_info not in images:
 		images.append(image_info)
 
+    def __gen_script_append_images_wififw_ubi_volume(self, fw_filename, wifi_fw_type, images):
+
+	image_info = ImageInfo(fw_filename[:-13] + "-" + sha1(fw_filename),
+				fw_filename, "firmware")
+	if fw_filename.lower() != "none":
+	    if image_info not in images:
+		images.append(image_info)
+
     def __gen_script(self, script_fp, script, images, flinfo, root):
         """Generate the script to flash the multi-image blob.
 
@@ -1139,32 +1596,42 @@
         """
 	global MODE
 	global SRC_DIR
-	global HK10
+	global QCN9000
 
 	soc_version = 0
 	diff_soc_ver_files = 0
+	wifi_fw_type = ""
+	wifi_fw_type_min = ""
+	wifi_fw_type_max = ""
 	diff_files = ""
 	file_exists = 1
 
-        ret = self.__gen_flash_script(script, flinfo, root)
+        ret = self.__gen_flash_script(script, flinfo, root, True)
         if ret == 0:
             return 0 #Stop packing this single-image
 
-        if HK10:
-            script.end_if() #end if started for hk10+pine
+        if QCN9000:
+            script.end_if() #end if started for hk+pine
 
         if (self.flash_type == "norplusemmc" and flinfo.type == "emmc") or (self.flash_type != "norplusemmc"):
             if flinfo.type == "emmc":
-                script.start_activity("Flashing rootfs_data:")
-                part_info = self.partitions["rootfs_data"]
-                script.erase(part_info.offset, part_info.length)
-                script.finish_activity()
+                srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + flinfo.type + "-partition.xml"
+                rpart = ET.parse(srcDir_part)
+                parts = rpart.findall(".//physical_partition[@ref='emmc']/partition")
+                for index in range(len(parts)):
+                        section = parts[index]
+                        if section.attrib['label'] == "rootfs_data":
+                            script.start_activity("Flashing rootfs_data:")
+                            part_info = self.partitions["rootfs_data"]
+                            script.erase(part_info.offset, part_info.length)
+                            script.finish_activity()
             script.end()
 
         if self.flash_type == "norplusemmc" and flinfo.type == "emmc":
             srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + flinfo.type + "-partition.xml"
         else:
             srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + self.flash_type.lower() + "-partition.xml"
+
         root_part = ET.parse(srcDir_part)
         if self.flash_type != "emmc" and flinfo.type != "emmc":
             parts = root_part.findall(".//partitions/partition")
@@ -1229,26 +1696,31 @@
                     except KeyError, e:
 			continue
                     partition = section[0].text
-                else:
 
+                else:
 		    try:
 			diff_files = section.attrib['diff_files']
 		    except KeyError, e:
-                        try:
+			try:
 			    diff_soc_ver_files = section.attrib['diff_soc_ver_files']
 			    partition = section.attrib['label']
 			except KeyError, e:
-			    try:
-			       if image_type == "all" or section.attrib['image_type'] == image_type:
-				   filename = section.attrib['filename']
-                                   if lk == "true" and "u-boot" in filename:
-                                       filename = filename.replace("u-boot", "lkboot")
-				   partition = section.attrib['label']
-			       if filename == "":
-				   continue
-			    except KeyError, e:
-			       print "Skipping partition '%s'" % section.attrib['label']
-			       pass
+			    if (qcn6122 == "true" or tiny_16m == "true") and 'wififw_type_min' in section.attrib:
+				wifi_fw_type_min = section.attrib['wififw_type_min']
+				wifi_fw_type_max = section.attrib['wififw_type_max']
+				partition = section.attrib['label']
+			    else:
+				try:
+				    if image_type == "all" or section.attrib['image_type'] == image_type:
+					filename = section.attrib['filename']
+					if filename == "":
+					    continue
+					partition = section.attrib['label']
+					if lk == "true" and "u-boot" in filename:
+					    filename = filename.replace("u-boot", "lkboot")
+				except KeyError, e:
+				    print "Skipping partition '%s'" % section.attrib['label']
+				    pass
 
 		    if diff_files == "true":
 			try:
@@ -1287,9 +1759,33 @@
                 except KeyError, e:
                     continue
 
+            if section_conf == "bootldr1":
+		try:
+		    if image_type == "all" or section[8].attrib['image_type'] == image_type:
+	                self.__gen_script_bootldr(images, flinfo, root, section_conf, partition)
+			continue
+                except KeyError, e:
+                    continue
+
             if flinfo.type != "emmc":
 
 		img = section.find('img_name')
+
+		if img != None and 'wififw_type' in img.attrib and (qcn6122 == "true" or tiny_16m == "true"):
+		    imgs = section.findall('img_name')
+		    try:
+			for img in imgs:
+			    wifi_fw_type = img.get('wififw_type')
+			    filename = img.text
+			    if 'optional' in img.attrib:
+				if not os.path.exists(os.path.join(self.images_dname, filename)):
+				    continue
+			    self.__gen_script_append_images(filename, soc_version, wifi_fw_type, images, flinfo, root, section_conf, partition)
+		            wififw_type = ""
+			continue
+		    except KeyError, e:
+			continue
+
 		if img != None and 'soc_version' in img.attrib:
 
 		    imgs = section.findall('img_name')
@@ -1297,45 +1793,72 @@
 		        for img in imgs:
 				soc_version = img.get('soc_version')
 				filename = img.text
-                                if HK10 and section_conf == "wififw":
-                                    filename_hk10 = filename.replace("wifi_fw_ubi", "wifi_fw_ipq8074_qcn9000_ubi")
-				    if os.path.exists(os.path.join(self.images_dname, filename_hk10)):
-                                        section_conf_hk10 = section_conf + "_ubi_hk10"
-                                        self.__gen_script_append_images(filename_hk10, soc_version, images, flinfo, root, section_conf_hk10, partition)
+                                if QCN9000 and section_conf == "wififw":
+                                    filename_qcn9000 = filename.replace("wifi_fw_ubi", "wifi_fw_ipq8074_qcn9000_ubi")
+				    if os.path.exists(os.path.join(self.images_dname, filename_qcn9000)):
+                                        section_conf_qcn9000 = section_conf + "_ubi_qcn9000"
+                                        self.__gen_script_append_images(filename_qcn9000, soc_version, wifi_fw_type, images, flinfo, root, section_conf_qcn9000, partition)
 				if 'optional' in img.attrib:
 				    if not os.path.exists(os.path.join(self.images_dname, filename)):
 					file_exists = 0
 
 				if file_exists == 1:
-				    self.__gen_script_append_images(filename, soc_version, images, flinfo, root, section_conf, partition)
+				    self.__gen_script_append_images(filename, soc_version, wifi_fw_type, images, flinfo, root, section_conf, partition)
 				file_exists = 1
 			soc_version = 0 # Clear soc_version for next iteration
 			continue
 		    except KeyError, e:
 			continue
 
-                # system-partition specific for HK10+PINE
-                if section_conf == "mibib" and HK10:
-                    img = section.find('img_name')
-                    filename_hk10 = img.text[:-4] + "-hk10.bin"
-                    section_conf_hk10 = section_conf + "_hk10"
-                    self.__gen_script_append_images(filename_hk10, soc_version, images, flinfo, root, section_conf_hk10, partition)
+		imgs = section.findall('img_name')
+		for img in imgs:
+			memory_attr = img.get('memory')
+			if memory_attr != None and memory_attr == memory_size:
+				filename = img.text;
 
+			atf_image = img.get('atf')
+			if atf_image != None and atf == "true":
+				filename = img.text;
+
+                # system-partition specific for HK+PINE
+                if section_conf == "mibib" and QCN9000:
+                    img = section.find('img_name')
+                    filename_qcn9000 = img.text[:-4] + "-qcn9000.bin"
+                    section_conf_qcn9000 = section_conf + "_qcn9000"
+                    self.__gen_script_append_images(filename_qcn9000, soc_version, wifi_fw_type, images, flinfo, root, section_conf_qcn9000, partition)
             else:
+		# wififw images specific for RDP based on machid
+		if wifi_fw_type_min:
+
+		    for fw_type in range(int(wifi_fw_type_min), int(wifi_fw_type_max) + 1):
+			if image_type == "all" or section.attrib['image_type'] == image_type:
+			    filename = section.attrib['filename_img' + str(fw_type)]
+			if filename == "":
+			    continue
+			if 'optional' in section.attrib:
+			    if not os.path.exists(os.path.join(self.images_dname, filename)):
+				continue
+			wifi_fw_type = str(fw_type)
+			self.__gen_script_append_images(filename, soc_version, wifi_fw_type, images, flinfo, root, section_conf, partition)
+			wifi_fw_type = ""
+
+		    wifi_fw_type_min = ""
+		    wifi_fw_type_max = "" # Clean for next partition
+		    continue
+
 		if diff_soc_ver_files:
 		    try:
 			for version in range(1, int(diff_soc_ver_files)+1):
 			   if image_type == "all" or section.attrib['image_type'] == image_type:
 				filename = section.attrib['filename_v' + str(version)]
-				partition = section.attrib['label']
 			   if filename == "":
 				continue
-			   if section.attrib['optional']:
+			   if 'optional' in section.attrib:
 				if not os.path.exists(os.path.join(self.images_dname, filename)):
 					file_exists = 0
 
 			   if file_exists == 1:
-			        self.__gen_script_append_images(filename, version, images, flinfo, root, section_conf, partition)
+			        self.__gen_script_append_images(filename, version, wifi_fw_type, images, flinfo, root, section_conf, partition)
 			   file_exists = 1
 
 			diff_soc_ver_files = 0 # Clear diff_soc_ver_files for next iteration
@@ -1344,8 +1867,31 @@
 			print "Skipping partition '%s'" % section.attrib['label']
 			pass
 
+		if section != None and filename != "" and section.get('filename_mem' + memory_size) != None:
+			filename = section.get('filename_mem' + memory_size)
+
+		if section != None and atf == "true" and section.get('filename_atf') != None:
+			filename = section.get('filename_atf')
+
             if filename != "":
-                self.__gen_script_append_images(filename, soc_version, images, flinfo, root, section_conf, partition)
+                self.__gen_script_append_images(filename, soc_version, wifi_fw_type, images, flinfo, root, section_conf, partition)
+
+	    if self.flash_type in [ "nand", "nand-4k", "norplusnand", "norplusnand-4k" ] and section_conf == "rootfs" and qcn6122 == "true":
+
+		fw_imgs = section.findall('img_name')
+		try:
+		    for fw_img in fw_imgs:
+			wifi_fw_type = fw_img.get('wififw_type')
+			if wifi_fw_type != None:
+			    fw_filename = fw_img.text
+			    ret = self.__gen_script_append_images_wififw_ubi_volume(fw_filename, wifi_fw_type, images)
+			    if ret == 0:
+				return 0
+			wifi_fw_type = ""
+		    continue
+		except KeyError, e:
+		    continue
+
         return 1
 
     def __mkimage(self, images):
@@ -1373,7 +1919,7 @@
 
         its_fp.write(its_data)
         its_fp.close()
-	
+
         try:
             cmd = [SRC_DIR + "/mkimage", "-f", self.its_fname, self.img_fname]
             ret = subprocess.call(cmd)
@@ -1392,8 +1938,8 @@
     def __gen_board_script(self, flinfo, part_fname, images, root):
 	global SRC_DIR
 	global ARCH_NAME
-	global HK10
-	global IF_HK10
+	global QCN9000
+	global IF_QCN9000
 
         """Generate the flashing script for one board.
 
@@ -1404,7 +1950,7 @@
         fconf_fname -- string, flash config file specific to the board
         images -- list of ImageInfo, append images used by the board here
         """
-        IF_HK10 = False
+        IF_QCN9000 = False
         script_fp = open(self.scr_fname, "a")
         self.flinfo = flinfo
 
@@ -1436,22 +1982,22 @@
                 script = Flash_Script(flinfo, pagesize)
 
             script.probe()
-            # system-partition specific for HK10+PINE
-            if HK10:
-                IF_HK10 = True
-                part_fname_hk10 = part_fname[:-4] + "-hk10.bin"
-                mibib_hk10 = MIBIB(part_fname_hk10, flinfo.pagesize, flinfo.blocksize,
+            # system-partition specific for HK+PINE
+            if QCN9000:
+                IF_QCN9000 = True
+                part_fname_qcn9000 = part_fname[:-4] + "-qcn9000.bin"
+                mibib_qcn9000 = MIBIB(part_fname_qcn9000, flinfo.pagesize, flinfo.blocksize,
                                    flinfo.chipsize, blocksize, chipsize, root_part)
-                self.partitions = mibib_hk10.get_parts()
+                self.partitions = mibib_qcn9000.get_parts()
 
-                script.append('if test "$machid" = "801000e" || test "$machid" = "801010e"; then\n', fatal=False)
-                ret = self.__gen_flash_script(script, flinfo, root)
+                script.append('if test "$machid" = "801000e" || test "$machid" = "801010e" || test "$machid" = "8010012" || test "$machid" = "8010013" || test "$machid" = "8010500"; then\n', fatal=False)
+                ret = self.__gen_flash_script(script, flinfo, root, True)
                 if ret == 0:
-                    return 0 #Issue in packing hk10+pine single-image
+                    return 0 #Issue in packing hk+pine single-image
 
                 script.append('else', fatal=False)
                 self.partitions = {}
-                IF_HK10 = False
+                IF_QCN9000 = False
 
             mibib = MIBIB(part_fname, flinfo.pagesize, flinfo.blocksize,
                           flinfo.chipsize, blocksize, chipsize, root_part)
@@ -1466,8 +2012,8 @@
 	if ret == 0:
 	    return 0
 
-	if HK10:
-	    HK10 = False
+	if QCN9000:
+	    QCN9000 = False
 
         try:
             script_fp.write(script.dumps())
@@ -1517,10 +2063,10 @@
 	global SRC_DIR
 	global ARCH_NAME
 	global MODE
-	global HK10
+	global QCN9000
 
         try:
-            if ftype == "tiny-nor":
+            if ftype == "tiny-nor" or ftype == "tiny-nor-debug":
                 part_info = root.find(".//data[@type='" + "NOR_PARAMETER']")
             elif ftype in ["nand", "nand-4k", "nand-audio", "nand-audio-4k"]:
                 if root.find(".//data[@type='NAND_PARAMETER']/entry") != None:
@@ -1539,11 +2085,8 @@
             else:
                 part_info = root.find(".//data[@type='" + ftype.upper() + "_PARAMETER']")
 
-	    if ARCH_NAME == "ipq6018" or ARCH_NAME == "ipq5018":
-		if MODE == "64":
-                    MODE_APPEND = "_64"
-                else:
-                    MODE_APPEND = ""
+            if ARCH_NAME in ["ipq6018", "ipq5018", "ipq807x"]:
+                MODE_APPEND = "_64" if MODE == "64" else ""
 
                 if ftype in ["nand-audio", "nand-audio-4k"]:
                     UBINIZE_CFG_NAME = ARCH_NAME + "-ubinize" + MODE_APPEND + "-audio.cfg"
@@ -1558,12 +2101,15 @@
                 f1.close()
                 f2.close()
 
-                if ftype in ["nand-4k", "nand-audio-4k", "norplusnand-4k"]:
-                    if ARCH_NAME == "ipq6018":
-                        UBI_IMG_NAME = "openwrt-ipq-ipq60xx" + MODE_APPEND + "-ubi-root-m4096-p256KiB.img"
-                    if ARCH_NAME == "ipq5018":
-                        UBI_IMG_NAME = "openwrt-ipq-ipq50xx" + MODE_APPEND + "-ubi-root-m4096-p256KiB.img"
+                part_file = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + ftype + "-partition.xml"
+                parts = ET.parse(part_file).findall('.//partitions/partition')
+                for index in range(len(parts)):
+                        section = parts[index]
+                        if section[0].text == "rootfs":
+                            rootfs_pos = 9 if MODE == "64" else 8
+                            UBI_IMG_NAME = section[rootfs_pos].text
 
+                if ftype in ["nand-4k", "nand-audio-4k", "norplusnand-4k"]:
                     cmd = '%s -m 4096 -p 256KiB -o root.ubi %s' % ((SRC_DIR + "/ubinize") ,UBINIZE_CFG_NAME)
                     ret = subprocess.call(cmd, shell=True)
                     if ret != 0:
@@ -1572,12 +2118,8 @@
                     ret = subprocess.call(cmd, shell=True)
                     if ret != 0:
                          error("ubi image copy operation failed")
-                elif ftype in ["nand", "nand-audio", "norplusnand"]:
-                    if ARCH_NAME == "ipq6018":
-                        UBI_IMG_NAME = "openwrt-ipq-ipq60xx" + MODE_APPEND +"-ubi-root.img"
-                    if ARCH_NAME == "ipq5018":
-                        UBI_IMG_NAME = "openwrt-ipq-ipq50xx" + MODE_APPEND +"-ubi-root.img"
 
+                elif ftype in ["nand", "nand-audio", "norplusnand"]:
                     cmd = '%s -m 2048 -p 128KiB -o root.ubi %s' % ((SRC_DIR + "/ubinize") ,UBINIZE_CFG_NAME)
                     ret = subprocess.call(cmd, shell=True)
                     if ret != 0:
@@ -1597,9 +2139,9 @@
             blocks_per_chip = int(part_info.find(".//total_block").text)
 
             if ARCH_NAME == "ipq807x" and (ftype == "norplusnand" or ftype == "nand"):
-                HK10 = True
+                QCN9000 = True
 
-            if ftype in ["tiny-nor", "norplusnand", "norplusnand-4k", "norplusemmc"]:
+            if ftype in ["tiny-nor", "norplusnand", "norplusnand-4k", "norplusemmc", "tiny-nor-debug"]:
                 ftype = "nor"
             if ftype in ["nand-4k", "nand-audio", "nand-audio-4k"]:
                 ftype = "nand"
@@ -1617,11 +2159,11 @@
 
     def __process_board(self, images, root):
 
-        global HK10
+        global QCN9000
 
-        HK10 = False
+        QCN9000 = False
         try:
-            if self.flash_type in [ "nand", "nand-4k", "nand-audio", "nand-audio-4k", "nor", "tiny-nor", "norplusnand", "norplusnand-4k" ]:
+            if self.flash_type in [ "nand", "nand-4k", "nand-audio", "nand-audio-4k", "nor", "tiny-nor", "norplusnand", "norplusnand-4k", "tiny-nor-debug" ]:
                 ret = self.__process_board_flash(self.flash_type, images, root)
             elif self.flash_type == "emmc":
                 ret = self.__process_board_flash_emmc(self.flash_type, images, root)
@@ -1657,7 +2199,7 @@
             self.__mkimage(images)
         else:
 	    fail_img = out_fname.split("/")
-            print "Failed to pack %s" % fail_img[-1]
+            error("Failed to pack %s" % fail_img[-1])
 
 class UsageError(Exception):
     """Indicates error in command arguments."""
@@ -1682,6 +2224,9 @@
 	global image_type
 	global memory_size
         global lk
+        global atf
+        global skip_4k_nand
+	global qcn6122
 
         """Start the parsing process, and populate members with parsed value.
 
@@ -1691,7 +2236,7 @@
 	cdir = os.path.abspath(os.path.dirname(""))
         if len(sys.argv) > 1:
             try:
-                opts, args = getopt(sys.argv[1:], "", ["arch=", "fltype=", "srcPath=", "inImage=", "outImage=", "image_type=", "memory=", "lk"])
+                opts, args = getopt(sys.argv[1:], "", ["arch=", "fltype=", "srcPath=", "inImage=", "outImage=", "image_type=", "memory=", "lk", "skip_4k_nand", "atf", "qcn6122"])
             except GetoptError, e:
 		raise UsageError(e.msg)
 
@@ -1720,6 +2265,14 @@
                 elif option =="--lk":
                     lk = "true"
 
+                elif option =="--atf":
+                    atf = "true"
+
+                elif option =="--skip_4k_nand":
+                    skip_4k_nand = "true"
+
+                elif option == "--qcn6122":
+                    qcn6122 = "true"
 
 #Verify Arguments passed by user
 
@@ -1743,7 +2296,7 @@
 	    if self.flash_type == None:
                 self.flash_type = ArgParser.DEFAULT_TYPE
 	    for flash_type in self.flash_type.split(","):
-                if flash_type not in [ "nand", "nor", "tiny-nor", "emmc", "norplusnand", "norplusemmc" ]:
+                if flash_type not in [ "nand", "nor", "tiny-nor", "emmc", "norplusnand", "norplusemmc", "tiny-nor-debug" ]:
                     raise UsageError("invalid flash type '%s'" % flash_type)
 
 # Verify src Path
@@ -1771,7 +2324,7 @@
         print "options:"
         print "  --arch \tARCH_TYPE [ipq40xx/ipq806x/ipq807x/ipq807x_64/ipq6018/ipq6018_64/ipq5018/ipq5018_64]"
 	print
-	print "  --fltype \tFlash Type [nor/tiny-nor/nand/emmc/norplusnand/norplusemmc]"
+	print "  --fltype \tFlash Type [nor/tiny-nor/nand/emmc/norplusnand/norplusemmc/tiny-nor-debug]"
         print " \t\tMultiple flashtypes can be passed by a comma separated string"
         print " \t\tDefault is all. i.e If \"--fltype\" is not passed image for all the flash-type will be created.\n"
         print "  --srcPath \tPath to the directory containg the meta scripts and configs"
@@ -1785,6 +2338,8 @@
         print " \t\tIf specified, CDTs created with specified memory size will be used for single-image.\n"
         print
         print "  --lk \t\tReplace u-boot with lkboot for appsbl"
+        print "  --atf \t\tReplace tz with atf for QSEE partition"
+        print "  --skip_4k_nand \tskip generating 4k nand images"
         print " \t\tThis Argument does not take any value"
         print "Pack Version: %s" % version
 
@@ -1818,8 +2373,17 @@
                 BASE_ADDR = "0x41000000"
 
         src = parser.images_dname + "/qcom-" + BOARD_NAME + ".dtb"
+
+	#alternate name(alt_src) for linux-5.4 dtbs
+	alt_src = parser.images_dname + "/" + BOARD_NAME + ".dtb"
+	if ARCH_NAME == "ipq807x":
+		alt_src = parser.images_dname + "/ipq8074-hk01.dtb"
+
         if not os.path.exists(src):
-            error("%s file not found" % src)
+	    if os.path.exists(alt_src):
+		src = alt_src
+	    else:
+		error("%s file not found" % src)
         copy(src, TMP_DIR)
 
         src = parser.images_dname + "/Image"
@@ -1859,6 +2423,8 @@
 
     Created to avoid polluting the global namespace.
     """
+
+    global tiny_16m
     try:
         parser = ArgParser()
         parser.parse(sys.argv)
@@ -1874,18 +2440,25 @@
     config = SRC_DIR + "/" + ARCH_NAME + "/config.xml"
     root = ET.parse(config)
 
-# Add nand-4k flash type, if nand flash type is specified
-    if "nand" in parser.flash_type.split(","):
-        if root.find(".//data[@type='NAND_PARAMETER']/entry") != None:
-            parser.flash_type = parser.flash_type + ",nand-4k"
+    if skip_4k_nand != "true":
+	# Add nand-4k flash type, if nand flash type is specified
+	if "nand" in parser.flash_type.split(","):
+            if root.find(".//data[@type='NAND_PARAMETER']/entry") != None:
+		parser.flash_type = parser.flash_type + ",nand-4k"
 
-# Add norplusnand-4k flash type, if norplusnand flash type is specified
-    if "norplusnand" in parser.flash_type.split(","):
-        if root.find(".//data[@type='NAND_PARAMETER']/entry") != None:
-            parser.flash_type = parser.flash_type + ",norplusnand-4k"
+	# Add norplusnand-4k flash type, if norplusnand flash type is specified
+	if "norplusnand" in parser.flash_type.split(","):
+            if root.find(".//data[@type='NAND_PARAMETER']/entry") != None:
+		parser.flash_type = parser.flash_type + ",norplusnand-4k"
 
 # Format the output image name from Arch, flash type and mode
     for flash_type in parser.flash_type.split(","):
+
+	if ARCH_NAME == "ipq5018" and (flash_type == "tiny-nor" or flash_type == "tiny-nor-debug"):
+	    tiny_16m = "true"
+	else:
+	    tiny_16m = "false"
+
         if image_type == "hlos":
             if MODE == "64":
                 parser.out_fname = flash_type + "-" + ARCH_NAME + "_" + MODE + "-apps.img"
diff --git a/tools/squashfs_to_array.sh b/tools/squashfs_to_array.sh
new file mode 100644
index 0000000..8ec8041
--- /dev/null
+++ b/tools/squashfs_to_array.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+######################################################################
+# Copyright (c) 2020 The Linux Foundation. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 and
+# only version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#####################################################################
+
+unsquashfs -d tmp bt_fw_patch_squashfs.img
+echo "" > bt_binary_array.h
+for entry in ./tmp/image/*
+do
+  echo "$entry"
+  file_name=${entry##*/}
+  file_name="${file_name//./}"
+
+  echo "unsigned char $file_name[] = {" >> bt_binary_array.h
+  hexdump -v  -e '15/1 "0x%02X, " 1/1  " 0x%02X,\n"' $entry | sed 's/\, 0x .*//' >> bt_binary_array.h
+
+  echo "};" >> bt_binary_array.h
+done
+
+rm -rf ./tmp