[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;
+}
+
+
+