免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3157 | 回复: 5
打印 上一主题 下一主题

诚邀一起解读G-BIOS BH的flas子系统 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-04-08 22:09 |只看该作者 |倒序浏览
有时间且有兴趣的话,不妨一起解读一下flas子系统!!!

论坛徽章:
0
2 [报告]
发表于 2011-04-09 09:49 |只看该作者
要想较好的理解BH flash subsystem ,TH的flash subsystem 是前提!

struct nand_chip
{
        u32 cmmd_port;
        u32 addr_port;
        u32 data_port;

        u32 write_size;
        u32 block_size;

        int (*flash_ready)(struct nand_chip *);
};

int nand_init(struct nand_chip *);
int nand_probe(struct nand_chip *);
int nand_load(struct nand_chip *);


int nand_probe(struct nand_chip *flash)
{
        u8  dev_id, ven_id, ext_id;
        int front, end;

        //
        nand_wait_ready(flash);

        nand_send_cmd(flash, NAND_CMMD_READID, -1, 0);
        ven_id = nand_read_data(flash);
        dev_id = nand_read_data(flash);

        if (dev_id == 0)
        {
                printf("NAND not found!\n");
                return -1;
        }

        printf("NAND = 0x%x%x\n", ven_id, dev_id);

        front = 0;
        end = ARRAY_ELEM_NUM(nand_ids);

        while (front <= end)
        {
                int nMid = (front + end) / 2;

                if (nand_ids[nMid] == dev_id)
                {
                        flash->write_size = 512;
                        flash->block_size = KB(16);

                        goto L1;
                }

                if (dev_id < nand_ids[nMid])
                        end = nMid -1;
                else
                        front = nMid + 1;
        }

        ext_id = nand_read_data(flash);
        ext_id = nand_read_data(flash);

        flash->write_size = KB(1) << (ext_id & 0x3);
        flash->block_size = KB(64) << ((ext_id >> 4) & 0x03);

L1:

        return 0;
}

int nand_load(struct nand_chip *flash)
{
        u32 cur_page, end_page;
        u32 wshift = 0, eshift = 0, shift;
        u32 bh_len = GBH_LOAD_SIZE;
        u8 *buff = (u8 *)GBH_START_MEM;

        // yes, calc shift in this way.
        for (shift = 0; shift < sizeof(long) * 8; shift++)
        {
                if ((1 << shift) == flash->write_size)
                        wshift = shift;
                else if ((1 << shift) == flash->block_size)
                        eshift = shift;
        }

        if (0 == wshift || 0 == eshift)
                return -1;

        cur_page = GBH_START_BLK << (eshift - wshift);

        buff = nand_read_page(flash, cur_page, buff);

        if (GBH_MAGIC == *(u32 *)(GBH_START_MEM + GBH_MAGIC_OFFSET))
        {
                bh_len = *(u32 *)(GBH_START_MEM + GBH_SIZE_OFFSET);
        }

        if (bh_len < flash->block_size)
        {
                bh_len = flash->block_size;
        }

        end_page = cur_page + ((bh_len - 1) >> wshift);

        while (++cur_page <= end_page)
        {
                buff = nand_read_page(flash, cur_page, buff);
        }

        return 0;
}

static int nand_loader(struct loader_opt *opt)
{
        int ret;

        // nand_chip must be initialized.
        struct nand_chip nand = {0};

        // printf("Loading from NAND...\n");
        ret = nand_init(&nand);

        if (ret >= 0)
                ret = nand_load(&nand);

        return ret;
}

REGISTER_LOADER(n, nand_loader, "NAND");

不同board ,编译后只有所选的board的init_nand函数才存在于g-bio-th.bin可执行程序中,这时通过REGISTER_LOADER(n, nand_loader, "NAND");把nand_loader函数放入自定义段gbios_loader里,当遍历gbios_loader段执行里面函数时执行到nand_loader函数,这时会调用所编译board 的nand_init(&nand)函数对nand结构体初始化(有关硬件操作在此步完成),当nand这个结构体成员都初始化好后,对于nand的操作就完全可以脱离具体的硬件操作而是对nand结构体几个成员的操作,这就是TH nand 子系统的主要思想!

