/* SPDX-License-Identifier: GPL-2.0 */
/*
 ************************************************************************************************************************
 *                                                      eNand
 *                                           Nand flash driver scan module
 *
 *                             Copyright(C), 2008-2009, SoftWinners Microelectronic Co., Ltd.
 *                                                  All Rights Reserved
 *
 * File Name : version.c
 *
 * Author :
 *
 * Version : v0.1
 *
 * Date : 2013-11-20
 *
 * Description :
 *
 * Others : None at present.
 *
 *
 *
 ************************************************************************************************************************
 */
#define _NVER_C_

#include <linux/string.h>
#include "rawnand_debug.h"
#include "../nand_boot.h"
#include <sunxi_nand_errno.h>
#include "../nand_nftl.h"
#include "../nand_physic_interface.h"
#include "rawnand_chip.h"
#include "controller/ndfc_base.h"
#include "controller/ndfc_ops.h"
/*#include "rawnand.h"*/
#include <sunxi_nand.h>
#include "rawnand_base.h"
#include <sunxi_nand_boot.h>


/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void show_nctri(struct nand_controller_info *nctri)
{
	int i;
	char str[100] = {0};

	if (nctri == NULL) {
		RAWNAND_ERR(" ====invalid nctri=====\n");
		return;
	}

	RAWNAND_INFO("==============show_nctri======================\n");
	RAWNAND_INFO("channel_id:            %d\n", nctri->channel_id);
	RAWNAND_INFO("type:                  %d\n", nctri->type);
	RAWNAND_INFO("chip_cnt:              %d\n", nctri->chip_cnt);
	RAWNAND_INFO("chip_connect_info:     %d\n", nctri->chip_connect_info);
	RAWNAND_INFO("rb_connect_info:       %d\n", nctri->rb_connect_info);

	/*RAWNAND_INFO("ce: ");*/
	snprintf(str, sizeof("ce: "), "ce: ");
	for (i = 0; i < nctri->chip_cnt; i++)
		snprintf(str + sizeof("ce: ") + i, 1, "%d", nctri->ce[i]);
		/*RAWNAND_INFO("%d ", nctri->ce[i]);*/
	RAWNAND_INFO("%s\n", str);
	memset(str, 0, sizeof(str));
	snprintf(str, sizeof("rb: "), "rb: ");
	/*RAWNAND_INFO("\nrb: ");*/
	for (i = 0; i < nctri->chip_cnt; i++)
		snprintf(str + sizeof("rb: ") + i, 1, "%d", nctri->rb[i]);
		/*RAWNAND_INFO("%d ", nctri->rb[i]);*/
	/*RAWNAND_INFO("\n");*/
	RAWNAND_INFO("%s\n", str);

	RAWNAND_INFO("dma_type:              %d\n", nctri->dma_type);
	RAWNAND_INFO("dma_addr:              %d\n", nctri->dma_addr);
	RAWNAND_INFO("write_wait_rb_before:  %d\n", nctri->write_wait_rb_before_cmd_io);
	RAWNAND_INFO("write_wait_rb_mode:    %d\n", nctri->write_wait_rb_mode);
	RAWNAND_INFO("rb_ready_flag:         %d\n", nctri->rb_ready_flag);
	RAWNAND_INFO("dma_ready_flag:        %d\n", nctri->dma_ready_flag);

	memset(str, 0, sizeof(str));
	RAWNAND_INFO("timing ctl: ");
	for (i = 0; i < nctri->chip_cnt; i++)
		snprintf(str, 10, "0x%x", nctri->ddr_timing_ctl[i]);
		/*RAWNAND_INFO("0x%x ", nctri->ddr_timing_ctl[i]);*/
	RAWNAND_INFO("%s\n", str);
	RAWNAND_INFO("\n");

	ndfc_print_reg(nctri);

	RAWNAND_INFO("==============show_nctri end======================\n");

	return;
}
/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void show_nci(struct nand_chip_info *nci)
{
	int i;
	char str[100] = {0};
	if (nci == NULL) {
		RAWNAND_ERR(" invalid nci\n");
		return;
	}

	RAWNAND_INFO("==============show_nci======================\n");
	RAWNAND_INFO("id: ");
	for (i = 0; i < 8; i++)
		snprintf(str, 2, "%02x", nci->id[i]);
		/*RAWNAND_INFO("%02x ", nci->id[i]);*/
	RAWNAND_INFO("%s\n", str);
	RAWNAND_INFO("\n");
	RAWNAND_INFO("chip_no:                   %d\n", nci->chip_no);
	RAWNAND_INFO("nctri_chip_no:             %d\n", nci->nctri_chip_no);
	RAWNAND_INFO("driver_no:                 %d\n", nci->driver_no);
	RAWNAND_INFO("blk_cnt_per_chip:          %d\n", nci->blk_cnt_per_chip);
	RAWNAND_INFO("sector_cnt_per_page:       %d\n", nci->sector_cnt_per_page);
	RAWNAND_INFO("page_cnt_per_blk:          %d\n", nci->page_cnt_per_blk);
	RAWNAND_INFO("page_offset_for_next_blk:  %d\n", nci->page_offset_for_next_blk);
	RAWNAND_INFO("randomizer:                %d\n", nci->randomizer);
	RAWNAND_INFO("read_retry:                %d\n", nci->read_retry);
	RAWNAND_INFO("interface_type:            %d\n", nci->interface_type);
	RAWNAND_INFO("timing_mode:               %d\n", nci->timing_mode);
	//	RAWNAND_DBG("io_driver_strength:        %d\n", nci->io_driver_strength);
	RAWNAND_INFO("support_change_onfi_timing_mode:   %d\n", nci->itf_cfg.onfi_cfg.support_change_onfi_timing_mode);
	RAWNAND_INFO("support_onfi_ddr2_specific_cfg:    %d\n", nci->itf_cfg.onfi_cfg.support_ddr2_specific_cfg);
	RAWNAND_INFO("support_onfi_io_driver_strength:   %d\n", nci->itf_cfg.onfi_cfg.support_io_driver_strength);
	RAWNAND_INFO("support_toggle_vendor_specific_cfg:%d\n", nci->itf_cfg.toggle_cfg.support_vendor_specific_setting);
	RAWNAND_INFO("support_toggle_only:       %d\n", nci->support_toggle_only);
	RAWNAND_INFO("frequency:                 %d\n", nci->frequency);
	RAWNAND_INFO("ecc_mode:                  %d\n", nci->ecc_mode);
	RAWNAND_INFO("max_erase_times:           %d\n", nci->max_erase_times);
	RAWNAND_INFO("page_addr_bytes:           %d\n", nci->page_addr_bytes);
	RAWNAND_INFO("sdata_bytes_per_page:      %d\n", nci->sdata_bytes_per_page);
	RAWNAND_INFO("nsci chip_no:              0x%08x\n", nci->nsci->chip_no);
	RAWNAND_INFO("nctri channel_id:          0x%08x\n", nci->nctri->channel_id);

	RAWNAND_INFO("multi_plane_read_instr_cmd0:     0x%08x\n", nci->opt_phy_op_par->instr.multi_plane_read_instr[0]);
	RAWNAND_INFO("multi_plane_read_instr_cmd1:     0x%08x\n", nci->opt_phy_op_par->instr.multi_plane_read_instr[1]);
	RAWNAND_INFO("multi_plane_write_instr_cmd0:    0x%08x\n", nci->opt_phy_op_par->instr.multi_plane_write_instr[0]);
	RAWNAND_INFO("multi_plane_write_instr_cmd1:    0x%08x\n", nci->opt_phy_op_par->instr.multi_plane_write_instr[1]);
	RAWNAND_INFO("bad_block_flag_position:   0x%08x\n", nci->bad_block_flag_position);
	RAWNAND_INFO("multi_plane_block_offset:  0x%08x\n", nci->multi_plane_block_offset);
	RAWNAND_INFO("id_number:                 0x%08x\n", nci->npi->id_number);

	return;
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void show_nsci(struct nand_super_chip_info *nsci)
{
	if (nsci == NULL) {
		RAWNAND_ERR(" invalid nsci\n");
		return;
	}
	RAWNAND_INFO("=================show_nsci===================\n");
	RAWNAND_INFO("chip_no:                       %d\n", nsci->chip_no);
	RAWNAND_INFO("blk_cnt_per_super_chip:        %d\n", nsci->blk_cnt_per_super_chip);
	RAWNAND_INFO("sector_cnt_per_super_page:     %d\n", nsci->sector_cnt_per_super_page);
	RAWNAND_INFO("page_cnt_per_super_blk:        %d\n", nsci->page_cnt_per_super_blk);
	RAWNAND_INFO("page_offset_for_next_super_blk:%d\n", nsci->page_offset_for_next_super_blk);
	RAWNAND_INFO("spare_bytes:                   %d\n", nsci->spare_bytes);
	RAWNAND_INFO("two_plane:                     %d\n", nsci->two_plane);
	RAWNAND_INFO("channel_num:                   %d\n", nsci->channel_num);
	RAWNAND_INFO("vertical_interleave:           %d\n", nsci->vertical_interleave);
	RAWNAND_INFO("dual_channel:                  %d\n", nsci->dual_channel);
	RAWNAND_INFO("driver_no:                     %d\n", nsci->driver_no);
	RAWNAND_INFO("nci_first:                     %d %d\n", nsci->nci_first->chip_no, nsci->nci_first->nctri_chip_no);
	if (nsci->vertical_interleave != 0) {

		RAWNAND_INFO("v_intl_nci_1:              %d %d\n", nsci->v_intl_nci_1->chip_no, nsci->v_intl_nci_1->nctri_chip_no);
		RAWNAND_INFO("v_intl_nci_2:              %d %d\n", nsci->v_intl_nci_2->chip_no, nsci->v_intl_nci_2->nctri_chip_no);
	}
	if (nsci->dual_channel != 0) {

		RAWNAND_INFO("d_channel_nci_1:              %d %d\n", nsci->d_channel_nci_1->chip_no, nsci->d_channel_nci_1->nctri_chip_no);
		RAWNAND_INFO("d_channel_nci_2:              %d %d\n", nsci->d_channel_nci_2->chip_no, nsci->d_channel_nci_2->nctri_chip_no);
	}
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void show_nsi(void)
{
#ifdef DBG
	struct _nand_storage_info *nsi = g_nsi;
	RAWNAND_INFO("================show_nsi====================\n");
	RAWNAND_INFO("chip_cnt:      %d\n", nsi->chip_cnt);
	RAWNAND_INFO("block_nums:    %d\n", nsi->block_nums);
#endif
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void show_nssi(void)
{
	struct _nand_super_storage_info *nssi = g_nssi;
	struct nand_super_chip_info *nsci;

	RAWNAND_INFO("================show_nssi====================\n");
	RAWNAND_INFO("super_chip_cnt:      %d\n", nssi->super_chip_cnt);
	RAWNAND_INFO("super_block_nums:    %d\n", nssi->super_block_nums);
	RAWNAND_INFO("support_two_plane:   %d\n", nssi->support_two_plane);
	RAWNAND_INFO("support_v_interleave:%d\n", nssi->support_v_interleave);
	RAWNAND_INFO("support_dual_channel:%d\n", nssi->support_dual_channel);

	nsci = nssi->nsci;
	while (nsci != NULL) {
		show_nsci(nsci);
		nsci = nsci->nssi_next;
	}
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void show_static_info(void)
{
	struct nand_controller_info *nctri;
	struct nand_chip_info *nci;

	nctri = g_nctri;
	while (nctri != NULL) {
		show_nctri(nctri);
		nci = nctri->nci;
		while (nci != NULL) {
			show_nci(nci);
			nci = nci->nctri_next;
		}
		nctri = nctri->next;
	}
	show_nsi();
	show_nssi();
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void show_spare(int flag)
{
	unsigned char spare[64];
	int i, j, ret;
	//    unsigned int chip,block,page,bitmap;
	unsigned char *mbuf;
	//    struct _nand_physic_op_par npo;

	mbuf = nand_get_temp_buf(64 * 1024);

	for (i = NAND_BOOT0_BLK_START; i < NAND_BOOT0_BLK_CNT; i++) {
		;
	}

	RAWNAND_DBG("==========================uboot========================================\n");
	for (i = NAND_UBOOT_BLK_START; i < NAND_UBOOT_BLK_CNT; i++) {
		for (j = 0; j < g_nsi->nci->page_cnt_per_blk; j++) {
			ret = nand_physic_read_page(0, i, j, g_nsi->nci->sector_cnt_per_page, mbuf, spare);
			if ((ret != 0) && (ret != ECC_LIMIT)) {
				RAWNAND_ERR("ecc error chip0 block :%d page :0x%x \n", i, j);
			}
			RAWNAND_DBG("block:%d page:%d spare:0x%2x  0x%2x%2x%2x%2x   0x%2x%2x  0x%2x%2x%2x%2x\n", i, j, spare[0], spare[1], spare[2], spare[3], spare[4], spare[5], spare[6], spare[7], spare[8], spare[9], spare[10]);
		}
	}

	RAWNAND_DBG("==========================all page 0========================================\n");
	for (i = 8; i < g_nssi->nsci->blk_cnt_per_super_chip; i++) {
		ret = rawnand_physic_read_super_page(0, i, 0, 0, NULL, spare);
		if ((ret != 0) && (ret != ECC_LIMIT)) {
			RAWNAND_ERR("ecc error chip0 block :%d page :0 \n", i);
		}
		RAWNAND_DBG("block:%d page:0 spare:0x%2x    0x%2x 0x%2x 0x%2x 0x%2x   0x%2x%2x  0x%2x%2x%2x%2x\n", i, spare[0], spare[1], spare[2], spare[3], spare[4], spare[5], spare[6], spare[7], spare[8], spare[9], spare[10]);
	}

	if (flag == 0) {
		nand_free_temp_buf(mbuf, 64 * 1024);
		return;
	}

	RAWNAND_DBG("==========================all page========================================\n");
	for (i = 8; i < g_nssi->nsci->blk_cnt_per_super_chip; i++) {
		if (rawnand_physic_super_bad_block_check(0, i) != 0) {
			continue;
		}

		rawnand_physic_read_super_page(0, i, 0, 0, NULL, spare);

		RAWNAND_DBG("block:%d page:0 spare:0x%2x   0x%2x 0x%2x 0x%2x 0x%2x  0x%x%x  0x%x%x%x%x\n", i, spare[0], spare[1], spare[2], spare[3], spare[4], spare[5], spare[6], spare[7], spare[8], spare[9], spare[10]);

		if ((spare[0] == 0xff) && (spare[1] == 0xff) && (spare[2] == 0xff) && (spare[3] == 0xff) && (spare[4] == 0xff) && (spare[5] == 0xff)) {
			continue;
		}

		for (j = 1; j < g_nssi->nsci->page_cnt_per_super_blk; j++) {
			ret = rawnand_physic_read_super_page(0, i, j, 0, NULL, spare);
			if ((ret != 0) && (ret != ECC_LIMIT)) {
				RAWNAND_ERR("ecc error chip0 block :%d page :0x%x \n", i, j);
			}
			RAWNAND_DBG("block:%d page:%d spare:0x%2x   0x%2x 0x%2x 0x%2x 0x%2x  0x%x%x  0x%x%x%x%x\n", i, j, spare[0], spare[1], spare[2], spare[3], spare[4], spare[5], spare[6], spare[7], spare[8], spare[9], spare[10]);
		}
	}

	nand_free_temp_buf(mbuf, 64 * 1024);
	return;
}
/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void nand_show_data(uchar *buf, u32 len)
{
	u32 i;
	RAWNAND_DBG("show data: 0x%x %d\n ", buf, len);
	for (i = 0; i < len; i++) {
		RAWNAND_DBG("%2x ", buf[i]);
		if (((i + 1) % 32) == 0) {
			RAWNAND_DBG("\n");
		}
	}
	return;
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void show_dict_page(unsigned int chip, unsigned int block, unsigned int page, u32 start, u32 len)
{
	unsigned char spare[64];
	int i = 0;
	unsigned char *mbuf;
	//    struct _nand_physic_op_par npo;

#ifdef DBG
	uint32 special_data, block_used_count;
	uint16 erase_count;
#endif
	u32 start_byte;
	u32 len_byte;

	mbuf = nand_get_temp_buf(32 * 1024);

	//	ret = nand_physic_read_super_page(chip,block,page,0,NULL,spare);

	rawnand_physic_read_super_page(chip, block, page, g_nssi->nsci->sector_cnt_per_super_page, mbuf, spare);

#ifdef DBG
	special_data = get_special_data_from_oob(spare);
	block_used_count = get_block_used_count_from_oob(spare);
	erase_count = get_erase_count_from_oob(spare);

	RAWNAND_DBG("block:%d page:%d special_data:%x,erase_count:%x,block_used_count:%x\n", block, page, special_data, erase_count, block_used_count);
#endif

	start_byte = start << 9;
	len_byte = len << 9;

	for (i = start_byte; i < (start_byte + len_byte); i++) {
		RAWNAND_DBG("|%2x", mbuf[i]);
		if (((i + 1) % 32) == 0) {
			RAWNAND_DBG("\n");
		}
	}

	nand_free_temp_buf(mbuf, 32 * 1024);
	return;
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void show_logic_page_all_history(unsigned int logic_page)
{
	unsigned char spare[64];
	int i, j, ret;
	//   unsigned int chip,block,page,bitmap;
	//    unsigned char*mbuf;
	//    struct _nand_physic_op_par npo;
	uint32 special_data;

	//mbuf = nand_get_temp_buf(64*1024);

	for (i = 8; i < g_nssi->nsci->blk_cnt_per_super_chip; i++) {
		if (rawnand_physic_super_bad_block_check(0, i) != 0) {
			continue;
		}

		rawnand_physic_read_super_page(0, i, 0, 0, NULL, spare);
		if ((spare[0] == 0xff) && (spare[1] == 0xff) && (spare[2] == 0xff) && (spare[3] == 0xff) && (spare[4] == 0xff) && (spare[5] == 0xff)) {
			continue;
		}
		if ((spare[0] == 0xff) && (spare[1] == 0x55) && (spare[2] == 0x55) && (spare[3] == 0x55) && (spare[4] == 0x55)) {
			continue;
		}

		for (j = 0; j < g_nssi->nsci->page_cnt_per_super_blk; j++) {
			ret = rawnand_physic_read_super_page(0, i, j, 0, NULL, spare);
			if ((ret != 0) && (ret != ECC_LIMIT)) {
				RAWNAND_ERR("ecc error chip0 block :%d page :0x%x \n", i, j);
			}
			special_data = get_special_data_from_oob(spare);
			special_data &= 0x0fffffff;
			if (special_data == logic_page) {
				show_dict_page(0, i, j, 8, 10);
			}
		}
	}

	//nand_free_temp_buf(mbuf,64*1024);
	return;
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
int nand_super_page_test(unsigned int chip, unsigned int block, unsigned int page, unsigned char *mbuf)
{
	unsigned char spare[64];
	int i, ret;

	RAWNAND_DBG("nand super page_test chip:0x%x block:0x%x page:0x%x \n", chip, block, page);

	ret = rawnand_physic_erase_super_block(chip, block);
	if (ret != 0) {
		return ret;
	}

	for (i = 0; i < g_nssi->nsci->sector_cnt_per_super_page << 7; i++) {
		*((unsigned int *)(mbuf + (i << 2))) = i;
	}

	spare[0] = 0xff;
	for (i = 1; i < 16; i++) {
		spare[i] = 0xa0 + i;
	}

	rawnand_physic_write_super_page(chip, block, page, g_nssi->nsci->sector_cnt_per_super_page, mbuf, spare);

	memset(mbuf, 0, g_nssi->nsci->sector_cnt_per_super_page << 9);
	memset(spare, 0, 64);

	rawnand_physic_read_super_page(chip, block, page, g_nssi->nsci->sector_cnt_per_super_page, mbuf, spare);

	for (i = 0; i < g_nssi->nsci->sector_cnt_per_super_page << 7; i++) {
		if (*((unsigned int *)(mbuf + (i << 2))) != i) {
			RAWNAND_ERR("data error chip:0x%x block:0x%x page:0x%x \n", chip, block, page);
			ret = 2;
			break;
		}
	}

	for (i = 1; i < 16; i++) {
		if ((spare[i] != 0xa0 + i) || (spare[0] != 0xff)) {
			RAWNAND_ERR("spare error chip:0x%x block:0x%x page:0x%x \n", chip, block, page);
			ret = 2;
			break;
		}
	}

	rawnand_physic_erase_super_block(chip, block);

	return ret;
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
int nand_phy_page_test(unsigned int chip, unsigned int block, unsigned int page, unsigned char *mbuf)
{
	unsigned char spare[64];
	int i, ret = 0;
	int page_size;

	page_size = g_nsi->nci->sector_cnt_per_page << 9;

	RAWNAND_DBG("nand phy page_test chip:0x%x block:0x%x page:0x%x \n", chip, block, page);

	nand_physic_erase_block(chip, block);

	for (i = 0; i < (page_size >> 2); i++) {
		*((unsigned int *)(mbuf + (i << 2))) = i;
	}

	spare[0] = 0xff;
	for (i = 1; i < 16; i++) {
		spare[i] = 0xa0 + i;
	}

	nand_physic_write_page(chip, block, page, page_size >> 9, mbuf, spare);

	memset(mbuf, 0, page_size);
	memset(spare, 0, 64);

	nand_physic_read_page(chip, block, page, page_size >> 9, mbuf, spare);

	for (i = 0; i < (page_size >> 2); i++) {
		if (*((unsigned int *)(mbuf + (i << 2))) != i) {
			RAWNAND_ERR("data error chip:0x%x block:0x%x page:0x%x \n", chip, block, page);
			ret = 2;
			break;
		}
	}

	for (i = 1; i < 16; i++) {
		if ((spare[i] != 0xa0 + i) || (spare[0] != 0xff)) {
			RAWNAND_ERR("spare error chip:0x%x block:0x%x page:0x%x \n", chip, block, page);
			ret = 2;
			break;
		}
	}
	nand_physic_erase_block(chip, block);

	return ret;
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
int nand_phy_block_test(unsigned int chip, unsigned int block, unsigned char *mbuf, u32 test_bad, u8 dat)
{
	unsigned char spare[64];
	int i, j, ret;
	int page_size;
	unsigned char *mbuf_t;

	page_size = g_nsi->nci->sector_cnt_per_page << 9;

	mbuf_t = mbuf;

	RAWNAND_DBG("nand phy page_test !chip:0x%x block:0x%x\n", chip, block);

	if (test_bad == 0) {
		if (nand_physic_bad_block_check(chip, block) != 0) {
			RAWNAND_ERR("nand phy page_test bad block\n");
			return 0;
		}
	}

	nand_physic_erase_block(chip, block);

	for (i = 0; i < page_size; i++) {
		mbuf_t[i] = dat;
	}

	spare[0] = 0xff;
	for (i = 1; i < 16; i++) {
		spare[i] = i;
	}

	for (j = 0; j < g_nsi->nci->page_cnt_per_blk; j++) {
		nand_physic_write_page(chip, block, j, g_nsi->nci->sector_cnt_per_page, mbuf, spare);
	}

	for (j = 0; j < g_nsi->nci->page_cnt_per_blk; j++) {
		memset(mbuf, 0, page_size);
		memset(spare, 0, 64);
		ret = nand_physic_read_page(chip, block, j, g_nsi->nci->sector_cnt_per_page, mbuf, spare);
		//		if(ret == ECC_LIMIT)
		//		{
		//			ret = 2;
		//			goto block_test_end;
		//		}

		if (ret == ERR_ECC) {
			ret = 2;
			goto block_test_end;
		}

		if (ret == 0) {
			ret = 0;
			goto block_test_end;
		}

		mbuf_t = mbuf;
		for (i = 0; i < page_size; i++) {
			if (mbuf_t[i] != dat) {
				RAWNAND_ERR("data error chip:0x%x block:0x%x page:0x%x offset:0x%x data:0x%x\n", chip, block, j, i, mbuf_t[i]);
				ret = 2;
				goto block_test_end;
			}
		}

		for (i = 1; i < 16; i++) {
			if ((spare[i] != i) || (spare[0] != 0xff)) {
				RAWNAND_ERR("spare error chip:0x%x block:0x%x spare:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n", chip, block, spare[0], spare[1], spare[2], spare[3], spare[4], spare[5], spare[6], spare[7]);
				ret = 2;
				goto block_test_end;
			}
		}
		ret = 0;
	}

block_test_end:
	nand_physic_erase_block(chip, block);

	return ret;
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
int nand_phy_block_erase_test(unsigned int chip, unsigned int block)
{
	unsigned char spare[64];
	int i, j, ret = 0;
	int page_size;

	unsigned char *mbuf;

	page_size = g_nsi->nci->sector_cnt_per_page << 9;

	mbuf = nand_get_temp_buf(page_size);
	if (mbuf == NULL) {
		return 1;
	}

	RAWNAND_DBG("nand phy block erase test !chip:0x%x block:0x%x\n", chip, block);
	nand_physic_erase_block(chip, block);

	for (j = 0; j < g_nsi->nci->page_cnt_per_blk; j++) {
		memset(mbuf, 0, page_size);
		memset(spare, 0, 64);
		//		nand_physic_temp1 = 1;
		nand_physic_read_page(chip, block, j, g_nsi->nci->sector_cnt_per_page, mbuf, spare);
		//		nand_physic_temp1 = 0;
		if ((mbuf[0] != 0xff) && (mbuf[1] != 0xff) && (mbuf[2] != 0xff) && (mbuf[3] != 0xff)) {
			RAWNAND_ERR("data error chip:0x%x block:0x%x page:0x%x data:%x %x %x %x\n", chip, block, j, mbuf[0], mbuf[1], mbuf[2], mbuf[3]);
			ret = 2;
			goto test_ff_end;
		}
		for (i = 1; i < 16; i++) {
			if ((spare[i] != 0xff) || (spare[0] != 0xff)) {
				RAWNAND_ERR("spare error chip:0x%x block:0x%x spare:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n", chip, block, spare[0], spare[1], spare[2], spare[3], spare[4], spare[5], spare[6], spare[7]);
				ret = 2;
				goto test_ff_end;
			}
		}
	}

test_ff_end:
	nand_physic_erase_block(chip, block);

	nand_free_temp_buf(mbuf, page_size);
	return ret;
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void nand_phy_erase_all(void)
{
	//    unsigned char*mbuf;
	unsigned int i, j;
	//    unsigned char spare[64];
	//    int page_size;
	//    page_size = g_nsi->nci->sector_cnt_per_page<<9;
	//    chip = 0;
	//    page = 0;

	for (i = 0; i < g_nsi->chip_cnt; i++) {
		for (j = 0; j < g_nsi->nci->blk_cnt_per_chip; j++) {
			RAWNAND_DBG("erase chip: %d block: %d\n", i, j);
			nand_physic_erase_block(i, j);
			nand_wait_all_rb_ready();
		}
	}
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void nand_phy_check_all(u8 dat)
{
	unsigned char *mbuf;
	unsigned int i, j;
	int ret;

	int page_size = g_nsi->nci->sector_cnt_per_page << 9;

	RAWNAND_DBG("nand phy check all start\n");

	mbuf = nand_get_temp_buf(page_size);

	for (i = 0; i < g_nsi->chip_cnt; i++) {
		for (j = 0; j < g_nsi->nci->blk_cnt_per_chip; j++) {
			//			RAWNAND_DBG("nand phy check block:%d %d\n",i,j);
			ret = nand_phy_block_test(i, j, mbuf, 0, dat);
			if (ret == 0) {
				continue;
			}
			RAWNAND_DBG("mark chip: %d block: %d\n", i, j);
			nand_physic_bad_block_mark(i, j);
		}
	}
	nand_free_temp_buf(mbuf, page_size);

	RAWNAND_DBG("nand phy check all end\n");
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
int nand_phy_read_block_test(unsigned int chip, unsigned int start_block, unsigned int end_block)
{
	unsigned char spare[64];
	int i, j, ret = 0;
	int page_size;

	unsigned char *mbuf;

	page_size = g_nsi->nci->sector_cnt_per_page << 9;

	mbuf = nand_get_temp_buf(page_size);
	if (mbuf == NULL) {
		return 1;
	}

	for (j = start_block; j < end_block; j++) {
		RAWNAND_DBG("nand_phy_read_block_test !chip:0x%x block:0x%x\n", chip, j);

		for (i = 0; i < g_nsi->nci->page_cnt_per_blk; i++) {
			ret = nand_physic_read_page(chip, j, i, g_nsi->nci->sector_cnt_per_page, mbuf, spare);
			if (ret < 0) {
				RAWNAND_ERR("block error! chip:%d block:%d page:%d ret:%d\n", chip, j, i, ret);
				break;
			}
		}
	}

	nand_free_temp_buf(mbuf, page_size);
	return ret;
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
int nand_update_end(void)
{
	//    int ret;
	unsigned char *mbuf;
	int page_size;

	page_size = g_nsi->nci->sector_cnt_per_page << 9;
	mbuf = nand_get_temp_buf(page_size);

	nand_phy_block_test(0, 0, mbuf, 0, 0xaa);

	nand_phy_block_test(0, 2, mbuf, 0, 0xaa);

	nand_free_temp_buf(mbuf, page_size);
	RAWNAND_DBG("nand update end !\n");

	return 0;
}

/*****************************************************************************
 *Name         :
 *Description  :
 *Parameter    :
 *Return       :
 *Note         :
 *****************************************************************************/
void nand_special_test(void)
{
#if 0

	unsigned char *mbuf;
	unsigned int chip, block, page, i;
	unsigned char spare[64];
	int page_size;
	page_size = g_nssi->nsci->sector_cnt_per_super_page << 9;
	chip = 0;
	page = 0;

	memset(spare, 0, 64);

	page_size = 32768;
	mbuf = nand_get_temp_buf(page_size);
	RAWNAND_DBG("test start!!!\n");
	//---------------------------------------------------------------------------------

	//
	//    for(i=0; i<g_nsi->nci->page_cnt_per_blk; i++)
	//    {
	//        nand_physic_read_page(0,2,i,g_nsi->nci->sector_cnt_per_page,mbuf,spare);
	//        RAWNAND_DBG("spare %x %x %x %x %x %x!!!\n",spare[0],spare[1],spare[2],mbuf[0],mbuf[1],mbuf[2]);
	//    }

	//    nand_read_nboot_data(mbuf,page_size);

	//    memset(mbuf,0x0f,32768);
	//    nand_write_nboot_data(mbuf,page_size);

	//show_logic_page_all_history(0X6a00);
	//show_spare(1);
	//nand_phy_check_all(0xaa);

	nand_phy_block_test(0, 272, mbuf, 0, 0xff);

	//    nand_phy_check_all(0x55);
	//    nand_phy_check_all(0x0f);
	//    nand_phy_check_all(0xf0);
	//    nand_phy_check_all(0x01);
	//    nand_phy_check_all(0xfe);

	//---------------------------------------------------------------------------------

	//---------------------------------------------------------------------------------
	RAWNAND_DBG("test end!!!\n");
	nand_free_temp_buf(mbuf, page_size);
	while (1)
		;

#endif
	return;
}
