uboot之flash初始化

nand_init()函数其实现过程与内核nand驱动大致差不多,涉及到的结构体有pxa3xx_nand,此结构体包含mtd_info,mtd_info结构体在注册进mtd子系统时需要用到
比较重要的结构体还有nand_chip,这个结构体实现对nand操作的基本方法。应该提供:选中,发命令,发地址,发数据,读数据,判断状态的功能

void nand_init()
{
        struct pxa3xx_nand_platform_data pxa_nandinfo;
        struct pxa3xx_nand *nand;                     //具体哪类型芯片如下:
        int chip;

        pxa_nandinfo.mmio_base          = CONFIG_SYS_NAND_BASE;
        pxa_nandinfo.enable_arbiter     = 1;
        pxa_nandinfo.RD_CNT_DEL         = 0;

        nand = pxa3xx_nand_probe(&pxa_nandinfo);         
        if (!nand) {
                printf("pxa3xx-nand probe failed!!\n");
                return;
        }

        for (chip = 0; chip < CONFIG_SYS_MAX_NAND_DEVICE; chip ++) {
                if (nand->mtd[chip]) {
                        memcpy(&(nand_info[chip]), nand->mtd[chip], sizeof(struct mtd_info));

                        if (nand_curr_device < 0)
                                nand_curr_device = chip;
                }
        }

        if (nand_curr_device < 0)
                printf("No NAND dev is found !!!\n\n");
}

此处的probe与内核层的probe功能差不多,即实现nand的初始化和基本操作函数。

struct pxa3xx_nand *pxa3xx_nand_probe(struct pxa3xx_nand_platform_data *pdata)
{
        struct pxa3xx_nand               *nand;
        struct pxa3xx_bbm                *bbm;
        struct mtd_info                  *mtd;
        int    i;

        nand = alloc_nand_resource(pdata);          //分配一个nand资源
        if (!nand)
                return NULL;
      //对分配的nand结构体资源进行初始化
        nand->enable_arbiter    = pdata->enable_arbiter;
        nand->RD_CNT_DEL        = pdata->RD_CNT_DEL;
        //通过id号找到具体的nand设备
        pxa3xx_nand_detect_flash(nand);
        //
        for (i = 0; i < NUM_CHIP_SELECT; i ++) {
                mtd = nand->mtd[i];

                if (mtd) {
                        bbm = mtd->bbm;
                        pxa3xx_nand_init_mtd(mtd);        //重要:对nand_chip结构体进行赋值,包括对nand的基本操作如选中,发命令,发地址,发数据,读数据,判断状态的功能,
                        if (pxa3xx_nand_scan(mtd)) {       //对mtd和chip最后进行初始化
                                printf("failed to scan nand\n");
                        }
                        mtd->name = mtd_names[i];
#ifdef CONFIG_CMD_UBI
                        add_mtd_device(mtd);           //添加设备
#endif
                }
        }

下面函数中的f取值是具体支持的flash各参数指标。如
static struct pxa3xx_nand_flash esmt1G81A = {
.timing = &esmt_timing,
.cmdset = &largepage_cmdset,
.name = “ESMT F59L1G81A”,
.page_per_block = 64,
.page_size = 2048,
.flash_width = 8,
.dfc_width = 8,
.num_blocks = 1024,
.chip_id = 0xf192,
.chip_id_mask = 0xffff,
.ecc_type = ECC_BCH,
.ecc_strength = 1,
};

static int pxa3xx_nand_detect_flash(struct pxa3xx_nand *nand)
{
        struct pxa3xx_nand_flash *f;
        struct nand_chip *chip;
        struct pxa3xx_nand_info *info;
        struct mtd_info *mtd;
        uint32_t id = -1;
        int i, ret, chip_select;

        f = builtin_flash_types[0];   //取出一个支持的具体设备并给f赋初值
        chip_select = 0;
        for (; chip_select < NUM_CHIP_SELECT; chip_select ++) {
                mtd = nand->mtd[chip_select];
                chip = mtd->priv;
                info = mtd->priv;
                ret = pxa3xx_nand_sensing(info, chip_select);   //对nand控制器的寄存器进行赋值并复位
                if (!ret) {
                        free (nand->mtd[chip_select]);
                        nand->mtd[chip_select] = NULL;
                        continue;
                }

                pxa3xx_nand_cmdfunc(mtd, NAND_CMD_READID, 0, 0);   //读取ID操作

                id = *((uint32_t *)(info->data_buff));

                if (id == 0) {
                        kfree(mtd);
                        nand->mtd[chip_select] = NULL;
                        continue;
                }

                for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) {

                        f = builtin_flash_types[i];

                        /* find the chip in default list */
                        if (f->chip_id == (id & f->chip_id_mask)) {                        //查找是否支持此id类型设备。若支持则对mtd进行赋值初始化。
//                                      printf("detect chip id 0x%x on cs %d, %s\n",
//                                                      f->chip_id, chip_select, f->name);
                                pxa3xx_nand_config_flash(info, f, 1);
                                chip->cellinfo = info->data_buff[2];
                                mtd->writesize = f->page_size;
                                mtd->oobsize = mtd->writesize / 32;
                                mtd->erasesize = f->page_size * f->page_per_block;
                                if (is_power_of_2(mtd->erasesize))
                                        mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
                                else
                                        mtd->erasesize_shift = 0;

                                if (is_power_of_2(mtd->writesize))
                                        mtd->writesize_shift = ffs(mtd->writesize) - 1;
                                else
                                        mtd->writesize_shift = 0;

                                mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
                                mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
                                break;
                        }
                }

                if (i == ARRAY_SIZE(builtin_flash_types)) {
                        kfree(mtd);
                        nand->mtd[chip_select] = NULL;
                        printf("ERROR!! flash on cs %d id %x not defined!!!\n",
                                       chip_select, id);
                        continue;
                }
        }

        return 0;
}

具体函数调用关系如下:
nand_init()–>pxa3xx_nand_probe(&pxa_nandinfo)
–>pxa3xx_nand_detect_flash(nand)
–>pxa3xx_nand_sensing(info, chip_select)
–>pxa3xx_nand_cmdfunc(mtd, NAND_CMD_READID, 0, 0)

–>pxa3xx_nand_init_mtd(mtd)
–>pxa3xx_nand_scan(mtd)
–>nand_scan_tail(mtd)
–>add_mtd_device(mtd)

猜你喜欢

转载自blog.csdn.net/qq_28219531/article/details/72419743
今日推荐