board at91:
int nand_init(struct nand_chip *nand)
{
        u32 val;

#ifdef CONFIG_AT91SAM9261
        val = readl(AT91SAM926X_PA_MATRIX + MATRIX_EBICSA);
        val |= 1 << 3;
        writel(AT91SAM926X_PA_MATRIX + MATRIX_EBICSA, val);

        at91_smc_writel(SMC_SETUP(3), 0);
        at91_smc_writel(SMC_PULSE(3), 4 | 6 << 8 | 3 << 16 | 5 << 24);
        at91_smc_writel(SMC_CYCLE(3), 6 | 5 << 16);
        at91_smc_writel(SMC_MODE(3), 1 | 1 << 1 | 1 << 16);

        writel(AT91SAM926X_PA_PMC + PMC_PCER, 1 << PID_PIOC);

        // GPIO
        writel(AT91SAM926X_PA_PIOC + PIO_PDR, 0x3);
        writel(AT91SAM926X_PA_PIOC + PIO_ASR, 0x3);

        writel(AT91SAM926X_PA_PIOC + PIO_PER, PIO_NAND_CE);
        writel(AT91SAM926X_PA_PIOC + PIO_OER, PIO_NAND_CE);
        writel(AT91SAM926X_PA_PIOC + PIO_CODR, PIO_NAND_CE);

        writel(AT91SAM926X_PA_PIOC + PIO_PER, PIO_NAND_RDY);
        writel(AT91SAM926X_PA_PIOC + PIO_ODR, PIO_NAND_RDY);
        writel(AT91SAM926X_PA_PIOC + PIO_PUER, PIO_NAND_RDY);
#elif defined(CONFIG_AT91SAM9263)
        val = readl(AT91SAM926X_PA_MATRIX + MATRIX_EBI0CSA);
        val |= 1 << 3;
        writel(AT91SAM926X_PA_MATRIX + MATRIX_EBI0CSA, val);

        at91_smc_writel(SMC_SETUP(3), 0);
        at91_smc_writel(SMC_PULSE(3), 4 | 6 << 8 | 3 << 16 | 5 << 24);
        at91_smc_writel(SMC_CYCLE(3), 6 | 5 << 16);
        at91_smc_writel(SMC_MODE(3), 1 | 1 << 1 | 1 << 16);

        at91_pmc_writel(PMC_PCER, 1 << PID_PIOA | 1 << PID_PIOD);

        at91_gpio_conf_output(PIOD, PIO_NAND_CE, 0);
        at91_gpio_conf_input(PIOA, PIO_NAND_RDY, 1);

        writel(AT91SAM926X_PA_PIOD + PIO_CODR, PIO_NAND_CE);

        writel(AT91SAM926X_HECC0_MR, 0x2);
#endif

        nand->cmmd_port = AT91SAM926X_PA_NAND + NAND_CMMD;
        nand->addr_port = AT91SAM926X_PA_NAND + NAND_ADDR;
        nand->data_port = AT91SAM926X_PA_NAND + NAND_DATA;
        nand->flash_ready = at91_nand_flash_ready;

        return nand_probe(nand);
}

board s3c6410:
.................

论坛徽章:
0
3 [报告]
发表于 2011-04-09 19:21 |只看该作者
TH的很简单的……

论坛徽章:
0
4 [报告]
发表于 2011-04-09 19:24 |只看该作者
回复 2# lincoln-shaw


    谢谢,不过TH的太简单了。
   看到BH和Kernel里的比较相似,所以想通过它进一步了解Kernel的……

论坛徽章:
0
5 [报告]
发表于 2011-04-14 12:41 |只看该作者
g-bios的bh里的subsystem设计和kernel里的很相似,但比kernel更直观、简洁,对初学者入门了解kernel的架构设计思想再好不过了,学习g-bios可以作为学习kernel的一个平滑过度,避免学习kernel时走弯路的同时也锻炼了程序架构能力,当把g-bios弄清楚后再去看kernel源码你会发现一切都来的那么自然和简单。
大家一起来讨论学习,不妨将自己的一些理解或心得体会一起分享!

论坛徽章:
0
6 [报告]
发表于 2011-04-14 18:52 |只看该作者
LS正解
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP