Chinaunix首页 | 论坛 | 博客
  • 博客访问: 61835
  • 博文数量: 23
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 45
  • 用 户 组: 普通用户
  • 注册时间: 2014-12-29 10:06
文章分类

全部博文(23)

文章存档

2015年(21)

2014年(2)

我的朋友

分类: LINUX

2015-03-27 14:58:07

原文地址:uboot之nand flash相关(1) 作者:gc5084

这几天在做和nandflash相关的东西,之前uboot中nandflash部分搞得模模糊糊。这次就将uboot中nand flash相关部分分析清楚
。本文uboot版本1.3.3

按照uboot的执行流程,在lib_arm/board.c文件中的start_armboot函数中会调用到nand初始化。
初始化的调用流程大致为:
start_armboot
nand_init //driver/mtd/nand/nand.c
nand_init_chip //driver/mtd/nand/nand.c
board_nand_init //cpu/sep4020/nand_flash.c
nand_scan //driver/mtd/nand/nand_base.c
start_armboot函数中,nand初始化部分

点击(此处)折叠或打开

  1. #if defined(CONFIG_CMD_NAND)    /*有nand的板都会定义CONFIG_CMD_NAND*/
  2.     puts ("NAND: ");
  3.     nand_init();        /* go init the NAND */
  4. #endif
nand_init()在driver/mtd/nand/nand.c文件中定义,此为nand初始化入口函数。

点击(此处)折叠或打开

  1. void nand_init(void)
  2. {
  3.     int i;
  4.     unsigned int size = 0;
  5.     for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {    //(1)
  6.         nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]);    //(2)
  7.         size += nand_info[i].size;    //(3)
  8.         if (nand_curr_device == -1)
  9.             nand_curr_device = i;
  10.     }
  11.     printf("%lu MiB\n", size / (1024 * 1024));

  12. #ifdef CFG_NAND_SELECT_DEVICE
  13.     /*
  14.      * Select the chip in the board/cpu specific driver
  15.      */
  16.     board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);
  17. #endif
  18. }
(1)CFG_MAX_NAND_DEVICE,nand的数量,一般板上有一个nand,就定义为1
(2)此函数初始化一个nand flash。首先看函数参数的3个变量。
  参数1 nand_info[i],其定义如
nand_info_t nand_info[CFG_MAX_NAND_DEVICE]; //driver/mtd/nand/nand.c
   定义了一个nand_info_t类型的全局数组,当然这里其CFG_MAX_NAND_DEVICE等于1,只有一个成员,再看nand_info_t定义
typedef struct mtd_info nand_info_t; //include/Nand.h
   mtd_info定义在include/linux/mtd/mtd.h中,它表示一个mtd设备的结构体,包含了mtd属性和其操作函数。

