uboot之nand flash相关(1)

来源:互联网 发布:中国环境监测实时数据 编辑:程序博客网 时间:2024/05/18 14:12

这几天在做和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 chipin 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. /* "Major" erase size for the device. Na飗e users may take this
  6. * to be the onlyerase size available,or may use the more detailed
  7. * information below if they desire
  8. */
  9. u_int32_t erasesize;

  10. u_int32_t oobblock; /* Size of OOB blocks (e.g. 512)*/
  11. u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16)*/
  12. u_int32_t oobavail; /* Number of bytes in OOB area available for fs */
  13. u_int32_t ecctype;
  14. u_int32_t eccsize;


  15. /* Kernel-only stuff starts here.*/
  16. char *name;
  17. int index;

  18. /* oobinfois a nand_oobinfo structure, which can beset by iotcl (MEMSETOOBINFO)*/
  19. struct nand_oobinfo oobinfo;

  20. /* Datafor variable erase regions.If numeraseregions is zero,
  21. * it means that the whole device has erasesize as given above.
  22. */
  23. int numeraseregions;
  24. struct mtd_erase_region_info *eraseregions;

  25. /* This really shouldn't be here. It can go awayin 2.5 */
  26. u_int32_t bank_size;

  27. int (*erase)(struct mtd_info *mtd, struct erase_info*instr);

  28. /* This stufffor eXecute-In-Place*/
  29. int (*point)(struct mtd_info *mtd, loff_t from, size_tlen, size_t*retlen, u_char**mtdbuf);

  30. /* We probably shouldn't allow XIPif the unpoint isn't aNULL */
  31. void (*unpoint)(struct mtd_info *mtd, u_char* addr, loff_t from, size_tlen);


  32. int (*read)(struct mtd_info *mtd, loff_t from, size_tlen, size_t*retlen, u_char*buf);
  33. int (*write)(struct mtd_info *mtd, loff_tto, size_t len, size_t *retlen, const u_char*buf);

  34. int (*read_ecc)(struct mtd_info *mtd, loff_t from, size_tlen, size_t*retlen, u_char*buf, u_char

  35. *eccbuf, struct nand_oobinfo*oobsel);
  36. int (*write_ecc)(struct mtd_info *mtd, loff_tto, size_t len, size_t *retlen, const u_char*buf, u_char

  37. *eccbuf, struct nand_oobinfo*oobsel);

  38. int (*read_oob)(struct mtd_info *mtd, loff_t from, size_tlen, size_t*retlen, u_char*buf);
  39. int (*write_oob)(struct mtd_info *mtd, loff_tto, size_t len, size_t *retlen, const u_char*buf);

  40. /*
  41. * Methods to access the protection register area, presentin some
  42. * flash devices. The user datais one time programmable but the
  43. * factory data is read only.
  44. */
  45. int (*read_user_prot_reg)(struct mtd_info *mtd, loff_t from, size_tlen, size_t*retlen, u_char*buf);

  46. int (*read_fact_prot_reg)(struct mtd_info *mtd, loff_t from, size_tlen, size_t*retlen, u_char*buf);

  47. /* Thisfunction isnot yet implemented */
  48. int (*write_user_prot_reg)(struct mtd_info *mtd, loff_t from, size_tlen, size_t*retlen, u_char*buf);

  49. /* Sync*/
  50. void (*sync)(struct mtd_info *mtd);

  51. /* Bad block management functions*/
  52. int (*block_isbad)(struct mtd_info *mtd, loff_t ofs);
  53. int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);

  54. void *priv;

  55. struct module *owner;
  56. int usecount;
  57. };
