Chinaunix首页 | 论坛 | 博客
  • 博客访问: 971717
  • 博文数量: 192
  • 博客积分: 3070
  • 博客等级: 中校
  • 技术积分: 1861
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-27 23:44
个人简介

Start Linux Leave Linux a while Back to Linux

文章分类

全部博文(192)

文章存档

2023年(18)

2022年(11)

2021年(8)

2020年(14)

2019年(7)

2018年(13)

2017年(16)

2016年(4)

2012年(2)

2011年(13)

2010年(26)

2009年(13)

2008年(27)

2007年(20)

我的朋友

分类: LINUX

2008-10-21 10:13:11

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()

 

阅读(5390) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~