platform: s3c2416 + u-boot-1.1.6 + K9F1G08UOA
u-boot-1.1.6与1.1.4相比,两者有较大的不同,1.1.6 更像是复制了 kernel 的方法来实现。
u-boot 启动之后,执行完汇编的代码之后,跳到 start_armboot 开始运行 C 的代码。
lib_arm/board.c start_armboot
nand_init();
nand_init() 初始化 nandflash。
drivers/nand/nand.c nand_init_chip
nand_init()->nand_init_chip()
nand_init_chip()有 3 个参数, nand_info, nand_chip, base_address
nand_info 记录 mtd 的信息,原型是 mtd_info
struct mtd_info {
u_char type;
u_int32_t flags;
u_int32_t size; // Total size of the MTD
u_int32_t erasesize;
u_int32_t writesize;
u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
u_int32_t oobavail; // Available OOB bytes per block
u_int32_t ecctype;
u_int32_t eccsize;
...
};
nand_chip 记录了 nandflash 的一些操作方法, 如读、写函数的实现
struct nand_chip {
void __iomem *IO_ADDR_R;
void __iomem *IO_ADDR_W;
uint8_t (*read_byte)(struct mtd_info *mtd);
u16 (*read_word)(struct mtd_info *mtd);
void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
void (*select_chip)(struct mtd_info *mtd, int chip);
int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
void (*cmd_ctrl)(struct mtd_info *mtd, int dat,
unsigned int ctrl);
int (*dev_ready)(struct mtd_info *mtd);
void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
void (*erase_cmd)(struct mtd_info *mtd, int page);
int (*scan_bbt)(struct mtd_info *mtd);
int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int page, int cached, int raw);
int chip_delay;
unsigned int options;
int page_shift;
int phys_erase_shift;
int bbt_erase_shift;
int chip_shift;
int numchips;
unsigned long chipsize;
int pagemask;
int pagebuf;
int subpagesize;
uint8_t cellinfo;
int badblockpos;
nand_state_t state;
uint8_t *oob_poi;
#if 0
struct nand_hw_control *controller;
#endif
struct nand_ecclayout *ecclayout;
struct nand_ecc_ctrl ecc;
struct nand_buffers *buffers;
/* XXX U-BOOT XXX */
#if 0
struct nand_hw_control hwcontrol;
#endif
struct mtd_oob_ops ops;
uint8_t *bbt;
struct nand_bbt_descr *bbt_td;
struct nand_bbt_descr *bbt_md;
struct nand_bbt_descr *badblock_pattern;
void *priv;
};
base_address 就是 nandflash 的 base address
#ifndef CFG_NAND_BASE_LIST
#define CFG_NAND_BASE_LIST { CFG_NAND_BASE }
#endif
static ulong base_address[CFG_MAX_NAND_DEVICE] = CFG_NAND_BASE_LIST;
static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, ulong base_addr) { mtd->priv = nand;
nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr; board_nand_init(nand);
if (nand_scan(mtd, 1) == 0) { if (!mtd->name) mtd->name = (char *)default_nand_name; } else mtd->name = NULL;
}
|
nand_IO_ADDR_R 是 nandflash 地址的端口
drivers/nand/nand.c
nand_init()->nand_init_chip()->board_nand_init()
board_nand_init 是初始化 nandflash 读写端口及ECC 校正的模式和方法.
nand_init()->nand_init_chip()->nand_scan()
int nand_scan(struct mtd_info *mtd, int maxchips) { int ret;
#if 0 /* Many callers got this wrong, so check for it for a while... */ if (!mtd->owner && caller_is_module()) { printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n"); BUG(); } #endif //scan nandflash ID ret = nand_scan_ident(mtd, maxchips); if (!ret) ret = nand_scan_tail(mtd); return ret; }
|
nand_scan_ident 扫描 nandflash 的型号和ID.
drivers/nand/nand_base.c nand_set_defaults
nand_init()->nand_init_chip()->nand_scan()->nand_scan_ident->nand_set_defaults()
nand_set_defaults() set the default function
drivers/nand/nand_base.c nand_scan_tail()
nand_init()->nand_init_chip()->nand_scan()->nand_scan_tail()
阅读(1353) | 评论(0) | 转发(0) |