⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nandflash.c

📁 启动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/**

* @FILENAME nandflash.c
* @BRIEF    并口NAND FLASH控制器驱
* Copyright (C) 2006 Anyka (Guangzhou) Software Technology Co., LTD
* @AUTHOR   dengjian
* @DATE   2006-1-11
* @VERSION  1.0
* @REF    Please refer to…
* @NOTE   1.只支持目前市面上大量生产的samsung 和hynix的驱动(这样运行速度会快一些
     果要支持比较特殊 的nandflash驱动,需要调整程序和宏定义
*   2. 多片选择的相关细节目前没有在驱动中体现,大多数都是针对单片flash编写。
*/
//#define OS_ANYKA
#ifdef OS_ANYKA

//#define CHK_STA_BEFORE
//#define CHK_STA_AFTER
//#define STORE_ALL_INT
#include "akdefine.h"
#include "nandflash.h"
#include "nand_list.h"
#include "CRCDrv.h"


// ECC flag bit
#define RS1_NO_ERR_BIT        (1 << 11)
#define RS2_NO_ERR_BIT        (1 << 12)
#define BCH_NO_ERR_BIT        (1 << 13)

#define RS1_CANT_CORRECT_BIT    (1 << 5)
#define RS2_CANT_CORRECT_BIT    (1 << 7)
#define BCH_CANT_CORRECT_BIT    (1 << 9)

#define RS1_CORRECT_END_BIT     (1 << 6)
#define RS2_CORRECT_END_BIT     (1 << 8)
#define BCH_CORRECT_END_BIT     (1 << 10)

// ECC error code(留16个错误码)
/*
 * 函数do_ECC_coerr()设置两个阀值:
 *  一个是16, 一个是2;
 *  当do_ECC_coerr()返回值>=ECC_CANT_CORRECT, 表示错不可纠, 此时不执行CRC校验;
 *  当do_ECC_coerr返回值小于ECC_CANT_CORRECT而大于等于ECC_NEED_CRC_CHECK, 表示错误较多, 可能会错纠, 此时执行CRC校验;
 *  当do_ECC_coerr返回值为0时, 表示无错或已经正确纠错;
 */
#define ECC_NEED_CRC_CHECK      (2)
#define ECC_CANT_CORRECT      (1 << 4)  // 
#define RS1_CANT_CORRECT      (1 << 4)
#define RS2_CANT_CORRECT      (1 << 5)
#define BCH_CANT_CORRECT      (1 << 6)

#define RS1_COERR         1
#define RS2_COERR         2


static T_S16 read_chipinfo();
static T_BOOL check_cmd_done(T_VOID);
static T_VOID CPU_setFIFO(T_U32 addr, T_U32 val);
static T_U32 CPU_readFIFO(T_U32 addr);
static T_VOID CPU_FIFO2memory(T_U32 *dest, T_U32 fifo_start, T_U8 count);
static T_VOID CPU_memory2FIFO(T_U32 fifo_start, T_U32 *src, T_U8 count);
static T_VOID DMA_FIFO2memory(T_U32 *dest, T_U32 fifo_start, T_U8 count);
static T_VOID DMA_memory2FIFO(T_U32 fifo_start, T_U32 *src, T_U8 count);
static T_U8 nf_read_status(T_U8 chip);

//#######excute comamnd,ctrl reg22 command configuration define ################
//所有的配置定义针对发送命令的方式。
//必须进行片选或片保护、操作模式、以及是否使能的省电模式flag
//片选使用宏NCHIP_SELECT(x)
//同时打该片的写保护,使用宏WRITE_PROTECT(x),
#define NCHIP_SELECT(x)     (((0x01 << (chipInfo.pos[x])) << 10) | (0xF << 15))


//*****************************************************************************************
//*************from lgj******************************************************************
// regisger 0x44 命令组合
#define comb_ctrl_reg(ps, staff, ce_keep, ce, wp, go) (ps | (staff << 1) | (ce_keep << 9) \
                       | (ce << 10) | (wp << 15) | (go << 30))

