880 lines
27 KiB
C
Executable File
880 lines
27 KiB
C
Executable File
/* 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 "rawnand_debug.h"
|
|
#include "../../nfd/nand_osal_for_linux.h"
|
|
/*#include "../nand_boot.h"*/
|
|
#include "../nand-partition3/sunxi_nand_boot.h"
|
|
#include "../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 "rawnand_base.h"
|
|
|
|
|
|
/*****************************************************************************
|
|
*Name :
|
|
*Description :
|
|
*Parameter :
|
|
*Return :
|
|
*Note :
|
|
*****************************************************************************/
|
|
void show_nctri(struct nand_controller_info *nctri)
|
|
{
|
|
int i;
|
|
|
|
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: ");
|
|
for (i = 0; i < nctri->chip_cnt; i++)
|
|
RAWNAND_INFO("%d ", nctri->ce[i]);
|
|
RAWNAND_INFO("\nrb: ");
|
|
for (i = 0; i < nctri->chip_cnt; i++)
|
|
RAWNAND_INFO("%d ", nctri->rb[i]);
|
|
RAWNAND_INFO("\n");
|
|
|
|
RAWNAND_INFO("dma_type: %d\n", nctri->dma_type);
|
|
RAWNAND_INFO("dma_addr: %llx\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);
|
|
|
|
RAWNAND_INFO("timing ctl: ");
|
|
for (i = 0; i < nctri->chip_cnt; i++)
|
|
RAWNAND_INFO("0x%x ", nctri->ddr_timing_ctl[i]);
|
|
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;
|
|
|
|
if (nci == NULL) {
|
|
RAWNAND_ERR(" invalid nci\n");
|
|
return;
|
|
}
|
|
|
|
RAWNAND_INFO("==============show_nci======================\n");
|
|
RAWNAND_INFO("id: ");
|
|
for (i = 0; i < 8; i++)
|
|
RAWNAND_INFO("%02x ", nci->id[i]);
|
|
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);
|
|
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);
|
|
return;
|
|
}
|
|
/*****************************************************************************
|
|
*Name :
|
|
*Description :
|
|
*Parameter :
|
|
*Return :
|
|
*Note :
|
|
*****************************************************************************/
|
|
void nand_show_data(uchar *buf, u32 len)
|
|
{
|
|
u32 i;
|
|
RAWNAND_DBG("show data: %p %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);
|
|
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);*/
|
|
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;
|
|
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);
|
|
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);
|
|
|
|
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);
|
|
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);
|
|
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);
|
|
while (1)
|
|
;
|
|
|
|
#endif
|
|
return;
|
|
}
|