点击(此处)折叠或打开

  1. struct mtd_info {
  2.         u_char type;
  3.         u_int32_t flags;
  4.         u_int32_t size;     /* Total size of the MTD */
  5.     
  6.         /* "Major" erase size for the device. Na飗e users may take this
  7.          * to be the only erase size available, or may use the more detailed
  8.          * information below if they desire
  9.          */
  10.         u_int32_t erasesize;
  11.     
  12.         u_int32_t oobblock; /* Size of OOB blocks (e.g. 512) */
  13.         u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */
  14.         u_int32_t oobavail; /* Number of bytes in OOB area available for fs */
  15.         u_int32_t ecctype;
  16.         u_int32_t eccsize;
  17.     
  18.     
  19.         /* Kernel-only stuff starts here. */
  20.         char *name;
  21.         int index;
  22.     
  23.         /* oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) */
  24.         struct nand_oobinfo oobinfo;
  25.     
  26.         /* Data for variable erase regions. If numeraseregions is zero,
  27.          * it means that the whole device has erasesize as given above.
  28.          */
  29.         int numeraseregions;
  30.         struct mtd_erase_region_info *eraseregions;
  31.     
  32.         /* This really shouldn't be here. It can go away in 2.5 */
  33.         u_int32_t bank_size;
  34.     
  35.         int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
  36.     
  37.         /* This stuff for eXecute-In-Place */
  38.         int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
  39.     
  40.         /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
  41.         void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
  42.     
  43.     
  44.         int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
  45.         int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
  46.     
  47.         int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char
  48.     
  49.     *eccbuf, struct nand_oobinfo *oobsel);
  50.         int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char
  51.     
  52.     *eccbuf, struct nand_oobinfo *oobsel);
  53.     
  54.         int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
  55.         int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
  56.     
  57.         /*
  58.          * Methods to access the protection register area, present in some
  59.          * flash devices. The user data is one time programmable but the
  60.          * factory data is read only.
  61.          */
  62.         int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
  63.     
  64.         int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
  65.     
  66.         /* This function is not yet implemented */
  67.         int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
  68.     
  69.         /* Sync */
  70.         void (*sync) (struct mtd_info *mtd);
  71.     
  72.         /* Bad block management functions */
  73.         int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
  74.         int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
  75.     
  76.         void *priv;
  77.     
  78.         struct module *owner;
  79.         int usecount;
  80.     };
   参数2 nand_chip[i] ,如下
   static struct nand_chip nand_chip[CFG_MAX_NAND_DEVICE];
   再看struct nand_chip定义,当前文件(driver/mtd/nand/nand.c)包含nand.h(include目录),nand.h又包含#include ,所以nand_chip的定义是linux/mtd/nand.h中的。不是nand_legacy.h。这个结构体表示一个nand flash其包含所有属性和操作函数。