#define FLASH_CE_VALID    0 // (配置此值可选择不同FLASH)
#define SELECT_FLASH_CE   (1 << FLASH_CE_VALID)

#define SELECT_FLASH_WP   0x1

//static volatile T_BOOL NC_DMARun = AK_FALSE;
//static volatile T_BOOL NChip_Busy = AK_FALSE;
//static T_BOOL bNandInit = AK_FALSE;

T_NANDCHIP_INFO chipInfo;
T_NAND_LOG_INFO Nand_SysInfo;


/**
* @BRIEF read chip id for head file
* @AUTHOR dengjian
* @DATE 2006-01-05
* @PARAM
* @RETURN chip id
* @RETVAL
*/
static T_S16 read_chipinfo()
{

    T_U16  i, chip_cnt = 0;
    T_U32 nand_id = ERROR_CHIP_ID;
    T_NAND_PHY_INFO *nand_info;
    
    nand_info = (T_NAND_PHY_INFO *)0x40000020;
    

    chipInfo.count = 0;
    chipInfo.id = ERROR_CHIP_ID;
    for(i=0;i<NFC_SUPPORT_CHIPNUM;i++)
        chipInfo.pos[i] = i;
  
    for(i=0;i<NFC_SUPPORT_CHIPNUM;i++)
    {
        nand_id = ERROR_CHIP_ID;
    
        HAL_WRITE_UINT32(FLASH_CTRL_REG22, 0x00);

        HAL_WRITE_UINT32(FLASH_CTRL_REG0, (NFLASH_READ_ID << 11) | COMMAND_CYCLES_CONF);
        HAL_WRITE_UINT32(FLASH_CTRL_REG0+0x04, (0x00 << 11) | ADDRESS_CYCLES_CONF);

        //wait > 10 ns < 30????(84M, 1 clock =12ns)//wait 2 clocks
        HAL_WRITE_UINT32(FLASH_CTRL_REG0+0x08, 0 | DELAY_CNT_CONF);
        //ID information is 4 byte,read it to register 22

        HAL_WRITE_UINT32(FLASH_CTRL_REG0+0x0C, (0x03 << 11) | READ_INFO_CONF | LAST_CMD_FLAG);

        // excute operation, , enable power saving, CE# keep LOW wait R/B
        //printf("%d is 0x%x", i, NCHIP_SELECT(i));
        HAL_WRITE_UINT32(FLASH_CTRL_REG22, NCHIP_SELECT(i)|DEFAULT_GO);
        //HAL_READ_UINT32(FLASH_CTRL_REG22, nand_id);
        //printf("\r\nreg22 is 0x%x\r\n",nand_id );

        // wait end & read data (data at where)
        while(!check_cmd_done());

        // read status
        HAL_READ_UINT32(FLASH_CTRL_REG20, nand_id);

        //printf("\n*********************detect nand********************\n");
        //printf("bios detect %d nandid is 0x%x\n", i, nand_id);

        if(nand_id != ERROR_CHIP_ID)
        {
            printf("nand_info->chip_id nand_id is 0x%x 0x%x\n", nand_info->chip_id, nand_id);
            if(chipInfo.id != nand_id)
            {
                if(nand_info->chip_id == nand_id)
                {
                    if (chipInfo.id == ERROR_CHIP_ID)
                    {
                        chipInfo.id = nand_id;
            
                        //printf("\r\ncurrent nandflash:");
                        //printf(SUPPORT_NAND_TABLE[id_cnt].des_str);
                        //printf("\r\n");
            
                        chipInfo.col_cycle = nand_info->col_cycle;
                        printf("chipInfo.col_cycle %x\n", chipInfo.col_cycle);
                        chipInfo.row_cycle = nand_info->row_cycle;
                        printf("chipInfo.row_cycle %x\n", chipInfo.row_cycle);
                        chipInfo.lst_col_mask = nand_info->lst_col_mask;
                        printf("chipInfo.lst_col_mask %x\n", chipInfo.lst_col_mask);
                        chipInfo.last_row_mask = nand_info->last_row_mask;
                        printf("chipInfo.last_row_mask %x\n", chipInfo.last_row_mask);
                        chipInfo.phy_page_size = nand_info->page_size;
                        printf("chipInfo.phy_page_size %x\n", chipInfo.phy_page_size);
                        chipInfo.chip_blk_num = nand_info->blk_num;
                        printf("chipInfo.chip_blk_num %x\n", chipInfo.chip_blk_num);
                        chipInfo.group_blk_num = nand_info->group_blk_num;
                        printf("chipInfo.group_blk_num %x\n", chipInfo.group_blk_num);
                        chipInfo.plane_blk_num = nand_info->plane_blk_num;
                        printf("chipInfo.plane_blk_num %x\n", chipInfo.plane_blk_num);
                        chipInfo.phy_page_per_blk = nand_info->page_per_blk;
                        printf("chipInfo.phy_page_per_blk %x\n", chipInfo.phy_page_per_blk);
                    }
                }
                else
                {
                    printf("We dont support different chip type in one machine!!\r\n");
                    return NF_FAIL;
                }
            }

            if (nand_id == chipInfo.id)
            {
                chipInfo.pos[chipInfo.count] = i;
                chipInfo.count++;
                printf("now count is %d\n", chipInfo.count);
            }
        }

    }  

    if (chipInfo.count>0)
    {
        printf("\r\n chip ID is 0x%x\r\n  count= %d \n", chipInfo.id, chipInfo.count);
  
        return NF_SUCCESS;
    }

    printf("Cannot find chip!\r\n");
    return NF_FAIL;
}


