Merge "ipq40xx: removing redundant initialization in dts"
diff --git a/arch/arm/dts/ipq5018-emulation.dts b/arch/arm/dts/ipq5018-emulation.dts
index d0b1b05..5009210 100644
--- a/arch/arm/dts/ipq5018-emulation.dts
+++ b/arch/arm/dts/ipq5018-emulation.dts
@@ -28,6 +28,11 @@
 		compatible = "qcom,sdhci-msm";
 	};
 
+	nand: nand-controller@79B0000 {
+		status = "ok";
+		nand_gpio {};
+	};
+
 	timer {
 		gpt_freq_hz = <240000>;
 	};
diff --git a/arch/arm/dts/ipq5018-soc.dtsi b/arch/arm/dts/ipq5018-soc.dtsi
index e8dc902..56016fc 100644
--- a/arch/arm/dts/ipq5018-soc.dtsi
+++ b/arch/arm/dts/ipq5018-soc.dtsi
@@ -62,4 +62,55 @@
 		spi_gpio {};
 	};
 
+	nand: nand-controller@79B0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "qcom,qpic-nand-v2.1.1";
+		reg = <0x79B0000 0x10000>;
+
+		nand_gpio {
+			qspi_data0 {
+				gpio = <7>;
+				func = <2>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				oe = <GPIO_OE_DISABLE>;
+			};
+			qspi_data1 {
+				gpio = <6>;
+				func = <2>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				oe = <GPIO_OE_DISABLE>;
+			};
+			qspi_data2 {
+				gpio = <5>;
+				func = <2>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				oe = <GPIO_OE_DISABLE>;
+			};
+			qspi_data3 {
+				gpio = <4>;
+				func = <2>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				oe = <GPIO_OE_DISABLE>;
+			};
+			qspi_cs_n {
+				gpio = <8>;
+				func = <2>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				oe = <GPIO_OE_DISABLE>;
+			};
+			qspi_clk {
+				gpio = <9>;
+				func = <2>;
+				pull = <GPIO_PULL_DOWN>;
+				drvstr = <GPIO_8MA>;
+				oe = <GPIO_OE_DISABLE>;
+			};
+		};
+	};
 };
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 d556429..ed013c3 100644
--- a/arch/arm/include/asm/arch-qca-common/qca_common.h
+++ b/arch/arm/include/asm/arch-qca-common/qca_common.h
@@ -94,6 +94,7 @@
 			    */
 	uint32_t offset; /* offset to be added to start address */
 	uint32_t dump_level;
+	uint32_t to_compress; /* non-zero represent for compressed dump*/
 };
 extern struct dumpinfo_t dumpinfo_n[];
 extern int dump_entries_n;
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 f75145d..5a802c3 100644
--- a/arch/arm/include/asm/arch-qca-common/qpic_nand.h
+++ b/arch/arm/include/asm/arch-qca-common/qpic_nand.h
@@ -94,11 +94,200 @@
 #define NAND_EBI2_ECC_BUF_CFG		NAND_REG(0x00F0)
 #define NAND_HW_INFO			NAND_REG(0x00FC)
 #define NAND_FLASH_BUFFER		NAND_REG(0x0100)
+#define NAND_FLASH_FEATURES		NAND_REG(0x0F64)
 #define QPIC_NAND_CTRL			NAND_REG(0x0F00)
 #define QPIC_NAND_DEBUG			NAND_REG(0x0F0C)
+/* Additional Register set for Serial NAND */
+#define NAND_AUTO_STATUS_EN		NAND_REG(0x002C)
+#define NAND_VERSION			NAND_REG(0x4F08)
+#define SPI_NAND_DEV_CMD0		NAND_REG(0x70A0)
+#define SPI_NAND_DEV_CMD1		NAND_REG(0x70A4)
+#define SPI_NAND_DEV_CMD2		NAND_REG(0x70A8)
+#define SPI_NAND_DEV_CMD3		NAND_REG(0x70D0)
+#define NAND_FLASH_DEV_CMD_VLD		NAND_REG(0x70AC)
+#define SPI_NAND_DEV_CMD7		NAND_REG(0x70B0)
+#define SPI_NAND_DEV_CMD8		NAND_REG(0x70B4)
+#define SPI_NAND_DEV_CMD9		NAND_REG(0x70B8)
+#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)
+
+/* Register mask & shift value used in SPI transfer mode */
+#define SPI_TRANSFER_MODE_1X		0x1
+#define SPI_TRANSFER_MODE_4X		0x3
+/* These value as per HPG , these value as per 2K device*/
+#define SPI_NAND_DEVn_CFG0		0x1A5408D0
+#define SPI_NAND_DEVn_CFG1		0x08287440
+#define SPI_NAND_DEVn_CFG1_RESET	0x087476B1
+/* value for below register according to HPG : 0x42040702 for reset
+ * and 0x42040700 for reset disable
+ */
+#define SPI_NAND_DEVn_ECC_CFG		0x42040702
+#define SPI_NAND_DEVn_ECC_CFG_RST_DIS	0x42040700
+#define FLASH_DEV_CMD_VLD		0x0000000D
+/* These Value as per HPG */
+#define NAND_FLASH_DEV_CMD0_VAL		0x1080D8D8
+#define NAND_FLASH_DEV_CMD1_VAL		0xF00F3000
+#define NAND_FLASH_DEV_CMD2_VAL		0xF0FF709F
+#define NAND_FLASH_DEV_CMD3_VAL		0x3F310015
+/* For Micron NAND_FLASH_DEV_CMD3_VAL value should
+ * be 0x3F300015
+ */
+#define NAND_FLASH_DEV_CMD7_VAL		0x04061F0F
+#define NAND_FLASH_DEV_CMD7_WE		0x60000
+#define NAND_FLASH_DEV_CMD7_WD		0x40000000
+#define NAND_FLASH_DEV_CMD7_SET_FTR	0x1F00
+#define NAND_FLASH_DEV_CMD7_GET_FTR	0x0F
+#define SPI_BUSY_CHECK_WAIT_CNT		0x00000010
+#define SPI_CFG_VAL			0x1924C00D
+#define SPI_LOAD_CLK_CNTR_INIT_EN	(1 << 28)
+#define SPI_NUM_ADDR_CYCLES		0x000DA4DB
+#define NAND_FLASH_SET_FEATURE_MASK	0xB800000E
+#define NAND_FLASH_GET_FEATURE_MASK	0x3800000E
+#define QPIC_HARDWARE_VERSION_2_0	0x20000000
+#define NAND_FLASH_STATUS_MASK		0xC
+#define QPIC_SERIAL_ERROR		517
+#define QPIC_SPI_SET_FEATURE		(1 << 31)
+#define QPIC_SPI_GET_FEATURE		~(1 << 31)
+#define QPIC_SPI_WP_SET			(1 << 28)
+#define QPIC_SPI_HOLD_SET		(1 << 27)
+#define QPIC_SPI_TRANSFER_MODE_X1	(1 << 29)
+#define QPIC_SPI_TRANSFER_MODE_X4	(3 << 29)
+#define QPIC_SPI_BOOST_MODE		(1 << 11)
+#define QPIC_SPI_NAND_CTRL_VAL		0x341
+#define QPIC_SPI_NAND_AUTO_STATUS_VAL	0x003F003F
+#define QPIC_NAND_FLASH_CMD_WE_VAL	0XB800000F
+#define QPIC_NAND_FLASH_CMD_WD_VAL	0x3800000F
+#define WR_EN				0x1
+#define WR_DIS				0x0
+
+/* According to GigaDevice data sheet Block Protection Register is:
+ *  ____________________________________________
+ * |	  |    |    |    |    |     |     |	|
+ * |BRWD  |RSVD| BP2| BP1| BP0| INV | CMP |RSVD |
+ * |      |    |    |    |    |     |     |	|
+ * |______|____|____|____|____|_____|_____|_____|
+ *
+ * NOTE: RSVD = Reserved.
+ *
+ * After power-up the device is in "locked" state i.e feature bits
+ * BP0, BP1, BP2 are set to 1. ENV, CMP, BRWD are set to 0.
+ * When BRWD is set to 1 and WP# is LOW i.e 0, none of the writable
+ * protection feature bits can be set.
+ * When an ERASE command is issued to a locked block, the erase failure,
+ * 04H, is returned.
+ *
+ * With CMP = X, INV = X, BP2 = 0, BP1 = 0, BP0 = 0 : There will be no
+ * block protection functionality.
+ *
+ * When WP# is not LOW, user can issue bellows commands to alter the
+ * protection.
+ *
+ * Issue SET FEATURES register write (1FH)
+ * Issue the feature bit address (A0h)
+ */
+#define FLASH_SPI_NAND_BLK_PROCT_ADDR		0xA0
+#define FLASH_SPI_NAND_BLK_PROCT_DISABLE	0x00
+#define FLASH_SPI_NAND_BLK_PROCT_ENABLE		0x78
+/* According to GigaDevice data sheet Feature Register is:
+ *  _________________________________________________
+ * |	   |      |     |      |    |     |     |    |
+ * |OTP-PRT|OTP_EN| RSVD|ECC-EN|RSVD|RSVD |RSVD |QE  |
+ * |       |      |     |      |    |     |     |    |
+ * |_______|______|_____|______|____|_____|_____|____|
+ *
+ *
+ * NOTE : When a feature is set, it remains active until the
+ * device is power cycled or the feature is written to.once
+ * the device is set, it remains set, even if a RESET (FFH)
+ * command is issued.
+ *
+ * OTP-PRT = X , OTP_EN = 0 : Normal Operation
+ * OTP-PRT = 0, OTP_EN = 1 : Access OTP region, read and program data.
+ *
+ * ECC-EN : ECC is enabled after device power up, so the default
+ * READ and PROGRAM commands operate with internal ECC in the “active”
+ * state. To enable/disable ECC, perform the following command sequence:
+ *
+ * 1) Issue the SET FEATURES command (1FH).
+ * 2) Set the feature bit ECC_EN as you want:
+ * 	a) To enable ECC, Set ECC_EN to 1.
+ * 	b) To disable ECC, Clear ECC_EN to 0.
+ *
+ * NOTE: For this device GD5F1GQ4xExxG
+ * --> Internal ECC Off (ECC_EN=0):
+ *  2048-Byte+128-Byte Full Access.
+ *
+ * --> Internal ECC On (ECC_EN=1, default):
+ *  Program: 2048-Byte+64-Byte.
+ *  Read: 2048-Byte+128-Byte.
+ *
+ * QE : If QE is enabled, the quad IO operations can be executed.
+ *
+ */
+#define FLASH_SPI_NAND_FR_ADDR		0xB0
+#define FLASH_SPI_NAND_FR_ECC_ENABLE	(1 << 4)
+#define FLASH_SPI_NAND_FR_QUAD_ENABLE	0x1
+/* According to GigaDevice data sheet Status Register(0xC0) is:
+ *  _________________________________________________
+ * |	  |    	 |     |     |      |      |    |    |
+ * |RSVD  |RSVD  |ECCS1|ECCS0|P-FAIL|E-FAIL|WEL |OIP |
+ * |      |    	 |     |     |      |      |    |    |
+ * |______|______|_____|_____|_____ |______|____|____|
+ *
+ *
+ * NOTE: RSVD = Reserved.
+ *
+ * P-FAIL : This bit indicates that a program failure has occurred
+ * (P_FAIL set to 1). It will also be set if the user attempts to
+ * program an invalid address or a protected region, including
+ * the OTP area.
+ *
+ * E-FAIL : This bit indicates that an erase failure has occurred
+ * (E_FAIL set to 1). It will also be set if the user attempts to
+ * erase a locked region.
+ *
+ * WEL : This bit indicates the current status of the write enable
+ * latch (WEL) and must be set (WEL = 1), prior to issuing a
+ * PROGRAM EXECUTE or BLOCK ERASE command. It is set by issuing the
+ * WRITE ENABLE command. WEL can also be disabled (WEL = 0), by issuing
+ * the WRITE DISABLE command.
+ *
+ * OIP : This bit is set (OIP = 1 ) when a PROGRAM EXECUTE, PAGE READ,
+ * BLOCK ERASE, or RESET command is executing, indicating the device
+ * is busy. When the bit is 0, the interface is in the ready state.
+ *
+ * ECC Status : ECCS and ECCSE are set to 00b either following a RESET,
+ * or at the beginning of the READ.ECCS and ECCSE are invalid if internal
+ * ECC is disabled (via a SET FEATURES command to reset ECC_EN to 0).
+ *
+ * NOTE: After power-on RESET, ECC status is set to reflect the contents
+ * of block 0, page 0.
+ */
+#define FLASH_SPI_NAND_SR_ADDR       0xC0
+#define FLASH_SPI_NAND_SR_DATA       0x00
+
+/* According to GigaDevice data sheet Feature Register(0xD0) is:
+ *  _________________________________________________
+ * |	  |    	|     |     |      |      |     |    |
+ * |RSVD  |DS-S1|DS-S0|RSVD |RSVD  |RSVD  |RSVD |RSVD|
+ * |      |    	|     |     |      |      |     |    |
+ * |______|_____|_____|_____|______|______|_____|____|
+ *
+ * DS-S1 = 0 , DS-S0 = 0   : Drive strength is 50%
+ * DS-S1 = 0 , DS-S0 = 1   : Drive strength is 25%
+ * DS-S1 = 1 , DS-S0 = 0   : Drive strength is 75%
+ * DS-S1 = 1 , DS-S0 = 1   : Drive strength is 100%
+ *
+ * 00 is the default data byte value for Output Driver Register after power-up
+ */
+#define FLASH_SPI_NAND_FR_DS_ADDR	0xD0
+#define FLASH_SPI_NAND_FR_DS_DATA	0x00
+
 
 /* NANDc registers used during BAM transfer */
 #define NAND_READ_LOCATION_n(n)		(NAND_REG(0xF20) + 4 * (n))