点击(此处)折叠或打开

  1. /**
  2.  * struct nand_chip - NAND Private Flash Chip Data
  3.  * @IO_ADDR_R:        [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
  4.  * @IO_ADDR_W:        [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
  5.  * @read_byte:        [REPLACEABLE] read one byte from the chip
  6.  * @write_byte:        [REPLACEABLE] write one byte to the chip
  7.  * @read_word:        [REPLACEABLE] read one word from the chip
  8.  * @write_word:        [REPLACEABLE] write one word to the chip
  9.  * @write_buf:        [REPLACEABLE] write data from the buffer to the chip
  10.  * @read_buf:        [REPLACEABLE] read data from the chip into the buffer
  11.  * @verify_buf:        [REPLACEABLE] verify buffer contents against the chip data
  12.  * @select_chip:    [REPLACEABLE] select chip nr
  13.  * @block_bad:        [REPLACEABLE] check, if the block is bad
  14.  * @block_markbad:    [REPLACEABLE] mark the block bad
  15.  * @hwcontrol:        [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
  16.  * @dev_ready:        [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
  17.  *            If set to NULL no access to ready/busy is available and the ready/busy information
  18.  *            is read from the chip status register
  19.  * @cmdfunc:        [REPLACEABLE] hardwarespecific function for writing commands to the chip
  20.  * @waitfunc:        [REPLACEABLE] hardwarespecific function for wait on ready
  21.  * @calculate_ecc:    [REPLACEABLE] function for ecc calculation or readback from ecc hardware
  22.  * @correct_data:    [REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
  23.  * @enable_hwecc:    [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
  24.  *            be provided if a hardware ECC is available
  25.  * @erase_cmd:        [INTERN] erase command write function, selectable due to AND support
  26.  * @scan_bbt:        [REPLACEABLE] function to scan bad block table
  27.  * @eccmode:        [BOARDSPECIFIC] mode of ecc, see defines
  28.  * @eccsize:        [INTERN] databytes used per ecc-calculation
  29.  * @eccbytes:        [INTERN] number of ecc bytes per ecc-calculation step
  30.  * @eccsteps:        [INTERN] number of ecc calculation steps per page
  31.  * @chip_delay:        [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
  32.  * @chip_lock:        [INTERN] spinlock used to protect access to this structure and the chip
  33.  * @wq:            [INTERN] wait queue to sleep on if a NAND operation is in progress
  34.  * @state:        [INTERN] the current state of the NAND device
  35.  * @page_shift:        [INTERN] number of address bits in a page (column address bits)
  36.  * @phys_erase_shift:    [INTERN] number of address bits in a physical eraseblock
  37.  * @bbt_erase_shift:    [INTERN] number of address bits in a bbt entry
  38.  * @chip_shift:        [INTERN] number of address bits in one chip
  39.  * @data_buf:        [INTERN] internal buffer for one page + oob
  40.  * @oob_buf:        [INTERN] oob buffer for one eraseblock
  41.  * @oobdirty:        [INTERN] indicates that oob_buf must be reinitialized
  42.  * @data_poi:        [INTERN] pointer to a data buffer
  43.  * @options:        [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
  44.  *            special functionality. See the defines for further explanation
  45.  * @badblockpos:    [INTERN] position of the bad block marker in the oob area
  46.  * @numchips:        [INTERN] number of physical chips
  47.  * @chipsize:        [INTERN] the size of one chip for multichip arrays
  48.  * @pagemask:        [INTERN] page number mask = number of (pages / chip) - 1
  49.  * @pagebuf:        [INTERN] holds the pagenumber which is currently in data_buf
  50.  * @autooob:        [REPLACEABLE] the default (auto)placement scheme
  51.  * @bbt:        [INTERN] bad block table pointer
  52.  * @bbt_td:        [REPLACEABLE] bad block table descriptor for flash lookup
  53.  * @bbt_md:        [REPLACEABLE] bad block table mirror descriptor
  54.  * @badblock_pattern:    [REPLACEABLE] bad block scan pattern used for initial bad block scan
  55.  * @controller:        [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
  56.  * @priv:        [OPTIONAL] pointer to private chip date
  57.  */

  58. struct nand_chip {
  59.     void __iomem    *IO_ADDR_R;
  60.     void __iomem    *IO_ADDR_W;

  61.     u_char        (*read_byte)(struct mtd_info *mtd);
  62.     void        (*write_byte)(struct mtd_info *mtd, u_char byte);
  63.     u16        (*read_word)(struct mtd_info *mtd);
  64.     void        (*write_word)(struct mtd_info *mtd, u16 word);

  65.     void        (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
  66.     void        (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
  67.     int        (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
  68.     void        (*select_chip)(struct mtd_info *mtd, int chip);
  69.     int        (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
  70.     int        (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
  71.     void        (*hwcontrol)(struct mtd_info *mtd, int cmd);
  72.     int        (*dev_ready)(struct mtd_info *mtd);
  73.     void        (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
  74.     int        (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
  75.     int        (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
  76.     int        (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
  77.     void        (*enable_hwecc)(struct mtd_info *mtd, int mode);
  78.     void        (*erase_cmd)(struct mtd_info *mtd, int page);
  79.     int        (*scan_bbt)(struct mtd_info *mtd);
  80.     int        eccmode;
  81.     int        eccsize;
  82.     int        eccbytes;
  83.     int        eccsteps;
  84.     int        chip_delay;
  85. #if 0
  86.     spinlock_t    chip_lock;
  87.     wait_queue_head_t wq;
  88.     nand_state_t    state;
  89. #endif
  90.     int        page_shift;
  91.     int        phys_erase_shift;
  92.     int        bbt_erase_shift;
  93.     int        chip_shift;
  94.     u_char        *data_buf;
  95.     u_char        *oob_buf;
  96.     int        oobdirty;
  97.     u_char        *data_poi;
  98.     unsigned int    options;
  99.     int        badblockpos;
  100.     int        numchips;
  101.     unsigned long    chipsize;
  102.     int        pagemask;
  103.     int        pagebuf;
  104.     struct nand_oobinfo    *autooob;
  105.     uint8_t        *bbt;
  106.     struct nand_bbt_descr    *bbt_td;
  107.     struct nand_bbt_descr    *bbt_md;
  108.     struct nand_bbt_descr    *badblock_pattern;
  109.     struct nand_hw_control    *controller;
  110.     void        *priv;
  111. };
  参数3 base_address[i],如下
  static ulong base_address[CFG_MAX_NAND_DEVICE] = CFG_NAND_BASE_LIST;
  CFG_NAND_BASE_LIST如下,
  #ifndef CFG_NAND_BASE_LIST
#define CFG_NAND_BASE_LIST { CFG_NAND_BASE }
  #endif
  CFG_NAND_BASE是在include/configs/UB4020.h中配置为
  #define CFG_NAND_BASE 0x11000200 (nand FIFO 数据寄存器)
  
  (3)计算出总共nandflash多少容量,在紧随其后的printf语句中打印出来。
  
  接着看同文件(driver/mtd/nand/nand.c)中nand_init_chip函数的分析

点击(此处)折叠或打开

  1. static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, ulong base_addr)
  2. {
  3.     mtd->priv = nand;

  4.     nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;    //(1)
  5.     if (board_nand_init(nand) == 0) {            //(2)
  6.         if (nand_scan(mtd, 1) == 0) {            //(3)
  7.             if (!mtd->name)    //这个名字在nand_scan中设置,如果在table中找到就有了。
  8.                 mtd->name = (char *)default_nand_name;
  9.         } else
  10.             mtd->name = NULL;
  11.     } else {
  12.         mtd->name = NULL;
  13.         mtd->size = 0;
  14.     }

  15. }
(1)从上面的nand_chip结构体中写道IO_ADDR_R,IO_ADDR_W是nand flash的读写地址, base_add这里设置为0x11000200,正好的nand FIFO的数据寄存器,读写flash的接口寄存器。
(2)此函数设置相关的nand 初始化,它和具体的体现结构有关系,不是共性的东西,在cpu/xxx/Nand_flash.c文件中。
(3) 此函数设置通用默认处理,获得flash id,并匹配等等。

  
这里我们分析的是sep4020 cpu的board_nand_init() 在cpu/sep4020/nand_flash.c

点击(此处)折叠或打开

  1. int board_nand_init( struct nand_chip *chip )
  2.  {
  3.     memset((char *) chip, 0, sizeof(struct nand_chip));

  4.     INTC_IMR = 0XFFFFFFFF;    //(REGW(INTC_BASE+0X008))IRQ中断屏蔽寄存器 置1为屏蔽 0为通过
  5.     INTC_IMR = 0X00000000;    
  6.     
  7.     EMI_NAND_CONF1 = 0x06402857;    //(1)
  8.     EMI_NAND_CONF2 = 0x00d14353;    //(2)
  9.  
  10.     vaddr = malloc(2112);            //(3)
  11.     oob64 = malloc(2112);    
  12.     memset(vaddr,0,2112);
  13.     memset(oob64,0,2112);
  14.     
  15.     int erasepage;
  16.     /*设置nand_chip结构中的各个函数指针*/
  17.     /* Set address of NAND IO lines */
  18.     chip->IO_ADDR_R = (void *) EMI_NAND_DATA_RAW;    //设置nand flash读写寄存器地址,其实在调用函数中已经设置过了
  19.     chip->IO_ADDR_W = (void *) EMI_NAND_DATA_RAW;
  20.     /* Set address of hardware control function */
  21.     chip->hwcontrol = sep4020_hwcontrol;
  22.     /* 15 us command delay time */
  23.     chip->dev_ready = sep4020_nand_dev_ready;
  24.     chip->chip_delay = 15;
  25.     chip->write_buf    = sep4020_nand_write_buf;
  26.     chip->read_buf = sep4020_nand_read_buf;
  27.     chip->write_byte = sep4020_nand_write_byte;
  28.     chip->read_byte = sep4020_nand_read_byte;
  29.     chip->eccmode = NAND_ECC_SOFT;
  30.     chip->select_chip = sep4020_nand_select_chip;

  31.     chip->cmdfunc = sep4020_nand_command;
  32.     chip->erase_cmd = sep4020_nand_cmd_erase;
  33.     /* Return happy */
  34.     return 0;
  35.  }
(1)NAND FLASH的配置器存器1 110-0--100--000000--101000--0101--0111 可查看芯片手册,其中一项设置成5级地址
(2)NAND FLASH的配置器存器2  1--1--0--100--010100--0011--01--01--00--11 可查看芯片手册,页大小配置为2K
(3)分配一个整页空间,后续的读写操作中会用到它来暂存一页数据。
阅读(988) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~