[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/boot/common/src/uboot/downloader/downloader_nand.c b/boot/common/src/uboot/downloader/downloader_nand.c
new file mode 100644
index 0000000..d28cfbc
--- /dev/null
+++ b/boot/common/src/uboot/downloader/downloader_nand.c
@@ -0,0 +1,974 @@
+/*******************************************************************************

+ * Copyright (C) 2016, ZIXC Corporation.

+ *

+ * File Name:

+ * File Mark:

+ * Description:

+ * Others:

+ * Version:       1.0

+ * Author:        geanfeng

+ * Date:          2013-3-4

+ * History 1:

+ *     Date:

+ *     Version:

+ *     Author:

+ *     Modification:

+ * History 2:

+  ********************************************************************************/

+

+/****************************************************************************

+* 	                                     Include files

+****************************************************************************/

+#include "downloader_nand.h"

+#include <asm/errno.h>

+#include "partition_table.h"

+#include <linux/mtd/nor_spifc.h>

+

+

+/****************************************************************************

+* 	                                    Local Macros

+****************************************************************************/

+#define DATA_WITH_OOB	(1 << 0) /* whether write with oob data*/

+/****************************************************************************

+*							Local Types

+****************************************************************************/

+/****************************************************************************

+*							Global Variables

+****************************************************************************/

+extern partition_table_t * g_partition_table;

+extern partition_table_t * g_partition_table_dl;

+extern partition_entry_t * get_partitions(const char *partname, partition_table_t *table);

+

+/****************************************************************************

+*							Global Function Prototypes

+****************************************************************************/

+/****************************************************************************

+*							Function Definitions

+****************************************************************************/

+/*******************************************************************************

+ * Function:get_part_offset_skipbase

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *phyBase

+ *

+ * Others:

+ ********************************************************************************/

+static int  get_part_offset_skipbase(partition_entry_t * part, uint offset, uint * skipBase)

+{

+	nand_info_t * pNandInfo = NULL;

+	uint  offsetSkipBase = 0;

+	uint blockNum = 0;

+	int ret = 0;

+	

+	pNandInfo = &nand_info[nand_curr_device];

+	offsetSkipBase = part->part_offset;

+	assert((offset & (pNandInfo->erasesize - 1)) == 0);

+	assert((offsetSkipBase & (pNandInfo->erasesize - 1)) == 0);

+	if(offset != 0)

+		{

+			blockNum = offset /pNandInfo->erasesize;

+			while(blockNum > 0)

+				{

+					ret = nand_block_isbad (pNandInfo, offsetSkipBase);

+					offsetSkipBase += pNandInfo->erasesize;

+					if (ret)

+						{

+							continue;

+						}

+					else

+						{

+							blockNum--;

+						}					

+				}

+		}

+	*skipBase = offsetSkipBase;

+

+	return 0;

+}

+

+

+/*******************************************************************************

+ * Function:nand_read_skip_bad_compt

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *	NULL:error    else: success

+ *

+ * Others:

+ ********************************************************************************/

+int nand_read_skip_bad_compat(nand_info_t *nand, loff_t offset, size_t *length,

+			u_char *buffer, int flags)

+{

+	int rval = 0, blocksize;

+	size_t left_to_read = *length;

+	u_char *p_buffer = buffer;

+

+	if (flags & DATA_WITH_OOB) {

+		int pages;

+		pages = nand->erasesize / nand->writesize;

+		blocksize = (pages * nand->oobsize) + nand->erasesize;

+		if (*length % (nand->writesize + nand->oobsize)) {

+			printf ("Attempt to write incomplete page"

+				" in yaffs mode\n");

+			return -EINVAL;

+		}

+	} else

+	{

+		blocksize = nand->erasesize;

+	}

+

+	if ((offset & (nand->writesize - 1)) != 0) {

+		printf ("Attempt to write non page aligned data\n");

+		*length = 0;

+		return -EINVAL;

+	}	

+

+	while (left_to_read > 0) {

+		size_t block_offset = offset & (nand->erasesize - 1);

+		size_t read_size, truncated_read_size;

+

+		if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {

+			printf ("Skip bad block 0x%08llx\n",

+				(u64)(offset & ~(nand->erasesize - 1)));

+			offset += nand->erasesize - block_offset;

+			continue;

+		}

+

+		if (left_to_read < (blocksize - block_offset))

+			read_size = left_to_read;

+		else

+			read_size = blocksize - block_offset;

+

+		if (flags & DATA_WITH_OOB) {

+			int page, pages;

+			size_t pagesize = nand->writesize;

+			size_t pagesize_oob = pagesize + nand->oobsize;

+			struct mtd_oob_ops ops;

+			memset(&ops, 0x0, sizeof(ops));

+

+			ops.len = pagesize;

+			ops.ooblen = nand->oobsize;

+			ops.mode = MTD_OOB_RAW;

+			ops.ooboffs = 0;

+

+			pages = read_size / pagesize_oob;

+			for (page = 0; page < pages; page++) {

+				ops.datbuf = p_buffer;

+				ops.oobbuf = ops.datbuf + pagesize;

+				rval = nand->read_oob(nand, offset, &ops);

+				if (rval)

+					break;

+

+				offset += pagesize;

+				p_buffer += pagesize_oob;

+			}

+		}

+		else

+		{

+			truncated_read_size = read_size;	

+			rval = nand_read(nand, offset, &truncated_read_size,

+					p_buffer);

+			offset += read_size;

+			p_buffer += read_size;

+		}

+

+		if (rval != 0) {

+			printf ("NAND read from offset %llx failed %d\n",

+				(u64)offset, rval);

+			*length -= left_to_read;

+			return rval;

+		}

+

+		left_to_read -= read_size;

+	}

+

+	return 0;

+}

+/*******************************************************************************

+ * Function:nand_read_skip_bad_compt

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *	NULL:error    else: success

+ *

+ * Others:

+ ********************************************************************************/

+int nand_write_skip_bad_compat(nand_info_t *nand, loff_t offset, size_t *length,

+			u_char *buffer, int flags)

+{

+	int rval = 0, blocksize;

+	size_t left_to_write = *length;

+	u_char *p_buffer = buffer;

+

+	if (flags & DATA_WITH_OOB) {

+		int pages;

+		pages = nand->erasesize / nand->writesize;

+		blocksize = (pages * nand->oobsize) + nand->erasesize;

+		if (*length % (nand->writesize + nand->oobsize)) {

+			printf ("Attempt to write incomplete page"

+				" in yaffs mode\n");

+			return -EINVAL;

+		}

+	} else

+	{

+		blocksize = nand->erasesize;

+	}

+

+	/*

+	 * nand_write() handles unaligned, partial page writes.

+	 *

+	 * We allow length to be unaligned, for convenience in

+	 * using the $filesize variable.

+	 *

+	 * However, starting at an unaligned offset makes the

+	 * semantics of bad block skipping ambiguous (really,

+	 * you should only start a block skipping access at a

+	 * partition boundary).  So don't try to handle that.

+	 */

+	if ((offset & (nand->writesize - 1)) != 0) {

+		printf ("Attempt to write non page aligned data\n");

+		*length = 0;

+		return -EINVAL;

+	}	

+

+	while (left_to_write > 0) {

+		size_t block_offset = offset & (nand->erasesize - 1);

+		size_t write_size, truncated_write_size;

+

+		if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {

+			printf ("Skip bad block 0x%08llx\n",

+				(u64)(offset & ~(nand->erasesize - 1)));

+			offset += nand->erasesize - block_offset;

+			continue;

+		}

+

+		if (left_to_write < (blocksize - block_offset))

+			write_size = left_to_write;

+		else

+			write_size = blocksize - block_offset;

+

+		if (flags & DATA_WITH_OOB) {

+			int page, pages;

+			size_t pagesize = nand->writesize;

+			size_t pagesize_oob = pagesize + nand->oobsize;

+			struct mtd_oob_ops ops;

+

+			ops.len = pagesize;

+			ops.ooblen = nand->oobsize;

+			ops.mode = MTD_OOB_RAW;

+			ops.ooboffs = 0;

+

+			pages = write_size / pagesize_oob;

+			for (page = 0; page < pages; page++) {

+				ops.datbuf = p_buffer;

+				ops.oobbuf = ops.datbuf + pagesize;

+				//ops.oobbuf = NULL;

+				if(*(ops.datbuf + pagesize) != 0xFF || *(ops.datbuf + pagesize+1) != 0xFF) {

+					printf ("Fs image format error\n");

+					return  -EINVAL;

+					}

+				rval = nand->write_oob(nand, offset, &ops);

+

+

+				if (rval)

+					break;

+

+				offset += pagesize;

+				p_buffer += pagesize_oob;

+			}

+		}

+		else

+		{

+			truncated_write_size = write_size;	

+			rval = nand_write(nand, offset, &truncated_write_size,

+					p_buffer);

+			offset += write_size;

+			p_buffer += write_size;

+		}

+

+		if (rval != 0) {

+			printf ("NAND write to offset %llx failed %d\n",

+				(u64)offset, rval);

+			*length -= left_to_write;

+			return rval;

+		}

+

+		left_to_write -= write_size;

+	}

+

+	return 0;	

+}

+/*******************************************************************************

+ * Function:downloader_get_part

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *	NULL:error    else: success

+ *

+ * Others:

+ ********************************************************************************/

+partition_entry_t *  downloader_get_part(const char *partname)

+{

+	partition_entry_t *part;

+

+	part = find_partition_para((uchar *)partname);

+	if(part == NULL)

+		return NULL;

+

+	return part;	

+}

+/*******************************************************************************

+ * Function:downloader_get_part_dl

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *	NULL:error    else: success

+ *

+ * Others:

+ ********************************************************************************/

+partition_entry_t *  downloader_get_part_dl(const char *partname)

+{

+	partition_entry_t *part;

+

+	part = get_partitions((const char *)partname,g_partition_table_dl);

+	if(part == NULL)

+	{

+		return NULL;

+	}

+	printf("name=%s,part-name=%s,typt=%s\n",partname,part->part_name,part->part_type);

+

+	return part;	

+}

+/*******************************************************************************

+ * Function:downloader_get_part_actual_size

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *	NULL:error    else: success

+ *

+ * Others:

+ ********************************************************************************/

+u32 downloader_get_part_actual_size(partition_entry_t *part)

+{

+    nand_info_t * pNandInfo = NULL;

+	pNandInfo = &nand_info[nand_curr_device];

+	u32 bad_blk_cnt = 0;

+	u32 offset = part->part_offset;

+	while(offset < part->part_offset + part->part_size )

+	{

+		if (nand_block_isbad (pNandInfo, offset) ){

+			bad_blk_cnt  = bad_blk_cnt +1 ;

+			offset += pNandInfo->erasesize;

+				continue;

+			}

+		offset += pNandInfo->erasesize;

+	}

+	printf("downloader_get_part_actual_size:[%s] bad_blk_cnt = %d\n",part->part_name, bad_blk_cnt);

+	u32 part_actual_size = part->part_size -(bad_blk_cnt * pNandInfo->erasesize);

+	return part_actual_size;

+}

+

+/*******************************************************************************

+ * Function:downloader_nand_read

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_read(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	nand_info_t * pNandInfo = NULL;

+	uint  nandPhyBase = 0;

+	int ret = 0;

+	

+	char ack[64] = {0};

+	if(part == NULL  || \

+		offset>part->part_size  || (size>downloader_get_part_actual_size(part)) || (offset+size) > part->part_size)

+		{

+		    printf(" [downloader_nand_read:][%s]bin_size > actual part_size \n", part->part_name);

+			sprintf(ack, " READ FAIL UNLEGAL SIZE ");

+			downloader_serial_write(ack, strlen(ack)+1);	

+			return -1;

+		}

+	pNandInfo = &nand_info[nand_curr_device];

+	get_part_offset_skipbase(part,offset,&nandPhyBase);

+

+    if( strcmp((const char *)part->part_name , "zloader") == 0 )

+    {   

+        /* ÕâÀﲻʹÓÃECC¶Áȡʱ£¬Òª¶ÁÈ¡OOB£¬¶øOOBµÃÊý¾Ý»á·ÅÈëdata->buf; 

+           ËùÒÔ´æ·ÅÊý¾ÝµÄbuf±ØÐëΪ (1 page + oob),²»ÄÜʹÓÃÉÏÃæ´«ÏÂÀ´µÄ

+           buffer,ÒòΪbufferµÄ´óСΪ²»°üº¬ oob µÄ´óС

+        */

+        u_char *buf = kzalloc(pNandInfo->writesize + pNandInfo->oobsize, GFP_KERNEL);

+        if( buf == NULL )

+        {

+			printf("downloader_nand_read kzalloc error\n");

+			return -1;

+		}

+                 

+        int times = size/pNandInfo->writesize;

+        int i = 0;

+        for(; i<times; i++)

+        {

+	        ret += nand_read_page_with_ecc(pNandInfo, 

+										   ((loff_t)i*pNandInfo->writesize),

+										   &size,

+										   (u_char*)buf );

+            memcpy((u_char*)buffer, buf ,pNandInfo->writesize);

+            buffer += pNandInfo->writesize;

+        }

+        kfree(buf);

+        

+    }

