void board_init_r (gd_t *id,ulong dest_addr)
{
?? ?char *s;
?? ?bd_t *bd;
?? ?ulong malloc_start;
??? #ifndef CONFIG_SYS_NO_FLASH
?? ?ulong flash_size;
??? #endif
?? ?gd = id;?? ??? ?/* initialize RAM version of global data */
?? ?bd = gd->bd;
?? ?gd->flags |= GD_FLG_RELOC;?? ?/* tell others: relocation done */
?? ?/* The Malloc area is immediately below the monitor copy in DRAM */
?? ?malloc_start = dest_addr - TOTAL_MALLOC_LEN;
?? ?printf ("Now running in RAM - U-Boot at: %08lxn",dest_addr);
?? ?WATCHDOG_RESET ();
?? ?/*
?? ? * Setup trap handlers
?? ? */
?? ?trap_init (dest_addr);
?? ?monitor_flash_len = (ulong)&__init_end - dest_addr;
?? ?asm ("sync ; isync");
?? ?mem_malloc_init (malloc_start,TOTAL_MALLOC_LEN);
#if !defined(CONFIG_SYS_NO_FLASH)
?? ?puts ("FLASH: ");
?? ?if ((flash_size = flash_init ()) > 0) {
?? ?/* !CONFIG_SYS_FLASH_CHECKSUM */
?? ??? ?print_size (flash_size,"n");
?? ?} else {
?? ??? ?puts (failed);
?? ??? ?hang ();
?? ?}
?? ?bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;?? ?/* update start of FLASH memory??? */
?? ?bd->bi_flashsize = flash_size;?? ?/* size of FLASH memory (final value) */
?? ?/* initialize higher level parts of CPU like time base and timers */
?? ?cpu_init_r ();
?? ?/* relocate environment function pointers etc. */
?? ?env_relocate ();
?? ? * Fill in missing fields of bd_info.
?? ? * We do this here,where we have "normal" access to the
?? ? * environment; we used to do this still running from ROM,
?? ? * where had to use getenv_r(),which can be pretty slow when
?? ? * the environment is in EEPROM.
#ifdef CONFIG_CMD_NET
?? ?/* kept around for legacy kernels only ... ignore the next section */
?? ?eth_getenv_enetaddr("ethaddr",bd->bi_enetaddr);
#endif /* CONFIG_CMD_NET */
?? ?/* IP Address */
?? ?bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
/** leave this here (after malloc(),environment and PCI are working) **/
?? ?/* Initialize stdio devices */
?? ?stdio_init ();
?? ?/* Initialize the jump table for applications */
?? ?jumptable_init ();
?? ?/* Initialize the console (after the relocation and devices init) */
?? ?console_init_r ();
#if defined(CONFIG_MISC_INIT_R)
?? ?/* miscellaneous platform dependent initialisations */
?? ?misc_init_r ();
#endif
?? ?printf ("U-Boot relocated to %08lxn",255)">?? ? * Enable Interrupts
?? ?interrupt_init ();
?? ?/* Must happen after interrupts are initialized since
?? ? * an irq handler gets installed
?? ?udelay (20);
?? ?set_timer (0);
?? ?/* Initialize from environment */
?? ?if ((s = getenv ("loadaddr")) != NULL) {
?? ??? ?load_addr = simple_strtoul (s,NULL,16);
#if defined(CONFIG_CMD_NET)
?? ?if ((s = getenv ("bootfile")) != NULL) {
?? ??? ?copy_filename (BootFile,s,sizeof (BootFile));
#if defined(CONFIG_NET_MULTI)
?? ?puts ("Net:?? ");
?? ?eth_initialize (bd);
?? ?/* Initialization complete - start the monitor */
?? ?/* main_loop() can return to retry autoboot,if so just run it again. */
?? ?for (;;) {
?? ??? ?WATCHDOG_RESET ();
?? ??? ?main_loop ();
?? ?/* NOTREACHED - no way out of command loop except booting */
}
unsigned long flash_init (void)
{
?? ?unsigned long size = 0;
?? ?int i;
#define BANK_BASE(i)?? ?(((phys_addr_t [CFI_MAX_FLASH_BANKS])CONFIG_SYS_FLASH_BANKS_LIST)[i])//获得每个bank基地址
?? ?/* Init: no FLASHes known */
?? ?for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
?? ??? ?flash_info[i].flash_id = FLASH_UNKNOWN;
?? ??? ?if (!flash_detect_legacy (BANK_BASE(i),i))????????????????????????????????????????? //此flash是否遵从CFI协议
?? ??? ??? ?flash_get_size (BANK_BASE(i),i);
?? ??? ?size += flash_info[i].size;??????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? //获得flash大小
?? ?/* Monitor protection ON by default */
#if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) //将所有的uboot代码区域写保护
?? ?flash_protect (FLAG_PROTECT_SET,
?? ??? ??????? CONFIG_SYS_MONITOR_BASE,
?? ??? ??????? CONFIG_SYS_MONITOR_BASE + monitor_flash_len? - 1,
?? ??? ??????? flash_get_info(CONFIG_SYS_MONITOR_BASE));
#endif
?? ?/* Environment protection ON by default */
#ifdef CONFIG_ENV_IS_IN_FLASH
?? ?flash_protect (FLAG_PROTECT_SET,???????????????? //将代码之后的环境变量存储区写保护
?? ??? ??????? CONFIG_ENV_ADDR,
?? ??? ??????? CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
?? ??? ??????? flash_get_info(CONFIG_ENV_ADDR));
#endif
?? ?/* Redundant environment protection ON by default */
#ifdef CONFIG_ENV_ADDR_REDUND
?? ?flash_protect (FLAG_PROTECT_SET,?????????????? //在环境变量之后的保留区域写保护
?? ??? ??????? CONFIG_ENV_ADDR_REDUND,
?? ??? ??????? CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
?? ??? ??????? flash_get_info(CONFIG_ENV_ADDR_REDUND));
#endif
#if defined(CONFIG_SYS_FLASH_AUTOPROTECT_LIST)
?? ?for (i = 0; i < (sizeof(apl) / sizeof(struct apl_s)); i++) {
?? ??? ?debug("autoprotecting from %08x to %08xn",
?? ??? ?????? apl[i].start,apl[i].start + apl[i].size - 1);
?? ??? ?flash_protect (FLAG_PROTECT_SET,
?? ??? ??? ??????? apl[i].start,
?? ??? ??? ??????? apl[i].start + apl[i].size - 1,
?? ??? ??? ??????? flash_get_info(apl[i].start));
?? ?}
#endif
#ifdef CONFIG_FLASH_CFI_MTD
?? ?cfi_mtd_init();
#endif
?? ?return (size);
}
/*
?* The following code cannot be run from FLASH!
?*
?*/
ulong flash_get_size (phys_addr_t base,int banknum)
{
?? ?flash_info_t *info = &flash_info[banknum];
?? ?int i,j;
?? ?flash_sect_t sect_cnt;???????? //块个数
?? ?phys_addr_t sector;? ?
?? ?unsigned long tmp;
?? ?int size_ratio;
?? ?uchar num_erase_regions;
?? ?int erase_region_size;???? //擦除的块大小
?? ?int erase_region_count;? //擦除的块
?? ?struct cfi_qry qry;
?? ?memset(&qry,sizeof(qry));
?? ?info->ext_addr = 0;
?? ?info->cfi_version = 0;
#ifdef CONFIG_SYS_FLASH_PROTECTION
?? ?info->legacy_unlock = 0;
#endif
?? ?info->start[0] = (ulong)map_physmem(base,info->portwidth,MAP_NOCACHE);? //获得flash基地址0xfff0000
?? ?if (flash_detect_cfi (info,&qry)) { ? ? ? ? ? ? ? ? ? ? ???? //端口配置正确并且找到"QRY"标志,符合CFI端,并且读出相应信息
?? ??? ?info->vendor = le16_to_cpu(qry.p_id); ? ? ? ? ? //生产厂商指令集
?? ??? ?info->ext_addr = le16_to_cpu(qry.p_adr);??? //原始拓展表地址
?? ??? ?num_erase_regions = qry.num_erase_regions;
?? ??? ?if (info->ext_addr) {?????????????????????????????????????????? //读取CFI接口版本
?? ??? ??? ?info->cfi_version = (ushort) flash_read_uchar (info,
?? ??? ??? ??? ??? ??? ?info->ext_addr + 3) << 8;
?? ??? ??? ?info->cfi_version |= (ushort) flash_read_uchar (info,
?? ??? ??? ??? ??? ??? ?info->ext_addr + 4);
?? ??? ?}
#ifdef DEBUG
?? ??? ?flash_printqry (&qry);
#endif
?? ??? ?switch (info->vendor) {???????????????????????????????? //按厂商选择相应算法
?? ??? ?case CFI_CMDSET_INTEL_PROG_REGIONS:
?? ??? ?case CFI_CMDSET_INTEL_STANDARD:
?? ??? ?case CFI_CMDSET_INTEL_EXTENDED:
?? ??? ??? ?cmdset_intel_init(info,&qry);
?? ??? ??? ?break;
?? ??? ?case CFI_CMDSET_AMD_STANDARD:
?? ??? ?case CFI_CMDSET_AMD_EXTENDED:
?? ??? ??? ?cmdset_amd_init(info,&qry); ? ? ? ? ? ? //软件复位
?? ??? ??? ?break;
?? ??? ?default:
?? ??? ??? ?printf("CFI: Unknown command set 0x%xn",
?? ??? ??? ??? ??? ?info->vendor);
?? ??? ??? ?/*
?? ??? ??? ? * Unfortunately,this means we don't know how
?? ??? ??? ? * to get the chip back to Read mode. Might
?? ??? ??? ? * as well try an Intel-style reset...
?? ??? ??? ? */
?? ??? ??? ?flash_write_cmd(info,FLASH_CMD_RESET);
?? ??? ??? ?return 0;
?? ??? ?}
?? ??? ?/* Do manufacturer-specific fixups */
?? ??? ?switch (info->manufacturer_id) {
?? ??? ?case 0x0001:
?? ??? ??? ?flash_fixup_amd(info,&qry);????????? //查看厂商flash是否几何反转
?? ??? ??? ?break;
?? ??? ?case 0x001f:
?? ??? ??? ?flash_fixup_atmel(info,&qry);
?? ??? ??? ?break;
?? ??? ?case 0x0020:
?? ??? ??? ?flash_fixup_stm(info,&qry);
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?debug ("manufacturer is %dn",info->vendor);
?? ??? ?debug ("manufacturer id is 0x%xn",info->manufacturer_id);
?? ??? ?debug ("device id is 0x%xn",info->device_id);
?? ??? ?debug ("device id2 is 0x%xn",info->device_id2);
?? ??? ?debug ("cfi version is 0x%04xn",info->cfi_version);
?? ??? ?size_ratio = info->portwidth / info->chipwidth;????????????? //flash由几片构成
?? ??? ?/* if the chip is x8/x16 reduce the ratio by half */
?? ??? ?if ((info->interface == FLASH_CFI_X8X16)?????????????????? //使用x8模式
?? ??? ???? && (info->chipwidth == FLASH_CFI_BY8)) {
?? ??? ??? ?size_ratio >>= 1;
?? ??? ?}
?? ??? ?debug ("size_ratio %d port %d bits chip %d bitsn",
?? ??? ??????? size_ratio,info->portwidth << CFI_FLASH_SHIFT_WIDTH,
?? ??? ??????? info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
?? ??? ?debug ("found %d erase regionsn",num_erase_regions);
?? ??? ?sect_cnt = 0;
?? ??? ?sector = base;
?? ??? ?for (i = 0; i < num_erase_regions; i++) { //获得该片flash最大可用block数
?? ??? ??? ?if (i > NUM_ERASE_REGIONS) {
?? ??? ??? ??? ?printf ("%d erase regions found,only %d usedn",
?? ??? ??? ??? ??? ?num_erase_regions,NUM_ERASE_REGIONS);
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?tmp = le32_to_cpu(qry.erase_region_info[i]);
?? ??? ??? ?debug("erase region %u: 0x%08lxn",i,tmp);
?? ??? ??? ?erase_region_count = (tmp & 0xffff) + 1;
?? ??? ??? ?tmp >>= 16;
?? ??? ??? ?erase_region_size =
?? ??? ??? ??? ?(tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;//获得块大小
?? ??? ??? ?debug ("erase_region_count = %d erase_region_size = %dn",
?? ??? ??? ??? ?erase_region_count,erase_region_size);
?? ??? ??? ?for (j = 0; j < erase_region_count; j++) {
?? ??? ??? ??? ?if (sect_cnt >= CONFIG_SYS_MAX_FLASH_SECT) {?? //所有的block 数,为4block
?? ??? ??? ??? ??? ?printf("ERROR: too many flash sectorsn");
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?info->start[sect_cnt] =
?? ??? ??? ??? ??? ?(ulong)map_physmem(sector,
?? ??? ??? ??? ??? ??? ??? ??? info->portwidth,
?? ??? ??? ??? ??? ??? ??? ??? MAP_NOCACHE);
?? ??? ??? ??? ?sector += (erase_region_size * size_ratio);//该bank中所有sector
?? ??? ??? ??? ?/*
?? ??? ??? ??? ? * Only read protection status from
?? ??? ??? ??? ? * supported devices (intel...)
?? ??? ??? ??? ? */
?? ??? ??? ??? ?switch (info->vendor) {???? //按厂商查看保护快
?? ??? ??? ??? ?case CFI_CMDSET_INTEL_PROG_REGIONS:
?? ??? ??? ??? ?case CFI_CMDSET_INTEL_EXTENDED:
?? ??? ??? ??? ?case CFI_CMDSET_INTEL_STANDARD:
?? ??? ??? ??? ??? ?info->protect[sect_cnt] =
?? ??? ??? ??? ??? ??? ?flash_isset (info,sect_cnt,
?? ??? ??? ??? ??? ??? ??? ????? FLASH_OFFSET_PROTECT,
?? ??? ??? ??? ??? ??? ??? ????? FLASH_STATUS_PROTECT);
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?default:???????????????????????????? //AMD默认不写保护
?? ??? ??? ??? ??? ?/* default: not protected */
?? ??? ??? ??? ??? ?info->protect[sect_cnt] = 0;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?sect_cnt++;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?info->sector_count = sect_cnt;
?? ??? ?info->size = 1 << qry.dev_size;? //获得该chip的大小
?? ??? ?/* multiply the size by the number of chips */
?? ??? ?info->size *= size_ratio;?????? //计算该bank容量
?? ??? ?info->buffer_size = 1 << le16_to_cpu(qry.max_buf_write_size); //获得最大写buffer
?? ??? ?tmp = 1 << qry.block_erase_timeout_typ;
?? ??? ?info->erase_blk_tout = tmp *
?? ??? ??? ?(1 << qry.block_erase_timeout_max);//块擦除时间
?? ??? ?tmp = (1 << qry.buf_write_timeout_typ) *
?? ??? ??? ?(1 << qry.buf_write_timeout_max);//写buffer时间
?? ??? ?/* round up when converting to ms */
?? ??? ?info->buffer_write_tout = (tmp + 999) / 1000;
?? ??? ?tmp = (1 << qry.word_write_timeout_typ) *
?? ??? ??? ?(1 << qry.word_write_timeout_max);
?? ??? ?/* round up when converting to ms */
?? ??? ?info->write_tout = (tmp + 999) / 1000;
?? ??? ?info->flash_id = FLASH_MAN_CFI;
?? ??? ?if ((info->interface == FLASH_CFI_X8X16) &&
?? ??? ???? (info->chipwidth == FLASH_CFI_BY8)) {
?? ??? ??? ?/* XXX - Need to test on x8/x16 in parallel. */
?? ??? ??? ?info->portwidth >>= 1;
?? ??? ?}
?? ??? ?flash_write_cmd (info,info->cmd_reset);//复位
?? ?}
?? ?return (info->size);
}
块擦写函数很简单
int flash_erase (flash_info_t * info,int s_first,int s_last)
{
?int rcode = 0;
?int prot;
?flash_sect_t sect;
?if (info->flash_id != FLASH_MAN_CFI) {????????//未知ID
??puts ("Can't erase unknown flash type - abortedn");
??return 1;
?}
?if ((s_first < 0) || (s_first > s_last)) {
??puts ("- no sectors to erasen");
??return 1;
?}
?prot = 0;
?for (sect = s_first; sect <= s_last; ++sect) {?//查找保护的块
??if (info->protect[sect]) {
???prot++;
??}
?}
?if (prot) {
??printf ("- Warning: %d protected sectors will not be erased!n",
???prot);
?} else if (flash_verbose) {
??putc ('n');
?}
?for (sect = s_first; sect <= s_last; sect++) {?? 对没有保护的块按不同的厂商选择算法
??if (info->protect[sect] == 0) { /* not protected */
???switch (info->vendor) {
???case CFI_CMDSET_INTEL_PROG_REGIONS:
???case CFI_CMDSET_INTEL_STANDARD:
???case CFI_CMDSET_INTEL_EXTENDED:
????flash_write_cmd (info,sect,
?????? FLASH_CMD_CLEAR_STATUS);
????flash_write_cmd (info,
?????? FLASH_CMD_BLOCK_ERASE);
????flash_write_cmd (info,
?????? FLASH_CMD_ERASE_CONFIRM);
????break;
???case CFI_CMDSET_AMD_STANDARD: //我们使用的是这个算法
???case CFI_CMDSET_AMD_EXTENDED:??????
? ?flash_unlock_seq (info,sect);??????????????? ?//写入指令
????flash_write_cmd (info,
??????info->addr_unlock1,
??????AMD_CMD_ERASE_START);
????flash_unlock_seq (info,sect);
????flash_write_cmd (info,
?????? AMD_CMD_ERASE_SECTOR);
????break;
#ifdef CONFIG_FLASH_CFI_LEGACY???//如果定义了后续算法,使用默认算法
???case CFI_CMDSET_AMD_LEGACY:
????flash_unlock_seq (info,0);
????flash_write_cmd (info,info->addr_unlock1,
??????AMD_CMD_ERASE_SECTOR);
????break;
#endif
???default:
????debug ("Unkown flash vendor %dn",
?????????? info->vendor);
????break;
???}
???if (flash_full_status_check???????????????????????????//检测是否已经擦除
?????? (info,info->erase_blk_tout,"erase")) {?
????rcode = 1;
???} else if (flash_verbose)
????putc ('.');
??}
?}
?if (flash_verbose)?????????????????????????????????????????
??puts (" donen");
?return rcode; }