参数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 <linux/mtd/nand.h>,所以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] addressto read the 8 I/O lines of the flash device
  4. * @IO_ADDR_W:[BOARDSPECIFIC] addressto 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 byteto the chip
  7. * @read_word:[REPLACEABLE] read one word from the chip
  8. * @write_word:[REPLACEABLE] write one wordto the chip
  9. * @write_buf:[REPLACEABLE] write data from the bufferto 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] hardwarespecificfunction for accesing control-lines
  16. * @dev_ready:[BOARDSPECIFIC] hardwarespecificfunction for accesing device ready/busy line
  17. * If set to NULL no accessto ready/busyis available and the ready/busy information
  18. * is read from the chip status register
  19. * @cmdfunc:[REPLACEABLE] hardwarespecificfunction for writing commandsto the chip
  20. * @waitfunc:[REPLACEABLE] hardwarespecificfunction for waiton ready
  21. * @calculate_ecc:[REPLACEABLE]function for ecc calculationor readback from ecc hardware
  22. * @correct_data:[REPLACEABLE]function for ecc correction, matchingto 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 dueto 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-calculationstep
  30. * @eccsteps:[INTERN] number of ecc calculation steps per page
  31. * @chip_delay:[BOARDSPECIFIC] chip dependent delayfor transfering data from array to read regs (tR)
  32. * @chip_lock:[INTERN] spinlock usedto 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 bitsin a page (column address bits)
  36. * @phys_erase_shift:[INTERN] number of address bitsin a physical eraseblock
  37. * @bbt_erase_shift:[INTERN] number of address bitsin a bbt entry
  38. * @chip_shift:[INTERN] number of address bitsin one chip
  39. * @data_buf:[INTERN] internal bufferfor one page + oob
  40. * @oob_buf:[INTERN] oob bufferfor one eraseblock
  41. * @oobdirty:[INTERN] indicates that oob_buf must be reinitialized
  42. * @data_poi:[INTERN] pointerto a data buffer
  43. * @options:[BOARDSPECIFIC] various chip options. They can partly beset to inform nand_scan about
  44. * special functionality. See the definesfor further explanation
  45. * @badblockpos:[INTERN] position of the bad block markerin the oob area
  46. * @numchips:[INTERN] number of physical chips
  47. * @chipsize:[INTERN] the size of one chipfor multichip arrays
  48. * @pagemask:[INTERN] page number mask= number of (pages/ chip) - 1
  49. * @pagebuf:[INTERN] holds the pagenumber whichis 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 descriptorfor flash lookup
  53. * @bbt_md:[REPLACEABLE] bad block table mirror descriptor
  54. * @badblock_pattern:[REPLACEABLE] bad block scan pattern usedfor initial bad block scan
  55. * @controller:[OPTIONAL] a pointerto a hardware controller structure which is shared among multiple independend devices
  56. * @priv:[OPTIONAL] pointerto private chipdate
  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. EMI_NAND_CONF1 = 0x06402857;//(1)
  7. EMI_NAND_CONF2 = 0x00d14353;//(2)

  8. vaddr = malloc(2112);//(3)
  9. oob64 = malloc(2112);
  10. memset(vaddr,0,2112);
  11. memset(oob64,0,2112);

  12. int erasepage;
  13. /*设置nand_chip结构中的各个函数指针*/
  14. /* Set address of NAND IO lines */
  15. chip->IO_ADDR_R= (void *) EMI_NAND_DATA_RAW;//设置nand flash读写寄存器地址,其实在调用函数中已经设置过了
  16. chip->IO_ADDR_W= (void *) EMI_NAND_DATA_RAW;
  17. /* Set address of hardware control function*/
  18. chip->hwcontrol= sep4020_hwcontrol;
  19. /* 15 us command delaytime */
  20. chip->dev_ready= sep4020_nand_dev_ready;
  21. chip->chip_delay= 15;
  22. chip->write_buf= sep4020_nand_write_buf;
  23. chip->read_buf= sep4020_nand_read_buf;
  24. chip->write_byte= sep4020_nand_write_byte;
  25. chip->read_byte= sep4020_nand_read_byte;
  26. chip->eccmode= NAND_ECC_SOFT;
  27. chip->select_chip= sep4020_nand_select_chip;

  28. chip->cmdfunc= sep4020_nand_command;
  29. chip->erase_cmd= sep4020_nand_cmd_erase;
  30. /* Return happy*/
  31. return 0;
  32. }
(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)分配一个整页空间,后续的读写操作中会用到它来暂存一页数据。

原创粉丝点击