//******************************************init,read chipID and set information done*******************************//

static T_S32 do_RS_coerr(T_U8 RS_type, T_pDATA buf)
{
  T_S32 errCnt;
  T_U32 regAddr, offset, tmp;
  T_U32 errValue, errAddr;
  

  if (RS_type == RS1_COERR)
  {
    printf("do RS1 coerr\r\n");

    regAddr = FLASH_ECC_REG4 + 0x04;
    offset = 0;
  }
  else if (RS_type == RS2_COERR)
  {
    printf("do RS2 coerr\r\n");

    regAddr = FLASH_ECC_REG4 + 0x08;
    /* phy structure, must offset value is 255(251B + 4B)
     * phy structure conver to logic structure !!!
     * 减去1个RS占的长度(4B*1), rs2 logic offset value is 251B(no RS code)       
     */
    offset = 255 - 4;
  }

  errCnt = 0;
  HAL_READ_UINT32(regAddr, tmp);
  errValue = (tmp >> 16) & 0xFF;
  errAddr = (tmp >> 24) & 0xFF;
  if ((251 <= errAddr) && (errAddr <= 254)) // 是否是ECC本身错
  {
    printf("Is RS_err1 ECC itself error, ignore it\r\n");
    
    errCnt++;
  }     
  else if (errAddr != 255)
  {
    errAddr += offset;
    printf("rs err1 value is 0x%x, location is 0x%x\r\n", errValue, errAddr);
    printf("excute corect rs err1: 0x%x --> 0x%x\r\n", 
      buf[errAddr], buf[errAddr] ^ errValue);
    buf[errAddr] = buf[errAddr] ^ errValue; // correct
    
    errCnt++;
  }

  errValue = tmp & 0xFF;
  errAddr = (tmp >> 8) & 0xFF;
  if ((251 <= errAddr) && (errAddr <= 254)) // 是否是ECC本身错
  {
    printf("errAddr = 0x%x,  errValue = 0x%x\r\n", errAddr, errValue);
    printf("Is RS_err2 ECC itself error, ignore it\r\n");
    
    errCnt++;
  }     
  else if (errAddr != 255)  // have error
  {
    errAddr += offset;
    printf("rs err2 value is 0x%x, location is 0x%x\r\n", errValue, errAddr);
    printf("excute corect rs err2: 0x%x --> 0x%x\r\n", 
      buf[errAddr], buf[errAddr] ^ errValue);
    buf[errAddr] = buf[errAddr] ^ errValue; // correct
    
    errCnt++;
  }

  return errCnt;
}

