- 论坛徽章:
- 0
|
要想较好的理解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:
................. |
|