+#define NAND_READ_LOCATION_LAST_CW_n(n)	(NAND_REG(0xF40) + 4 * (n))
 #define NAND_RD_LOC_LAST_BIT(x)		((x) << 31)
 #define NAND_RD_LOC_SIZE(x)		((x) <<  16)
 #define NAND_RD_LOC_OFFSET(x)		((x) <<  0)
@@ -151,6 +340,23 @@
 #define NAND_CMD_BLOCK_ERASE				0x3A
 #define NAND_CMD_FETCH_ID				0x0B
 #define NAND_CMD_RESET_DEVICE				0x0D
+#define NAND_CMD_SET_FEATURE				0x1F
+#define NAND_CMD_GET_FEATURE				0x0F
+#define NAND_CMD_ACC_FEATURE				0x0E
+/* Serial NAND Device command */
+#define SERIAL_NAND_CMD_READ_FROM_CACHE_X4		0x6B
+#define SERIAL_NAND_CMD_READ_FROM_CACHE_DUAL_IO		0xBB
+#define SERIAL_NAND_CMD_READ_FROM_CACHE_QUAD_IO		0xEB
+#define SERIAL_NAND_CMD_READ_ID				0x9F
+#define SERIAL_NAND_CMD_PROGRAM_LOAD			0x02
+#define SERIAL_NAND_CMD_PROGRAM_LOAD_X4			0x32
+#define SERIAL_NAND_CMD_PROGRAM_EXECUTE			0x10
+#define SERIAL_NAND_CMD_PROGRAM_LOAD_RND_DATA		0x84
+#define SERIAL_NAND_CMD_PROGRAM_LOAD_RND_DATA_X4	0xC4  /* Or 0x34 */
+#define SERIAL_NAND_CMD_PROGRAM_LOAD_QUAD_IO		0x72
+#define SERIAL_NAND_CMD_BLOCK_ERASE			0xD8
+#define SERIAL_NAND_CMD_RESET				0xFF
+
 /* NAND Status errors */
 #define NAND_FLASH_MPU_ERR				(1 << 8)
 #define NAND_FLASH_TIMEOUT_ERR				(1 << 6)
@@ -170,6 +376,7 @@
 #define DATA_CONSUMER_PIPE_INDEX		0
 #define DATA_PRODUCER_PIPE_INDEX		1
 #define CMD_PIPE_INDEX				2
+#define BAM_STATUS_PIPE_INDEX			3
 
 /* Define BAM pipe lock groups for NANDc*/
 #define P_LOCK_GROUP_0				0
@@ -238,11 +445,13 @@
 #define DATA_CONSUMER_PIPE			0
 #define DATA_PRODUCER_PIPE			1
 #define CMD_PIPE				2
+#define NAND_BAM_STATUS_PIPE			3
 
 /* NANDc BAM pipe groups */
 #define DATA_PRODUCER_PIPE_GRP			0
 #define DATA_CONSUMER_PIPE_GRP			0
 #define CMD_PIPE_GRP				1
+#define NAND_BAM_STATUS_PIPE_GRP		2
 
 /* NANDc EE */
 #define QPIC_NAND_EE				0
@@ -252,6 +461,7 @@
 
 /* Register: NAND_CTRL */
 #define BAM_MODE_EN				0x1
+#define NANDC_READ_DELAY_COUNTER_VAL		0x340
 
 /* Register: NAND_DEBUG */
 #define BAM_MODE_BIT_RESET			(1 << 31)
@@ -277,6 +487,7 @@
 
 #define QPIC_BAM_DATA_FIFO_SIZE			64
 #define QPIC_BAM_CMD_FIFO_SIZE			64
+#define QPIC_BAM_STATUS_FIFO_SIZE		64
 
 #define QPIC_MAX_ONFI_MODES				4
 #define QPIC_NUM_XFER_STEPS				7
@@ -284,7 +495,7 @@
 enum qpic_verion{
 	QCA_QPIC_V1_4_20,
 	QCA_QPIC_V1_5_20,
-
+	QCA_QPIC_V2_1_1,
 };
 
 
@@ -311,6 +522,28 @@
 	NAND_CFG,
 };
 
+/* Structure for Serial nand parameter */
+struct qpic_serial_nand_params {
+	u8 id[4];
+	u16 page_size;
+	u16 pgs_per_blk;
+	u32 spare_size;
+	u32 erase_blk_size;
+	u16 no_of_blocks;
+	u32 density;
+	u32 otp_region;
+	u8 no_of_addr_cycle;
+	u8 no_of_dies;
+	u8 num_bits_ecc_correctability;
+	u8 timing_mode_support;
+	bool quad_mode;
+	bool check_quad_config;
+	int prev_die_id;
+	u8 protec_bpx;
+	u64 pages_per_die;
+	const char *name;
+};
+
 struct onfi_param_page
 {
 	uint32_t signature;
@@ -396,9 +629,15 @@
 	unsigned read_pipe;
 	unsigned write_pipe;
 	unsigned cmd_pipe;
+#if defined(QPIC_SERIAL) && defined(MULTI_PAGE_READ)
+	unsigned status_pipe;
+#endif
 	uint8_t  read_pipe_grp;
 	uint8_t  write_pipe_grp;
 	uint8_t  cmd_pipe_grp;
+#if defined(QPIC_SERIAL) && defined(MULTI_PAGE_READ)
+	uint8_t status_pipe_grp;
+#endif
 };
 
 /* Structure to define the initial nand config */
@@ -442,6 +681,10 @@
 	uint32_t cfg0_raw;
 	uint32_t cfg1_raw;
 	uint32_t ecc_bch_cfg;
+#ifdef CONFIG_QPIC_SERIAL
+	bool quad_mode;
+	bool check_quad_config;
+#endif
 	unsigned oob_per_page;
 	unsigned char *buffers;
 	unsigned char *pad_dat;
diff --git a/board/qca/arm/common/crashdump.c b/board/qca/arm/common/crashdump.c
index ca7598f..22ede22 100644
--- a/board/qca/arm/common/crashdump.c
+++ b/board/qca/arm/common/crashdump.c
@@ -404,7 +404,7 @@
 
 static int do_dumpqca_data(unsigned int dump_level)
 {
-	uint32_t memaddr;
+	uint32_t memaddr, comp_addr = 0x0;
 	uint32_t remaining;
 	int indx;
 	int ebi_indx = 0;
@@ -412,8 +412,8 @@
 	char buf = 1;
 	struct dumpinfo_t *dumpinfo = dumpinfo_n;
 	int dump_entries = dump_entries_n;
-	char wlan_segment_name[32];
-	char *usb_dump = NULL;
+	char wlan_segment_name[32], runcmd[128], *s;
+	char *usb_dump = NULL, *compress = NULL;
 	ulong is_usb_dump = 0;
 
 	usb_dump = getenv("dump_to_usb");
@@ -507,7 +507,6 @@
 	for (indx = 0; indx < dump_entries; indx++) {
 		if (dump_level != dumpinfo[indx].dump_level)
 			continue;
-		printf("\nProcessing %s:", dumpinfo[indx].name);
 
 		if (dumpinfo[indx].is_redirected) {
 			memaddr = *((uint32_t *)(dumpinfo[indx].start));
@@ -525,17 +524,57 @@
 
 		if (!strncmp(dumpinfo[indx].name, "EBICS", strlen("EBICS")))
 		{
-			if (!strncmp(dumpinfo[indx].name,
-				     "EBICS0", strlen("EBICS0")))
-				dumpinfo[indx].size = gd->ram_size;
+			compress = getenv("dump_compressed");
+			if (compress) {
+				if (!strncmp(dumpinfo[indx].name, "EBICS2", strlen("EBICS2"))) {
+					memaddr = CONFIG_SYS_SDRAM_BASE + (gd->ram_size / 2);
+					dumpinfo[indx].size = gd->ram_size / 2;
+					comp_addr = memaddr;
+				}
+				if (!strncmp(dumpinfo[indx].name, "EBICS_S2", strlen("EBICS_S2"))) {
+					dumpinfo[indx].size = gd->ram_size - (dumpinfo[indx].start - CONFIG_SYS_SDRAM_BASE);
+					comp_addr = memaddr;
+				}
+				if (!strncmp(dumpinfo[indx].name, "EBICS1", strlen("EBICS1"))) {
+					dumpinfo[indx].size = (gd->ram_size / 2)
+								- (dumpinfo[indx + 1].size + 0x400000);
+				}
+			}
+			else {
+				if (!strncmp(dumpinfo[indx].name,
+					     "EBICS0", strlen("EBICS0")))
+					dumpinfo[indx].size = gd->ram_size;
 
-			if (!strncmp(dumpinfo[indx].name,
-				     "EBICS_S1", strlen("EBICS_S1")))
-				dumpinfo[indx].size = gd->ram_size
-						      - dumpinfo[indx - 1].size
-						      - CONFIG_TZ_SIZE;
+				if (!strncmp(dumpinfo[indx].name,
+					     "EBICS_S1", strlen("EBICS_S1")))
+					dumpinfo[indx].size = gd->ram_size
+							      - dumpinfo[indx - 1].size
+							      - CONFIG_TZ_SIZE;
+			}
 
-			if (is_usb_dump == 1) {
+			if (compress && (dumpinfo[indx].to_compress == 1)) {
+
+				snprintf(runcmd, sizeof(runcmd), "zip 0x%x 0x%x 0x%x", memaddr, dumpinfo[indx].size, comp_addr);
+				if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
+					printf("gzip compression of %s failed\n", dumpinfo[indx].name);
+				else {
+					s = getenv("filesize");
+					dumpinfo[indx].size = (int)simple_strtol(s, NULL, 16); //compressed_file_size
+					memaddr = comp_addr;
+					snprintf(dumpinfo[indx].name, sizeof(dumpinfo[indx].name), "%s.gz", dumpinfo[indx].name);
+				}
+			}
+
+#ifdef CONFIG_IPQ40XX
+			if (buf != 1)
+#endif
+				if ((compress && (dumpinfo[indx].to_compress != 1)) ||
+				    (!compress && (dumpinfo[indx].to_compress == 1))) {
+					continue;
+				}
+
+			printf("\nProcessing %s:\n", dumpinfo[indx].name);
+			if (is_usb_dump == 1 || compress) {
 				ret = dump_to_dst (dumpinfo[indx].is_aligned_access, memaddr, dumpinfo[indx].size, dumpinfo[indx].name);
 				if (ret == CMD_RET_FAILURE) {
 					goto stop_dump;
@@ -552,6 +591,7 @@
 					else {
 						dumpinfo[indx].size = remaining;
 					}
+
 					ret = dump_to_dst (dumpinfo[indx].is_aligned_access, memaddr, dumpinfo[indx].size, dumpinfo[indx].name);
 					if (ret == CMD_RET_FAILURE)
 						goto stop_dump;
@@ -564,6 +604,7 @@
 		}
 		else
 		{
+			printf("\nProcessing %s:\n", dumpinfo[indx].name);
 			if (dumpinfo[indx].dump_level == MINIMAL_DUMP )
 				memaddr = dump_minimal(dumpinfo, indx);
 			if (dumpinfo[indx].size && memaddr) {
diff --git a/board/qca/arm/ipq40xx/ipq40xx.c b/board/qca/arm/ipq40xx/ipq40xx.c
index a8cd2dd..5ac247d 100644
--- a/board/qca/arm/ipq40xx/ipq40xx.c
+++ b/board/qca/arm/ipq40xx/ipq40xx.c
@@ -77,6 +77,9 @@
 
 struct dumpinfo_t dumpinfo_n[] = {
 	{ "EBICS0.BIN", 0x80000000, 0x10000000, 0 },
+	{ "EBICS2.BIN", 0xA0000000, 0x10000000, 0, 0, 0, 0, 1 },
+	{ "EBICS1.BIN", CONFIG_UBOOT_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
+	{ "EBICS0.BIN", 0x80000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
 };
 
 int dump_entries_n = ARRAY_SIZE(dumpinfo_n);
diff --git a/board/qca/arm/ipq5018/ipq5018.c b/board/qca/arm/ipq5018/ipq5018.c
index 90d4ce3..307aab6 100644
--- a/board/qca/arm/ipq5018/ipq5018.c
+++ b/board/qca/arm/ipq5018/ipq5018.c
@@ -26,6 +26,7 @@
 #include <mmc.h>
 #include <sdhci.h>
 
+#define DLOAD_MAGIC_COOKIE	0x10
 DECLARE_GLOBAL_DATA_PTR;
 struct sdhci_host mmc_host;
 extern int ipq_spi_init(u16);
@@ -287,11 +288,51 @@
 
 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);
+}
+
+void qpic_clk_enbale(void)
+{
+	writel(QPIC_CBCR_VAL, GCC_QPIC_CBCR_ADDR);
+	writel(0x1, GCC_QPIC_AHB_CBCR_ADDR);
+	writel(0x1, GCC_QPIC_IO_MACRO_CBCR);
+}
+
 void board_nand_init(void)
 {
+	qpic_nand_init();
+
 #ifdef CONFIG_QCA_SPI
 	int gpio_node;
 	gpio_node = fdt_path_offset(gd->fdt_blob, "/spi/spi_gpio");
@@ -327,7 +368,3 @@
 	return 0;
 }
 
-void reset_cpu(unsigned long a)
-{
-	while(1);
-}
diff --git a/board/qca/arm/ipq5018/ipq5018.h b/board/qca/arm/ipq5018/ipq5018.h
index a220312..0bb6fa5 100644
--- a/board/qca/arm/ipq5018/ipq5018.h
+++ b/board/qca/arm/ipq5018/ipq5018.h
@@ -35,6 +35,15 @@
 #define GCC_SDCC1_AHB_CBCR		0x0184201C
 #define GCC_SDCC1_MISC			0x01842020
 
+/*
+ * 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
+
 /* UART 1 */
 #define GCC_BLSP1_UART1_BCR               0x01802038
 #define GCC_BLSP1_UART1_APPS_CBCR         0x0180203C
@@ -77,6 +86,15 @@
 #define KERNEL_AUTH_CMD                   0x13
 #define SCM_CMD_SEC_AUTH		       0x1F
 
+#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)
+
+unsigned int __invoke_psci_fn_smc(unsigned int, unsigned int,
+					 unsigned int, unsigned int);
 struct smem_ram_ptn {
 	char name[16];
 	unsigned long long start;
@@ -118,6 +136,7 @@
 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);
 
 typedef enum {
 	SMEM_SPINLOCK_ARRAY = 7,
diff --git a/board/qca/arm/ipq6018/ipq6018.c b/board/qca/arm/ipq6018/ipq6018.c
index 964dafa..559a9ba 100644
--- a/board/qca/arm/ipq6018/ipq6018.c
+++ b/board/qca/arm/ipq6018/ipq6018.c
@@ -57,7 +57,20 @@
 	 *                                |                      |
          *                                ------------------------
 	 */
+
+	/* Compressed EBICS dump follows descending order
+	 * to use in-memory compression for which destination
+	 * for compression will be address of EBICS2.BIN
+	 *
+	 * EBICS2 - (ddr size / 2) [to] end of ddr
+	 * EBICS1 - uboot end addr [to] (ddr size / 2)
+	 * EBICS0 - ddr start      [to] uboot start addr
+	 */
+
 	{ "EBICS0.BIN", 0x40000000, 0x10000000, 0 },
+	{ "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 },
 	{ "CODERAM.BIN", 0x00200000, 0x00028000, 0 },
 	{ "DATARAM.BIN", 0x00290000, 0x00014000, 0 },
 	{ "MSGRAM.BIN", 0x00060000, 0x00006000, 1 },
@@ -71,9 +84,18 @@
 };
 int dump_entries_n = ARRAY_SIZE(dumpinfo_n);
 
+/* Compressed dumps:
+ * EBICS_S2 - (ddr start + 256M) [to] end of ddr
+ * EBICS_S1 - uboot end addr     [to] (ddr start + 256M)
+ * EBICS_S0 - ddr start          [to] uboot start addr
+ */
+
 struct dumpinfo_t dumpinfo_s[] = {
 	{ "EBICS_S0.BIN", 0x40000000, 0xA600000, 0 },
 	{ "EBICS_S1.BIN", CONFIG_TZ_END_ADDR, 0x10000000, 0 },
+	{ "EBICS_S2.BIN", 0x50000000, 0x10000000, 0, 0, 0, 0, 1 },
+	{ "EBICS_S1.BIN", CONFIG_UBOOT_END_ADDR, 0x5B00000, 0, 0, 0, 0, 1 },
+	{ "EBICS_S0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
 	{ "DATARAM.BIN", 0x00290000, 0x00014000, 0 },
 	{ "MSGRAM.BIN", 0x00060000, 0x00006000, 1 },
 	{ "IMEM.BIN", 0x08600000, 0x00001000, 0 },
@@ -324,6 +346,7 @@
 }
 #endif
 
+#ifdef CONFIG_QCA_SPI
 static void spi_clock_init(void)
 {
 	int cfg;
@@ -340,6 +363,7 @@
 	/* Configure CBCR */
 	writel(CLK_ENABLE, GCC_BLSP1_QUP1_SPI_APPS_CBCR);
 }
+#endif
 
 void board_nand_init(void)
 {
diff --git a/board/qca/arm/ipq806x/ipq806x.c b/board/qca/arm/ipq806x/ipq806x.c
index fadf7af..bec1e1a 100644
--- a/board/qca/arm/ipq806x/ipq806x.c
+++ b/board/qca/arm/ipq806x/ipq806x.c
@@ -75,7 +75,10 @@
 	{ "WLAN_FW.BIN",  0x41400000, 0x000FFF80, 0 },
 	{ "WLAN_FW_900B.BIN", 0x44000000, 0x00600000, 0 },
 	{ "EBICS0.BIN",   0x40000000, 0x20000000, 0 },
-	{ "EBI1CS1.BIN",  0x60000000, 0x20000000, 0 }
+	{ "EBI1CS1.BIN",  0x60000000, 0x20000000, 0 },
+	{ "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 }
 };
 int dump_entries_n = ARRAY_SIZE(dumpinfo_n);
 
@@ -105,7 +108,10 @@
 	{ "WLAN_FW.BIN",  0x41400000, 0x000FFF80, 0 },
 	{ "WLAN_FW_900B.BIN", 0x44000000, 0x00600000, 0 },
 	{ "EBICS0.BIN",   0x40000000, 0x20000000, 0 },
-	{ "EBI1CS1.BIN",  0x60000000, 0x20000000, 0 }
+	{ "EBI1CS1.BIN",  0x60000000, 0x20000000, 0 },
+	{ "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 }
 };
 int dump_entries_s = ARRAY_SIZE(dumpinfo_s);
 
diff --git a/board/qca/arm/ipq807x/ipq807x.c b/board/qca/arm/ipq807x/ipq807x.c
index 4934641..03fa539 100644
--- a/board/qca/arm/ipq807x/ipq807x.c
+++ b/board/qca/arm/ipq807x/ipq807x.c
@@ -109,7 +109,15 @@
 	 *                                |  PMIC dump (8k)      |
 	 *                                ------------------------
 	 */
+
+	/* Compressed EBICS dump follows descending order
+	 * to use in-memory compression for which destination
+	 * for compression will be address of EBICS2.BIN
+	 */
 	{ "EBICS0.BIN", 0x40000000, 0x10000000, 0 },
+	{ "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 },
 	{ "CODERAM.BIN", 0x00200000, 0x00028000, 0 },
 	{ "DATARAM.BIN", 0x00290000, 0x00014000, 0 },
 	{ "MSGRAM.BIN", 0x00060000, 0x00006000, 1 },
@@ -126,6 +134,9 @@
 struct dumpinfo_t dumpinfo_s[] = {
 	{ "EBICS_S0.BIN", 0x40000000, 0xAC00000, 0 },
 	{ "EBICS_S1.BIN", CONFIG_TZ_END_ADDR, 0x10000000, 0 },
+	{ "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 },
 	{ "DATARAM.BIN", 0x00290000, 0x00014000, 0 },
 	{ "MSGRAM.BIN", 0x00060000, 0x00006000, 1 },
 	{ "IMEM.BIN", 0x08600000, 0x00001000, 0 },
diff --git a/drivers/mtd/nand/qpic_nand.c b/drivers/mtd/nand/qpic_nand.c
index 7ba7a42..f1104db 100644
--- a/drivers/mtd/nand/qpic_nand.c
+++ b/drivers/mtd/nand/qpic_nand.c
@@ -48,6 +48,78 @@
 
 static uint32_t hw_ver;
 
+#ifdef CONFIG_QPIC_SERIAL
+static struct qpic_serial_nand_params qpic_serial_nand_tbl[] = {
+	{
+		.id = { 0xc8, 0xc1 },
+		.page_size = 2048,
+		.erase_blk_size = 0x00020000,
+		.pgs_per_blk = 64,
+		.no_of_blocks = 1024,
+		.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 = "GD5F1GQ4RE9IG",
+	},
+	{
+		.id = { 0xc8, 0xc9 },
+		.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 = "GD5F1GQ4RE9IH",
+	},
+	{
+		.id = { 0xc8, 0x22 },
+		.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 = "GD5F2GQ5REYIH",
+	},
+	{
+		.id = { 0x2c, 0x15 },
+		.page_size = 2048,
+		.erase_blk_size = 0x00020000,
+		.pgs_per_blk = 64,
+		.no_of_blocks = 1024,
+		.spare_size = 128,
+		.density = 0x08000000,
+		.otp_region = 0x5000,
+		.no_of_addr_cycle = 0x3,
+		.num_bits_ecc_correctability = 8,
+		.timing_mode_support = 0,
+		.quad_mode = true,
+		.check_quad_config = false,
+		.name = "MT29F1G01ABBFDWB-IT",
+	},
+};
+struct qpic_serial_nand_params *serial_params;
+#define MICRON_DEVICE_ID	0x152c152c
+#define CMD3_MASK		0xfff0ffff
+#endif
+
 struct cmd_element ce_array[100]
 			__attribute__ ((aligned(CONFIG_SYS_CACHELINE_SIZE)));
 struct cmd_element ce_read_array[20]
@@ -57,6 +129,8 @@
 			__attribute__ ((aligned(CONFIG_SYS_CACHELINE_SIZE)));
 struct bam_desc qpic_data_desc_fifo[QPIC_BAM_DATA_FIFO_SIZE]
 			__attribute__ ((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+struct bam_desc qpic_status_desc_fifo[QPIC_BAM_STATUS_FIFO_SIZE]
+			__attribute__ ((aligned(CONFIG_SYS_CACHELINE_SIZE)));
 static struct bam_instance bam;
 struct nand_ecclayout fake_ecc_layout;
 
@@ -77,16 +151,24 @@
 static const struct udevice_id qpic_ver_ids[] = {
 	{ .compatible = "qcom,qpic-nand.1.4.20", .data = QCA_QPIC_V1_4_20 },
 	{ .compatible = "qcom,qpic-nand.1.5.20", .data = QCA_QPIC_V1_5_20 },
+	{ .compatible = "qcom,qpic-nand-v2.1.1", .data = QCA_QPIC_V2_1_1},
 	{ },
 };
 
 static uint32_t
 qpic_onfi_mode_to_xfer_steps[QPIC_MAX_ONFI_MODES][QPIC_NUM_XFER_STEPS] = {
+#ifdef CONFIG_QPIC_SERIAL
 	/* Mode 0 */
 	{
+		0x00e00080, 0x49f04998, 0x8de08d80, 0xc000c000,
+		0xc000c000, 0xc000c000, 0xc000c000,
+	},
+#else
+	{
 		0x04e00480, 0x59f05998, 0x89e08980, 0xd000d000,
 		0xc000c000, 0xc000c000, 0xc000c000,
 	},
+#endif
 	/* Mode 1 */
 	{
 		0x00e00080, 0x49f04d99, 0x85e08580, 0xd000d000,
@@ -254,17 +336,20 @@
 	uint32_t flash_cmd = NAND_CMD_FETCH_ID;
 	uint32_t exec_cmd = 1;
 	int nand_ret = NANDC_RESULT_SUCCESS;
-	uint32_t vld;
+	uint32_t vld = NAND_CMD_VALID_BASE;
 	uint32_t cmd_vld = NAND_DEV_CMD_VLD_V1_4_20;
 
+#ifdef CONFIG_QPIC_SERIAL
+	flash_cmd |= QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET |
+		QPIC_SPI_TRANSFER_MODE_X1;
+	vld = FLASH_DEV_CMD_VLD;
+#endif
 	/* Issue the Fetch id command to the NANDc */
 	bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd,
-			    CE_WRITE_TYPE);
+				CE_WRITE_TYPE);
 	cmd_list_ptr++;
 
-	vld = NAND_CMD_VALID_BASE;
-
-	if (hw_ver == QCA_QPIC_V1_5_20)
+	if (hw_ver == QCA_QPIC_V1_5_20 || hw_ver == QCA_QPIC_V2_1_1)
 		cmd_vld = NAND_DEV_CMD_VLD_V1_5_20;
 
 	bam_add_cmd_element(cmd_list_ptr, cmd_vld, (uint32_t)vld,
@@ -288,9 +373,6 @@
 	num_desc++;
 	qpic_nand_wait_for_cmd_exec(num_desc);
 
-	cmd_list_ptr_start = ce_array;
-	cmd_list_ptr = ce_array;
-
 	/* Read the status register */
 	status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
 
@@ -349,7 +431,15 @@
 	bam.pipe[CMD_PIPE_INDEX].fifo.size = QPIC_BAM_CMD_FIFO_SIZE;
 	bam.pipe[CMD_PIPE_INDEX].fifo.head = qpic_cmd_desc_fifo;
 	bam.pipe[CMD_PIPE_INDEX].lock_grp = config->pipes.cmd_pipe_grp;
-
+#if defined(CONFIG_QPIC_SERIAL) && defined(MULTI_PAGE_READ)
+	/* Set Status pipe params. */
+	bam.pipe[BAM_STATUS_PIPE_INDEX].pipe_num = config->pipes.status_pipe;
+	/* System consumer */
+	bam.pipe[BAM_STATUS_PIPE_INDEX].trans_type = BAM2SYS;
+	bam.pipe[BAM_STATUS_PIPE_INDEX].fifo.size = QPIC_BAM_STATUS_FIFO_SIZE;
+	bam.pipe[BAM_STATUS_PIPE_INDEX].fifo.head = qpic_status_desc_fifo;
+	bam.pipe[BAM_STATUS_PIPE_INDEX].lock_grp = config->pipes.status_pipe_grp;
+#endif
 	/* Programs the threshold for BAM transfer
 	 * When this threshold is reached, BAM signals the peripheral via the
 	 * pipe_bytes_available interface.
@@ -408,15 +498,32 @@
 		bam_ret = NANDC_RESULT_FAILURE;
 		goto qpic_nand_bam_init_error;
 	}
+#if defined(CONFIG_QPIC_SERIAL) && defined(MULTI_PAGE_READ)
+	/* Initialize BAM QPIC status pipe */
+	bam_sys_pipe_init(&bam, BAM_STATUS_PIPE_INDEX);
 
+	/* Init status fifo */
+	bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[BAM_STATUS_PIPE_INDEX].pipe_num);
+
+	if (bam_ret) {
+		printf("QPIC:NANDc BAM STATUS FIFO init error\n");
+		bam_ret = NANDC_RESULT_FAILURE;
+		goto qpic_nand_bam_init_error;
+	}
+#endif
 	/*
 	 * Once BAM_MODE_EN bit is set then QPIC_NAND_CTRL register
 	 * should be written with BAM instead of writel.
 	 * Check if BAM_MODE_EN is already set by bootloader and write only
 	 * if this bit is not set.
 	 */
-	if (!(readl(QPIC_NAND_CTRL) & BAM_MODE_EN))
-		writel(BAM_MODE_EN, QPIC_NAND_CTRL);
+	if (!(readl(QPIC_NAND_CTRL) & BAM_MODE_EN)) {
+#ifdef CONFIG_QPIC_SERIAL
+		writel(BAM_MODE_EN | NANDC_READ_DELAY_COUNTER_VAL, QPIC_NAND_CTRL);
+#else
+		writel(BAM_MODE_EN , QPIC_NAND_CTRL);
+#endif
+	}
 
 qpic_nand_bam_init_error:
 return bam_ret;
@@ -580,6 +687,7 @@
 	qpic_nand_wait_for_cmd_exec(1);
 }
 
+#ifndef CONFIG_QPIC_SERIAL
 static void
 qpic_config_timing_parameters(struct mtd_info *mtd)
 {
@@ -605,6 +713,40 @@
 		writel(qpic_onfi_mode_to_xfer_steps[timing_mode][i],
 		       xfer_start + 4 * i);
 }
+#endif
+
+#ifdef CONFIG_QPIC_SERIAL
+static void qpic_serial_update_dev_params(struct mtd_info *mtd)
+{
+	struct qpic_nand_dev *dev = MTD_QPIC_NAND_DEV(mtd);
+	uint32_t ecc_bits;
+
+	dev->page_size = serial_params->page_size;
+	mtd->writesize = dev->page_size;
+	dev->block_size = serial_params->pgs_per_blk * (dev->page_size);
+	mtd->erasesize = dev->block_size;
+	dev->num_blocks = serial_params->no_of_blocks;
+	dev->widebus = 0x0;
+	dev->density = serial_params->no_of_blocks * (dev->block_size);
+	mtd->size = dev->density;
+	dev->spare_size = serial_params->spare_size;
+	mtd->oobsize = dev->spare_size;
+	ecc_bits = serial_params->num_bits_ecc_correctability;
+	dev->num_pages_per_blk = serial_params->pgs_per_blk;
+	dev->num_pages_per_blk_mask = serial_params->pgs_per_blk - 1;
+	dev->timing_mode_support = serial_params->timing_mode_support;
+	dev->quad_mode = serial_params->quad_mode;
+	dev->check_quad_config = serial_params->check_quad_config;
+
+	if (ecc_bits >= 8)
+		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);
+}
+#endif
 
 static int
 qpic_nand_onfi_save_params(struct mtd_info *mtd,
@@ -651,6 +793,10 @@
 	struct qpic_nand_dev *dev = MTD_QPIC_NAND_DEV(mtd);
 	struct nand_chip *chip = MTD_NAND_CHIP(mtd);
 	uint32_t qpic_oob_size;
+	uint32_t no_of_address_cycle = 5;
+	uint32_t disable_status_after_write = 0;
+	uint32_t recovery_cycle = 7;
+	uint32_t wr_rd_busy_gap = 2;
 
 	/* Save Configurations */
 	dev->cws_per_page = dev->page_size >> NAND_CW_DIV_RIGHT_SHIFT;
@@ -719,37 +865,41 @@
 	 */
 	dev->bad_blk_loc = dev->page_size - dev->cw_size *
 				 (dev->cws_per_page - 1) + 1;
-
+#ifdef CONFIG_QPIC_SERIAL
+	no_of_address_cycle = 3;
+	disable_status_after_write = 1;
+	recovery_cycle = 0;
+	wr_rd_busy_gap = 20;
+#endif
 	dev->cfg0 |= ((dev->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT) /* 4/8 cw/pg for 2/4k */
 				|(DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) /* 516 user data bytes */
-				|(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
-				|(0 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
+				|(no_of_address_cycle << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
+				|(disable_status_after_write << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
 
-	dev->cfg1 |= (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
+	dev->cfg1 |= (recovery_cycle << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
 				|(0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT)		/* Allow CS deassertion */
 				|(dev->bad_blk_loc << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)/* Bad block marker location */
 				|(0 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT)		/* Bad block in user data area */
-				|(2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)		/* 8 cycle tWB/tRB */
+				|(wr_rd_busy_gap << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)		/* 8 cycle tWB/tRB */
 				|(dev->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT);	/* preserve wide flash flag */
 
 	dev->cfg0_raw = ((dev->cws_per_page- 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT)
-					|(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
+					|(no_of_address_cycle << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
 					|(dev->cw_size << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) //figure out the size of cw
-					| (1 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);
+					| (disable_status_after_write << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);
 
-	dev->cfg1_raw = (7 <<  NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
+	dev->cfg1_raw = (recovery_cycle <<  NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
 					| (0 <<  NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT)
 					| (17 <<  NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)
 					| (1 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT)
-					| (2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
+					| (wr_rd_busy_gap << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
 					| (dev->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT)
 					| 1 ; /* to disable reed solomon ecc..this feild is now read only. */
 
 	dev->ecc_bch_cfg |= (0 << NAND_DEV0_ECC_DISABLE_SHIFT) /* Enable ECC */
-						| (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
-						| (DATA_BYTES_IN_IMG_PER_CW <<
-						   NAND_DEV0_ECC_NUM_DATA_BYTES)
-						| (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
+					| (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
+					| (DATA_BYTES_IN_IMG_PER_CW <<  NAND_DEV0_ECC_NUM_DATA_BYTES)
+					| (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
 
 	/*
 	 * Safe to use a single instance global variable,
@@ -764,6 +914,331 @@
 	return 0;
 }
 
+#ifdef CONFIG_QPIC_SERIAL
+static int qpic_serial_get_feature(struct mtd_info *mtd, uint32_t ftr_addr)
+{
+	struct cmd_element *cmd_list_ptr = ce_array;
+	struct cmd_element *cmd_list_ptr_start = ce_array;
+	uint8_t num_desc = 0;
+	uint32_t status, nand_ret;
+	uint32_t exec_cmd = 1;
+
+	uint32_t cmd_val = (QPIC_SPI_TRANSFER_MODE_X1 | QPIC_SPI_HOLD_SET |
+			QPIC_SPI_WP_SET | NAND_CMD_ACC_FEATURE);
+
+	/* Set the feature address to NAND_ADDR0 register */
+	bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, ftr_addr,
+			CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	/* Set the value 0x0 to NAND_ADDR1 register */
+	bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, 0,
+			CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	/* First Clear the feature register to get the fresh feature value */
+	bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_FEATURES, 0,
+			    CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	/* cmd_val = 0x3800000E
+	 * bit-31 is clear means set feature
+	 * bit-30-29 means x1 mode
+	 * bit-28 is set , this is for wp pin
+	 * wp# pin should be set to high then only we can get the feature
+	 * bit-27 SPI_HOLD : this pin also should be high
+	 */
+	bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, cmd_val,
+			CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	/* Execute the cmd */
+	bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, exec_cmd,
+			    CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	/* Prepare the cmd desc for the above commands */
+	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_NWD_FLAG | BAM_DESC_CMD_FLAG |
+			BAM_DESC_INT_FLAG);
+
+	/* Keep track of the number of desc added. */
+	num_desc++;
+
+	qpic_nand_wait_for_cmd_exec(num_desc);
+
+	status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
+
+	/* Check for errors */
+	nand_ret = qpic_nand_check_status(mtd, status);
+	if (nand_ret) {
+		printf("%s : CMD status failed\n", __func__);
+		goto err;
+	}
+	/* read the feature register value and update in feature
+	 * 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",
+			ftr_addr,nand_ret);
+#endif
+err:
+	return nand_ret;
+
+}
+
+static int qpic_serial_set_feature(struct mtd_info *mtd, uint32_t ftr_addr,
+	       uint32_t ftr_val)
+{
+	struct cmd_element *cmd_list_ptr = ce_array;
+	struct cmd_element *cmd_list_ptr_start = ce_array;
+	uint8_t num_desc = 0;
+	uint32_t status, nand_ret;
+
+	uint32_t cmd_val = (QPIC_SPI_SET_FEATURE | QPIC_SPI_WP_SET |
+			QPIC_SPI_HOLD_SET | QPIC_SPI_TRANSFER_MODE_X1 |
+			NAND_CMD_ACC_FEATURE);
+
+	uint32_t exec_cmd = 1;
+
+	/* set the feature value to NAND_FLASH_FEATURES feature register */
+	bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_FEATURES, ftr_val,
+			    CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	/* Set the feature address to NAND_ADDR0 register */
+	bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, ftr_addr,
+			CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	/* Set the value 0x0 to NAND_ADDR1 register */
+	bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, 0,
+			CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	/* cmd_val = 0xB800000E
+	 * bit-31 is set means set feature
+	 * bit-30-29 means x1 mode
+	 * bit-28 is set , this is for wp pin
+	 * wp# pin should be set to high then only we can set the feature
+	 * bit-27 SPI_HOLD : this pin also should be high
+	 */
+	bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, cmd_val,
+			CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	/* Execute the cmd */
+	bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, exec_cmd,
+			    CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	/* Prepare the cmd desc for the above commands */
+	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_NWD_FLAG | BAM_DESC_CMD_FLAG |
+			BAM_DESC_INT_FLAG);
+
+	/* Keep track of the number of desc added. */
+	num_desc++;
+
+	qpic_nand_wait_for_cmd_exec(num_desc);
+
+	status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
+
+	/* Check for errors */
+	nand_ret = qpic_nand_check_status(mtd, status);
+	if (nand_ret) {
+		printf("%s : CMD status failed\n", __func__);
+		goto err;
+	}
+err:
+	return nand_ret;
+}
+
+static int qpic_nand_read_id_serial(struct mtd_info *mtd)
+{
+	uint32_t nand_ret;
+	uint32_t serial_dev_id[2] = {0x0};
+	int i;
+	struct qpic_nand_dev *dev = MTD_QPIC_NAND_DEV(mtd);
+
+	nand_ret = qpic_nand_fetch_id(mtd);
+	if (!nand_ret) {
+
+		serial_dev_id[0] = dev->id & 0x000000ff;
+		serial_dev_id[1] = (dev->id >> 8) & 0x000000ff;
+
+		for (i = 0; i < ARRAY_SIZE(qpic_serial_nand_tbl); i++) {
+			serial_params = &qpic_serial_nand_tbl[i];
+			if ((serial_params->id[0] == serial_dev_id[0]) &&
+			   (serial_params->id[1] == serial_dev_id[1])) {
+				printf("Serial Nand Device Found With ID : 0x%02x 0x%02x\n",
+						serial_dev_id[0],serial_dev_id[1]);
+
+				/* Upadate device paramter as per device table */
+				qpic_serial_update_dev_params(mtd);
+
+				return nand_ret;
+			}
+		}
+		if (i == ARRAY_SIZE(qpic_serial_nand_tbl)) {
+			printf("%s : No serial Nand device found in table.\n",
+					__func__);
+			return -QPIC_SERIAL_ERROR;
+		}
+	} else {
+		printf("%s : Error in featching id from device\n",__func__);
+		goto id_err;
+	}
+id_err:
+	return nand_ret;
+}
+
+int qpic_spi_nand_config(struct mtd_info *mtd)
+{
+	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
+	 * CMD3.
+	 */
+	if (dev->id == MICRON_DEVICE_ID) {
+		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) {
+		printf("%s : Error in getting feature.\n",__func__);
+		return status;
+	}
+
+	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__);
+
+		status  = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_BLK_PROCT_ADDR,
+				FLASH_SPI_NAND_BLK_PROCT_DISABLE);
+		if (status < 0) {
+			printf("%s : Error in disabling block protection.\n",__func__);
+			return status;
+		}
+		/* After disabling the block protection again read the status
+		 * i.e again call the get feature command to get the status
+		 */
+		status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_BLK_PROCT_ADDR);
+		if (status < 0) {
+			printf("%s : Error in getting feature.\n",__func__);
+			return status;
+		}
+		if ((status >> 8) & FLASH_SPI_NAND_BLK_PROCT_ENABLE) {
+			printf("%s : block protection still enabled.We can't erase a block\n",
+					__func__);
+			return -QPIC_SERIAL_ERROR;
+		} else
+			printf("%s : Block protection Disabled.\n",__func__);
+	} else
+		printf("%s: Block protection Disabled on Power on.\n",__func__);
+
+	/* Get Internal ECC status */
+	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_ECC_ENABLE) {
+		printf("%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,
+			status);
+
+		if (status < 0) {
+			printf("%s : Error in disabling internal ECC.\n",__func__);
+			return status;
+		}
+		/* again check internal ECC is disabled or not using get feature
+		 * command
+		 */
+		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_ECC_ENABLE) {
+			pr_info("%s: Failed to disabled device internal ECC\n",
+					__func__);
+			return -QPIC_SERIAL_ERROR;
+		} else
+			printf("%s : Internal ECC disabled.\n",__func__);
+	} else
+		printf("%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
+	 * else no need to check for Quad mode.
+	 * For Micron device there is no quad config bit so no need to check
+	 * quad config bit.
+	 */
+	/* Get QUAD bit status */
+	if (!dev->check_quad_config) {
+		dev->quad_mode = true;
+		return 0;
+	}
+
+	if (dev->quad_mode) {
+
+		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_QUAD_ENABLE)) {
+			printf("%s : Quad bit not enabled.\n",__func__);
+			printf("%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;
+			}
+			/* 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) {
+				printf("%s : Error in getting feature.\n",__func__);
+				return status;
+			}
+
+			if (!((status >> 8) & FLASH_SPI_NAND_FR_QUAD_ENABLE)) {
+				printf("%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;
+			}
+		} else {
+			printf("%s: Quad mode enabled on Opwer on.\n",__func__);
+			return 0;
+		}
+	}
+	return 0;
+}
+#endif
+
 /* Onfi probe should issue the following commands to the flash device:
  * 1. Read ID - with addr ONFI_READ_ID_ADDR.
  *              This returns the ONFI ASCII string indicating support for ONFI.
@@ -786,6 +1261,12 @@
 	struct onfi_param_page *param_page;
 	int onfi_ret = NANDC_RESULT_SUCCESS;
 
+#ifdef CONFIG_QPIC_SERIAL
+	uint32_t nand_ret;
+	nand_ret = qpic_nand_read_id_serial(mtd);
+	return nand_ret;
+#endif
+
 	/* Allocate memory required to read the onfi param page */
 	buffer = (unsigned char*) malloc(ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
 	if (buffer == NULL) {
@@ -891,8 +1372,77 @@
 	return onfi_ret;
 }
 
-static int
-qpic_nand_reset(struct mtd_info *mtd)
+#ifdef CONFIG_QPIC_SERIAL
+static void qpic_spi_init(struct mtd_info *mtd)
+{
+	uint32_t xfer_start = NAND_XFR_STEPS_V1_5_20;
+	int i;
+
+	/* Enabel QSPI CLK*/
+	qpic_clk_enbale();
+
+	/* 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);
+
+	/* 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
+	 */
+	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);
+
+	/* According to HPG Setting Xfer steps and spi_num_addr_cycles
+	 * is part of initialization flow before reset.However these
+	 * values differ from NAND part to part.sitting in QPIC layer
+	 * we won't know which NAND we don't know which NAND is connected.
+	 * So we are not following HPG init sequence.Instead we reset and
+	 * read id of NAND,then based on NAND ID we get Xfer steps
+	 * and spi_num_addr_cycles and configure them in this function.Since
+	 * Xfer steps and spi_num_addr_cycles are required for read/write/erase
+	 * functionality.
+	 *
+	 * NOTE: For now address cycle is same for Giga devices & Micron devices
+	 * so we can configure no of addess cycle here only
+	 * The NAND_FLASH_XFR_STEP register also fixed for both the devices so we
+	 * can configure this register here only . later change this logic as per
+	 * device
+	 *
+	 * NOTE: The XFER register value is now fixed as HPG.
+	 *
+	 */
+	for (i = 0; i < QPIC_NUM_XFER_STEPS; i++)
+		writel(qpic_onfi_mode_to_xfer_steps[0][i],
+		       xfer_start + 4 * i);
+
+	writel(NAND_FLASH_DEV_CMD0_VAL, SPI_NAND_DEV_CMD0);
+	writel(NAND_FLASH_DEV_CMD1_VAL, SPI_NAND_DEV_CMD1);
+	writel(NAND_FLASH_DEV_CMD2_VAL, SPI_NAND_DEV_CMD2);
+	writel(NAND_FLASH_DEV_CMD3_VAL, SPI_NAND_DEV_CMD3);
+	writel(NAND_FLASH_DEV_CMD7_VAL, SPI_NAND_DEV_CMD7);
+
+	/* NAND_DEV_CMD8 & NAND_DEV_CMD9 default value will be used for
+	 * QSPI
+	 */
+	writel(FLASH_DEV_CMD_VLD, NAND_FLASH_DEV_CMD_VLD);
+
+	/* 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);
+
+	writel(SPI_BUSY_CHECK_WAIT_CNT, NAND_SPI_BUSY_CHECK_WAIT_CNT);
+}
+#endif
+static int qpic_nand_reset(struct mtd_info *mtd)
 {
 	struct cmd_element *cmd_list_ptr = ce_array;
 	struct cmd_element *cmd_list_ptr_start = ce_array;
@@ -901,6 +1451,33 @@
 	uint32_t exec_cmd = 1;
 	uint32_t flash_cmd = NAND_CMD_RESET_DEVICE;
 
+#ifdef CONFIG_QPIC_SERIAL
+	flash_cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET | QPIC_SPI_TRANSFER_MODE_X1);
+	uint32_t cfg0 = SPI_NAND_DEVn_CFG0 & 0xff00f0;
+	uint32_t cfg1 = SPI_NAND_DEVn_CFG1_RESET;
+	uint32_t ecc_cfg = ((SPI_NAND_DEVn_ECC_CFG & 0x0f000002) | (1 << 0))
+				& ~(1 << 1);
+	/* As per HPG the reset sequence as follow
+	 * NAND_DEV0_CFG0	0x005400D0 or 0x00540010
+	 * NAND_DEVn_CFG1	0x087476B1
+	 * NAND_DEV0_ECC_CFG	0x02000001
+	 * NAND_FLASH_CMD 	0x3800000D
+	 * NAND_EXEC_CMD	0x00000001
+	 */
+	/* write the reset sequence as per HPG */
+	bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG0, (uint32_t)cfg0,
+			    CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG1, (uint32_t)cfg1,
+			    CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+	bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG, (uint32_t)ecc_cfg,
+			    CE_WRITE_TYPE);
+	cmd_list_ptr++;
+
+#endif
 	/* Issue the Reset device command to the NANDc */
 	bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd,
 			    CE_WRITE_TYPE);
@@ -1002,9 +1579,13 @@
 	bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
 			   (uint32_t)cfg->ecc_cfg, CE_WRITE_TYPE);
 	cmd_list_ptr++;
-
+#ifdef CONFIG_QPIC_SERIAL
+	bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_LAST_CW_n(0),
+			   (uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
+#else
 	bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0),
 			   (uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
+#endif
 	cmd_list_ptr++;
 
 	cmd_list_ptr = qpic_nand_add_cmd_ce(cfg, cmd_list_ptr);
@@ -1092,8 +1673,18 @@
 	/* Read the first page in the block. */
 	cwperpage = (dev->cws_per_page);
 
-	/* Read page cmd */
 	params.cmd = NAND_CMD_PAGE_READ_ECC;
+
+	/* Read page cmd */
+#ifdef CONFIG_QPIC_SERIAL
+	params.cmd = NAND_CMD_PAGE_READ;
+	if (dev->quad_mode)
+		params.cmd |= QPIC_SPI_TRANSFER_MODE_X4;
+	else
+		params.cmd |= QPIC_SPI_TRANSFER_MODE_X1;
+
+	params.cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET);
+#endif
 	/* Clear the CW per page bits */
 	params.cfg0 = dev->cfg0_raw & ~(7U <<
 			 NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
@@ -1148,16 +1739,38 @@
 	int num_desc = 0;
 	int int_flag = 0;
 	unsigned int i;
-
-	if (cfg_mode == NAND_CFG)
-		ecc = dev->ecc_bch_cfg;
+#ifdef CONFIG_QPIC_SERIAL
+	/* For Serial NAND devices the page program sequence as
+	 * 02H (PROGRAM LOAD)/32H (PROGRAM LOAD x4)
+	 * 06H (WRITE ENABLE)
+	 * 10H (PROGRAM EXECUTE)
+	 * 0FH (GET FEATURE command to read the status)
+	 * No need to 0x02 & 0x32 command manually, controller
+	 * automatically send this command to device. we have already mapped
+	 * these command in  QPIC_FLASH_DEV_CMD9 register, similar for command
+	 * 0x06 & 0x0F, controller will take care internally
+	 *
+	 * NOTE: While initializing we have already enabeld quad bit i.e QE-bit
+	 * and disable write protection so no need to check here.
+	 */
+	if (dev->quad_mode)
+		cfg->cmd |= QPIC_SPI_TRANSFER_MODE_X4;
 	else
-		ecc = 0x1; /* Disable ECC */
+		cfg->cmd |= QPIC_SPI_TRANSFER_MODE_X1;
 
+	cfg->cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET);
+#endif
+
+	if (cfg_mode == NAND_CFG) {
+		ecc = dev->ecc_bch_cfg;
+	} else {
+		ecc = 0x1; /* Disable ECC */
+	}
 	/* Add ECC configuration */
 	bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
 						(uint32_t)ecc, CE_WRITE_TYPE);
 	cmd_list_ptr++;
+
 	cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, cmd_list_ptr);
 
 	bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD,
@@ -1775,13 +2388,26 @@
 	unsigned char *buffer_st, *spareaddr_st;
 	unsigned int max_bitflips = 0, uncorrectable_err_cws = 0;
 
+	/* Check This address for serial NAND later on if any issue
+	 * Because as per HPG Page Read	0x13 NAND_ADDR1[7:0]
+	 * NAND_ADDR0[31:24] NAND_ADDR0[23:16]
+	 */
 	params.addr0 = page << 16;
 	params.addr1 = (page >> 16) & 0xff;
+
 	if (cfg_mode == NAND_CFG_RAW) {
 		params.cfg0 = dev->cfg0_raw;
 		params.cfg1 = dev->cfg1_raw;
 		params.cmd = NAND_CMD_PAGE_READ;
 		ecc = 0x1; /* Disable ECC */
+#ifdef CONFIG_QPIC_SERIAL
+		if (dev->quad_mode)
+			params.cmd |= QPIC_SPI_TRANSFER_MODE_X4;
+		else
+			params.cmd |= QPIC_SPI_TRANSFER_MODE_X1;
+
+		params.cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET);
+#endif
 		data_bytes =  dev->cw_size;
 		oob_bytes = mtd->oobsize;
 		ud_bytes_in_last_cw = (dev->cw_size - mtd->oobsize);
@@ -1789,14 +2415,22 @@
 		params.cfg0 = dev->cfg0;
 		params.cfg1 = dev->cfg1;
 		params.cmd = NAND_CMD_PAGE_READ_ALL;
+#ifdef CONFIG_QPIC_SERIAL
+		if (dev->quad_mode)
+			params.cmd |= QPIC_SPI_TRANSFER_MODE_X4;
+		else
+			params.cmd |= QPIC_SPI_TRANSFER_MODE_X1;
+
+		params.cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET);
+#endif
 		ecc = (dev->ecc_bch_cfg);
 		data_bytes = DATA_BYTES_IN_IMG_PER_CW;
 		ud_bytes_in_last_cw = USER_DATA_BYTES_PER_CW -
 					 (((dev->cws_per_page) - 1) << 2);
 		oob_bytes = DATA_BYTES_IN_IMG_PER_CW - ud_bytes_in_last_cw;
 	}
-	params.exec = 1;
 
+	params.exec = 1;
 	/* Read all the Data bytes in the first 3 CWs. */
 	addr_loc_0 = NAND_RD_LOC_OFFSET(0);
 	addr_loc_0 |= NAND_RD_LOC_SIZE(data_bytes);;
@@ -1844,12 +2478,19 @@
 		cmd_list_ptr++;
 
 		if (i == (dev->cws_per_page) - 1) {
+			/* Write addr loc 1 only for the last CW. */
 			addr_loc_0 = NAND_RD_LOC_OFFSET(0);
 			addr_loc_0 |= NAND_RD_LOC_SIZE(ud_bytes_in_last_cw);
 			addr_loc_0 |= NAND_RD_LOC_LAST_BIT(0);
-					  /* Write addr loc 1 only for the last CW. */
+#ifdef CONFIG_QPIC_SERIAL
+			 /*To read only spare bytes 80 0r 16*/
+			bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_LAST_CW_n(1),
+					   (uint32_t)addr_loc_1, CE_WRITE_TYPE);
+#else
 			bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(1),
 					   (uint32_t)addr_loc_1, CE_WRITE_TYPE);
+#endif
+
 			cmd_list_ptr++;
 			flags = 0;
 			/* Add Data desc */
@@ -1877,12 +2518,23 @@
 			bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX,
 					  num_data_desc);
 		}
-		/* Write addr loc 0. */
-		bam_add_cmd_element(cmd_list_ptr,
+#ifdef CONFIG_QPIC_SERIAL
+		if (i == (dev->cws_per_page) - 1)
+			bam_add_cmd_element(cmd_list_ptr,
+					NAND_READ_LOCATION_LAST_CW_n(0),
+					(uint32_t)addr_loc_0,
+					CE_WRITE_TYPE);
+		else
+			bam_add_cmd_element(cmd_list_ptr,
 				    NAND_READ_LOCATION_n(0),
 				    (uint32_t)addr_loc_0,
 				    CE_WRITE_TYPE);
-
+#else
+		bam_add_cmd_element(cmd_list_ptr,
+				NAND_READ_LOCATION_n(0),
+				(uint32_t)addr_loc_0,
+				CE_WRITE_TYPE);
+#endif
 		cmd_list_ptr++;
 
 		bam_add_cmd_element(cmd_list_ptr,
@@ -2064,6 +2716,7 @@
 
 		ret = qpic_nand_read_page(mtd, start_page + i, cfg_mode,
 					  &page_ops);
+
 		if (ret < 0) {
 			printf("%s: reading page %d failed with %d err\n",
 			       __func__, start_page + i, ret);
@@ -2314,7 +2967,28 @@
 	/* Clear CW_PER_PAGE in cfg0 */
 	cfg.cfg0 = dev->cfg0 & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
 	cfg.cfg1 = dev->cfg1;
+
 	cfg.cmd = NAND_CMD_BLOCK_ERASE;
+#ifdef CONFIG_QPIC_SERIAL
+	/* For serial NAND devices the block erase sequence is
+	 * Issue 06H (WRITE ENBALE command)
+	 * Issue D8H (BLOCK ERASE command)
+	 * Issue 0FH (GET FEATURES command to read the status register)
+	 * But we have already mapped write enable command in register
+	 * QPIC_FLASH_DEV_CMD7 so here no need to send this command manually
+	 * once we will send block erase command then controller internally
+	 * send write enable command
+	 * similar for Get feature command, no neeed to send this command
+	 * also manually controller will take care.
+	 *
+	 * NOTE: Initially we are disabling block protection, so no need
+	 * to do it again here.
+	 */
+	cfg.addr0 = page << 16;
+	cfg.cmd = 0xA;
+	cfg.cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET |
+			QPIC_SPI_TRANSFER_MODE_X1);
+#endif
 	cfg.exec = 1;
 	cmd_list_ptr = qpic_nand_add_cmd_ce(&cfg, cmd_list_ptr);
 
@@ -2418,13 +3092,13 @@
 	for (i = start; i < (start + blocks); i++) {
 		offs = i << chip->phys_erase_shift;
 		pageno = offs >> chip->page_shift;
+
 		/* Erase only if the block is not bad */
 		if (!instr->scrub && qpic_nand_block_isbad(mtd, offs)) {
 			printf("NAND Erase error: Block address belongs to "
 				"bad block: %ld\n",  (pageno / (dev->num_pages_per_blk)));
 			return -EIO;
 	}
-
 		ret = qpic_nand_blk_erase(mtd, pageno);
 		if (ret) {
 			instr->fail_addr = offs;
@@ -2519,6 +3193,25 @@
 		return;
 	}
 
+#ifdef CONFIG_QPIC_SERIAL
+	/* 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;
+	}
+
+	qpic_spi_init(mtd);
+#ifdef 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;
@@ -2544,13 +3237,27 @@
 	else if (ret > 0)
 		qpic_nand_non_onfi_probe(mtd);
 
+#ifndef CONFIG_QPIC_SERIAL
 	qpic_config_timing_parameters(mtd);
-
+#endif
 	/* Save the RAW and read/write configs */
 	ret = qpic_nand_save_config(mtd);
 	if (ret < 0)
 		return;
 
+#ifdef CONFIG_QPIC_SERIAL
+	/* Check all blocks of serial NAND device is unlocked or
+	 * not if not then unlock the all the blocks of serial NAND
+	 * device also check the internal ecc is enabled or not if internal
+	 * ecc is enabled then disable internal ecc using get/set feature
+	 * command.
+	 */
+	ret = qpic_spi_nand_config(mtd);
+	if (ret < 0) {
+		printf("%s : Issue with Serial Nand configuration.\n",__func__);
+		return;
+	}
+#endif
 	dev = MTD_QPIC_NAND_DEV(mtd);
 	qpic_nand_mtd_params(mtd);
 
diff --git a/include/configs/ipq40xx.h b/include/configs/ipq40xx.h
index 8e6b021..3613edf 100644
--- a/include/configs/ipq40xx.h
+++ b/include/configs/ipq40xx.h
@@ -84,6 +84,9 @@
 #define CONFIG_TZ_END_ADDR		0x88000000
 #define CONFIG_SYS_SDRAM_END		(CONFIG_SYS_SDRAM_BASE + gd->ram_size)
 
+#define CONFIG_QCA_UBOOT_OFFSET		0x7000000
+#define CONFIG_UBOOT_END_ADDR		0x87400000
+
 #define CONFIG_IPQ40XX_ENV
 #define CONFIG_ENV_IS_IN_NAND
 
diff --git a/include/configs/ipq5018.h b/include/configs/ipq5018.h
index e9a893e..e94798c 100644
--- a/include/configs/ipq5018.h
+++ b/include/configs/ipq5018.h
@@ -19,6 +19,7 @@
 #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
@@ -34,6 +35,11 @@
 #define CONFIG_ENV_SIZE_MAX			(256 << 10) /* 256 KB */
 
 /*
+* PSCI Calls enable
+*/
+#define CONFIG_ARMV7_PSCI
+
+/*
  *Size of malloc() pool
  */
 
@@ -130,6 +136,10 @@
 #define CONFIG_SYS_NAND_SELF_INIT
 #define CONFIG_SYS_NAND_ONFI_DETECTION
 
+/* QSPI Flash configs
+ */
+#define CONFIG_QPIC_SERIAL
+
 /*
 * SPI Flash Configs
 */
diff --git a/include/configs/ipq6018.h b/include/configs/ipq6018.h
index 5d9263e..835bf85 100644
--- a/include/configs/ipq6018.h
+++ b/include/configs/ipq6018.h
@@ -122,6 +122,9 @@
 #define CONFIG_TZ_END_ADDR		0x4AA00000
 #define CONFIG_SYS_SDRAM_END	((long long)CONFIG_SYS_SDRAM_BASE + gd->ram_size)
 
+#define CONFIG_QCA_UBOOT_OFFSET		0xA100000
+#define CONFIG_UBOOT_END_ADDR		0x4A500000
+
 #ifndef __ASSEMBLY__
 #include <compiler.h>
 extern loff_t board_env_offset;
diff --git a/include/configs/ipq806x.h b/include/configs/ipq806x.h
index 7126b42..bce2752 100644
--- a/include/configs/ipq806x.h
+++ b/include/configs/ipq806x.h
@@ -143,6 +143,9 @@
 #define QCA_BOOT_PARAMS_ADDR		(QCA_KERNEL_START_ADDR + 0x100)
 #define CONFIG_QCA_SMEM_BASE		CONFIG_SYS_SDRAM_BASE + 0x1000000
 
+#define CONFIG_QCA_UBOOT_OFFSET		0x1D00000
+#define CONFIG_UBOOT_END_ADDR		0x42100000
+
 #define CONFIG_OF_COMBINE		1
 
 #define CONFIG_CMD_BOOTZ
diff --git a/include/configs/ipq807x.h b/include/configs/ipq807x.h
index b7d8bf3..19a69f4 100644
--- a/include/configs/ipq807x.h
+++ b/include/configs/ipq807x.h
@@ -103,6 +103,8 @@
 
 #define CONFIG_OF_COMBINE		1
 
+#define CONFIG_QCA_UBOOT_OFFSET		0xA600000
+#define CONFIG_UBOOT_END_ADDR		0x4AA00000
 #define CONFIG_QCA_SMEM_BASE		0x4AB00000
 
 #define CONFIG_IPQ_FDT_HIGH		0x4A400000
diff --git a/lib/zlib/deflate.c b/lib/zlib/deflate.c
index 9a20b70..dd5c507 100644
--- a/lib/zlib/deflate.c
+++ b/lib/zlib/deflate.c
@@ -585,6 +585,7 @@
 {
     int old_flush; /* value of flush param for previous deflate call */
     deflate_state *s;
+    int hdr = 0;
 
     if (strm == Z_NULL || strm->state == Z_NULL ||
         flush > Z_BLOCK || flush < 0) {
@@ -603,6 +604,7 @@
 
     /* Write the header */
     if (s->status == INIT_STATE) {
+	hdr = 1;
 #ifdef GZIP
         if (s->wrap == 2) {
             strm->adler = crc32(0L, Z_NULL, 0);
@@ -782,7 +784,7 @@
 #endif
 
     /* Flush as much pending output as possible */
-    if (s->pending != 0) {
+    if ((s->pending != 0) && (hdr != 1)) {
         flush_pending(strm);
         if (strm->avail_out == 0) {
             /* Since avail_out is 0, deflate will be called again with
@@ -819,6 +821,15 @@
                     (s->strategy == Z_RLE ? deflate_rle(s, flush) :
                         (*(configuration_table[s->level].func))(s, flush));
 
+	/*****Flush header now to dst, which is src pointer after src data are read in previous step*****/
+	if ((s->pending != 0) && (hdr == 1)) {
+		flush_pending(strm);
+		if (strm->avail_out == 0) {
+			s->last_flush = -1;
+			return Z_OK;
+		}
+	}
+
         if (bstate == finish_started || bstate == finish_done) {
             s->status = FINISH_STATE;
         }