+        

+    else

+	    ret = nand_read_skip_bad(pNandInfo,\

+		        nandPhyBase+offset%(pNandInfo->erasesize),&size,(u_char*)buffer);

+	if(ret)

+		{

+			printf("downloader_nand_read error\n");

+			return -1;

+		}

+	return 0;

+}

+

+/*******************************************************************************

+ * Function:downloader_nand_write

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_write(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	nand_info_t * pNandInfo = NULL;

+	uint  nandPhyBase = 0;

+	int ret = 0;

+    uchar * buf = buffer;

+	char ack[64] = {0};

+	if(part == NULL  || \

+		offset>part->part_size  || (size > downloader_get_part_actual_size(part)) || (offset+size) > part->part_size)

+		{

+		    printf("[downloader_nand_write:][%s] bin_size > actual part_size \n", part->part_name);

+			sprintf(ack, "WRITE FAIL UNLEGAL SIZE ");

+			downloader_serial_write(ack, strlen(ack)+1);	

+			return -1;

+		}

+	/*if(zftl_get_ZFTLrecord(part->part_offset))

+		{

+			printf("Function not allowed write zftl\n");

+			return -1;

+		}*/

+	pNandInfo = &nand_info[nand_curr_device];

+	get_part_offset_skipbase(part,offset,&nandPhyBase);

+	printf("entry nand_write\n");

+	

+    /* רÃÅдZ-LOADʱʹÓ㬲»Ê¹ÓÃECC*/

+    if( strcmp((const char *)part->part_name , "zloader") == 0 )

+    {   

+        if( size != 12*1024 )

+        {

+            printf("downloader_nand_write z-load size != 12k...\n");

+			return -1;

+        } 

+        int times = 12*1024/pNandInfo->writesize;

+        int i = 0;

+

+        for(; i<times; i++)

+        {

+            

+            ret += nand_write_page_with_ecc(pNandInfo, 

+											((loff_t)i*(pNandInfo->writesize)),

+											buf );

+            buf += pNandInfo->writesize;

+        }

+        

+    }

+        

+    else

+	    ret = nand_write_skip_bad(pNandInfo,\

+		        nandPhyBase+offset%(pNandInfo->erasesize),&size,(u_char*)buffer, 0);

+    printf("write skipbad finish, addr = %d,size = %d\n",nandPhyBase+offset%(pNandInfo->erasesize),size);

+	if(ret)

+		{

+			printf("downloader_nand_write error\n");

+			return -1;

+		}

+	return 0;

+}

+

+/*******************************************************************************

+ * Function:downloader_nand_fs_read

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_fs_read(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	nand_info_t * pNandInfo = NULL;

+	uint  nandPhyBase = 0;

+	int ret = 0;

+	

+	char ack[64] = {0};

+	if(part == NULL || \

+		offset>part->part_size  || (size>downloader_get_part_actual_size(part)) || (offset+size) > part->part_size)

+		{

+		    printf("[downloader_nand_fs_read:][%s] bin_size > actual part_size \n", part->part_name);

+			sprintf(ack, " FS_READ FAIL UNLEGAL SIZE ");

+			downloader_serial_write(ack, strlen(ack)+1);	

+			return -1;

+		}

+	pNandInfo = &nand_info[nand_curr_device];

+	assert(pNandInfo!=NULL);

+	get_part_offset_skipbase(part,offset,&nandPhyBase);

+	ret = nand_read_skip_bad_compat(pNandInfo,nandPhyBase+offset%(pNandInfo->erasesize),&size,(u_char*)buffer,DATA_WITH_OOB);

+	if(ret)

+		{

+			printf("downloader_nand_fs_read error\n");

+			return -1;

+		}

+	return 0;

+}

+

+/*******************************************************************************

+ * Function:downloader_nand_fs_write

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_fs_write(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	nand_info_t * pNandInfo = NULL;

+	uint  nandPhyBase = 0;

+	int ret = 0;

+	char ack[64] = {0};

+	if(part == NULL || \

+		offset>part->part_size  || (size>downloader_get_part_actual_size(part)) || (offset+size) > part->part_size)

+		{

+		    printf("[downloader_nand_fs_write:][%s] bin_size > actual part_size \n", part->part_name);

+			sprintf(ack, " FS_WRITE FAIL UNLEGAL SIZE ");

+			downloader_serial_write(ack, strlen(ack)+1);	

+			return -1;

+		}

+

+	pNandInfo = &nand_info[nand_curr_device];

+	assert(pNandInfo!=NULL);

+	get_part_offset_skipbase(part,offset,&nandPhyBase);

+	ret = nand_write_skip_bad_compat(pNandInfo,nandPhyBase+offset%(pNandInfo->erasesize),&size,(u_char*)buffer, DATA_WITH_OOB);

+	if(ret)

+		{

+			printf("downloader_nand_fs_write error\n");

+			return -1;

+		}

+	return 0;

+}

+/*******************************************************************************

+ * Function:downloader_nand_erase

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_erase(partition_entry_t * part, uint  partEraseSize)

+{

+	nand_info_t * pNandInfo = NULL;

+	int  ret = 0;

+	struct erase_info instr;

+	uint  size = 0;

+	

+	if(part == NULL )

+	{

+		return -1;

+	}

+

+	pNandInfo = &nand_info[nand_curr_device];

+	instr.mtd = pNandInfo;

+	instr.addr = part->part_offset;

+	assert( (instr.addr & (pNandInfo->erasesize - 1)) == 0);

+	instr.callback = 0;

+	//ret=nand_erase(pNandInfo, part->part_offset, part->part_size);

+	while(size < partEraseSize  &&  (instr.addr < (part->part_offset+part->part_size)))

+		{

+		if(nand_block_isbad (pNandInfo, instr.addr))

+			{

+				instr.addr += pNandInfo->erasesize;

+				continue ;

+			}

+		instr.len = pNandInfo->erasesize;

+		instr.state = 0;

+		ret = pNandInfo->erase(pNandInfo, &instr);

+		if(ret  && instr.state == MTD_ERASE_FAILED)

+			{

+				pNandInfo->block_markbad(pNandInfo,instr.addr);

+			}

+		else if (ret == 0)

+			{

+				size += pNandInfo->erasesize;

+			}

+		else

+			{

+				printf( "downloader nand: erase error\n");

+				return 1;

+			}

+		instr.addr += pNandInfo->erasesize;

+		}

+	

+	return ret;

+}

+/*******************************************************************************

+ * Function:downloader_nand_eraseall

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_eraseall(void)

+{

+	nand_info_t * pNandInfo = NULL;

+	struct erase_info instr;

+	int i = 0;

+	int  ret = 0;

+

+	for(i=0; i<CONFIG_SYS_MAX_NAND_DEVICE; i++)

+		{

+			pNandInfo = &nand_info[i];

+

+			instr.mtd = pNandInfo;

+			instr.addr = 0x00;

+			assert( (instr.addr & (pNandInfo->erasesize - 1)) == 0);

+			instr.callback = 0;

+			while(instr.addr < pNandInfo->size)

+				{

+				if(nand_block_isbad (pNandInfo, instr.addr))

+					{

+						instr.addr += pNandInfo->erasesize;

+						continue ;

+					}

+				instr.len = pNandInfo->erasesize;

+				instr.state = 0;

+				ret = pNandInfo->erase(pNandInfo, &instr);

+				if(ret && instr.state == MTD_ERASE_FAILED)

+					{

+						pNandInfo->block_markbad(pNandInfo,instr.addr);

+					}

+				instr.addr += pNandInfo->erasesize;

+				}

+		}

+	return ret;

+}

+/*******************************************************************************

+ * Function:downloader_nand_erase_auto

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_erase_auto(void)

+{

+	int  ret = 0;

+	partition_entry_t *entry = &g_partition_table->table[0];

+    uint32_t entry_nums = g_partition_table->entrys;

+	

+	while( entry_nums-- )

+    {

+        if ( strcmp((const char *)entry->part_name, "nvrofs") == 0 \

+			||strcmp((const char *)entry->part_name, "ddr") == 0 \

+			||strcmp((const char *)entry->part_name, "raw") == 0)

+        {

+            entry++;

+            continue;

+        }

+		ret = downloader_nand_erase(entry,entry->part_size);

+        entry++;

+    }

+	return ret;

+}

+

+extern struct fsl_qspi spi_nor_flash;

+

+

+/*******************************************************************************

+ * Function:downloader_nor_read

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_nor_read(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	int ret = 0;

+	char ack[64] = {0};

+	size_t read_size = size;

+	struct fsl_qspi *nor = NULL;

+	

+	if(part == NULL  

+	   ||offset>part->part_size  

+	   || (offset+size) > part->part_size)

+	{

+		    printf(" [downloader_nor_read:][%s]bin_size > actual part_size \n", part->part_name);

+			sprintf(ack, " READ FAIL UNLEGAL SIZE ");

+			downloader_serial_write(ack, strlen(ack)+1);	

+			return -1;

+	}

+	

+	nor = &spi_nor_flash;

+    ret = nand_read(&(nor->nor[0].mtd), part->part_offset + offset, &read_size, buffer);

+	if(ret)

+	{

+		printf("downloader_nor_read error\n");

+		return -1;

+	}

+	

+	return 0;

+}

+

+

+/*******************************************************************************

+ * Function:downloader_nor_write

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+

+int downloader_nor_write(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	int ret = 0;

+     size_t write_size=0;

+	char ack[64] = {0};

+	struct fsl_qspi *nor = NULL;

+

+	write_size = size;

+	

+	if(part == NULL  

+	   || offset>part->part_size   

+	   || (offset+size) > part->part_size)

+	{

+		printf("[downloader_nor_write:][%s] bin_size > actual part_size \n", part->part_name);

+		sprintf(ack, "WRITE FAIL UNLEGAL SIZE ");

+		downloader_serial_write(ack, strlen(ack)+1);	

+		return -1;

+	}

+	

+	nor = &spi_nor_flash;

+	ret = nand_write(&(nor->nor[0].mtd), part->part_offset + offset, &write_size, buffer);

+	if(ret)

+	{

+		printf("downloader_nor_write error\n");

+		return ret;

+	}

+	

+	return 0;

+}

+

+/*******************************************************************************

+ * Function:downloader_nand_erase

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_nor_erase(partition_entry_t * part, uint  partEraseSize)

+{

+	int  ret = 0;

+	struct fsl_qspi *nor = NULL;

+	

+	if(part == NULL)

+	{

+		return -1;

+	}

+

+	nor = &spi_nor_flash;

+	ret = nand_erase(&(nor->nor[0].mtd), part->part_offset, partEraseSize);

+	if(ret)

+	{

+		printf("downloader_nor_erase error\n");

+		return ret;

+	}

+	printf("downloader_nor_erase ok\n");

+	return 0;

+}

+/*******************************************************************************

+ * Function:downloader_nor_eraseall

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_nor_eraseall(void)

+{

+	int  ret = 0;

+	struct fsl_qspi *nor = NULL;

+	

+	nor = &spi_nor_flash;

+	ret = nand_erase(&(nor->nor[0].mtd), 0x0, nor->nor[0].mtd.size);

+	if(ret)

+	{

+		printf("downloader_nor_eraseall error\n");

+		return ret;

+	}

+	printf("downloader_nor_eraseall ok\n");

+	return 0;

+

+}

+/*******************************************************************************

+ * Function:downloader_nor_erase_auto

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_nor_erase_auto(void)

+{

+	int  ret = 0;

+	partition_entry_t *entry = &g_partition_table->table[0];

+    uint32_t entry_nums = g_partition_table->entrys;

+	

+	while(entry_nums--)

+    {

+        if ( strcmp((const char *)entry->part_name, "nvrofs") == 0 \

+			||strcmp((const char *)entry->part_name, "ddr") == 0 \

+			||strcmp((const char *)entry->part_name, "raw") == 0)

+        {

+            entry++;

+            continue;

+        }

+		ret = downloader_nor_erase(entry,entry->part_size);

+		if(ret)

+		{

+			printf("downloader_nor_erase_auto error\n");

+			return ret;

+		}

+        entry++;

+    }

+	printf("downloader_nor_erase_auto ok\n");

+	return 0;

+}

+

+int get_nor_null_slice_flag(unsigned int *flag)

+{

+	int ret = 0;

+	size_t read_size = 0x100;

+	unchar buffer[256];

+	struct fsl_qspi *nor = NULL;

+		

+	memset(buffer, 0xFF, 0x100);

+	

+	nor = &spi_nor_flash;

+    ret = nand_read(&(nor->nor[0].mtd), 0x0, &read_size, buffer);

+	if(ret)

+	{

+		printf("downloader_nor_read error\n");

+		return -1;

+	}

+

+	if(strncmp((const char *)(buffer+4), "ZX7521V1", 8) == 0)

+	{

+		*flag = 1;

+		printf("nor flash not null\n");

+	}

+	

+	return 0;

+}

+	

+

+