/**
* @BRIEF 根据ECC进行纠错
* @AUTHOR lgj
* @DATE 2005-10-25
* @PARAM
*     buf
*       518Byte data for coerror.
*     fileSysBuf
*       file system information buffer.
* @RETURN
* @RETVAL
*     >=ECC_CANT_CORRECT, 表示错不可纠, 此时不执行CRC校验;
*     小于ECC_CANT_CORRECT而大于等于ECC_NEED_CRC_CHECK, 表示错误较多, 可能会错纠, 此时执行CRC校验;
*     为0时, 表示无错或已经正确纠错;
* @NOTE   
*   1.
*     buf: is logic structure:  512B data + 6B file system
*     ECC: is phy structure: 251B data + 4B rs1 + 251B data + 4B rs2 + 16B data + 2B bch
*
*   2. 校验码本身错时不用纠
*
*   3. 纠错过程:
*
* @to do
*   1. 当错不可纠时的处理.
*/
T_S32 do_ECC_coerr(T_pDATA buf, T_pDATA fileSysBuf)
{
  T_S32 ret;
  T_U32 tmp, status;

  T_U8 bit_loc;
  T_U16 byte_loc;
  T_U16 ecc_loc;
  T_U32 *reg_addr = (T_U32 *) FLASH_ECC_REG4;

  ret = 0;

  HAL_READ_UINT32(FLASH_ECC_REG4, status);
  if ((status & RS1_NO_ERR_BIT) != RS1_NO_ERR_BIT)
  {
    // RS1 have error
    if (status & RS1_CANT_CORRECT_BIT)
    {
      printf("RS1 have error, but can't correct(too many error)\r\n");
      ret |= RS1_CANT_CORRECT;
    }
    else
    {
      // 等待纠错过程结束
      while (1)
      {
        HAL_READ_UINT32(FLASH_ECC_REG4, status);
        if (status & RS1_CORRECT_END_BIT)
          break;
      }
      ret += do_RS_coerr(RS1_COERR, buf);
    }
  }
  else
  {
//    printf("RS1 no error\r\n");
  }

  // 使用最新的status
  if ((status & RS2_NO_ERR_BIT) != RS2_NO_ERR_BIT)
  {
    // RS2 have error
    if (status & RS2_CANT_CORRECT_BIT)
    {
      printf("RS2 have error, but can't correct(too many error)\r\n");
      ret |= RS2_CANT_CORRECT;
    }
    else
    {
      // 等待纠错过程结束
      while (1)
      {
        HAL_READ_UINT32(FLASH_ECC_REG4, status);
        if (status & RS2_CORRECT_END_BIT)
          break;
      }

      ret += do_RS_coerr(RS2_COERR, buf);
    }
  }
  else
  {
//    printf("RS2 no error\r\n");
  }
  
  // 使用最新的status
  if ((status & BCH_NO_ERR_BIT) != BCH_NO_ERR_BIT)
  {
    // BCH have error
    if (status & BCH_CANT_CORRECT_BIT)
    {
      printf("BCH have error, but can't correct(too many error)\r\n");
      ret |= BCH_CANT_CORRECT;
    }
    else
    {
      T_U8 cnt;

      // 等待纠错过程结束
      while (1)
      {
        HAL_READ_UINT32(FLASH_ECC_REG4, status);
        if (status & BCH_CORRECT_END_BIT)
          break;
      }
      // corect bch
      HAL_READ_UINT32(FLASH_ECC_REG4 + 0x0C, tmp);      
      for (cnt=0; cnt<2; cnt++)
      {
        ecc_loc = (tmp >> 8*cnt) & 0xFF;
        if (ecc_loc == 0xFF)
        {
          // 不是BCH2有错
//          printf("BCH %d no error\r\n", cnt);
        }
        else
        {
          ret++;

          byte_loc = (ecc_loc - 111) / 8 + 510; // ?
          bit_loc = (byte_loc - 510) * 8 + 111 + 7 - ecc_loc;
          // phy structure conver to logic structure !!!

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -