board_init_r
initr_flash
flash_init
cfi_flash_init_dm
cfi_flash_probe (会设置flash_info.dev和flash_info.base)
flash_get_size
flash_detect_cfi
__flash_detect_cfi
initr_flash
#if defined(CONFIG_MTD_NOR_FLASH) static int initr_flash(void) { ulong flash_size = 0; bd_t *bd = gd->bd; puts("Flash: "); if (board_flash_wp_on()) printf("Uninitialized - Write Protect On "); else flash_size = flash_init(); print_size(flash_size, ""); #ifdef CONFIG_SYS_FLASH_CHECKSUM /* * Compute and print flash CRC if flashchecksum is set to 'y' * * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX */ if (env_get_yesno("flashchecksum") == 1) { const uchar *flash_base = (const uchar *)CONFIG_SYS_FLASH_BASE; printf(" CRC: %08X", crc32(0, flash_base, flash_size)); } #endif /* CONFIG_SYS_FLASH_CHECKSUM */ putc(' '); /* update start of FLASH memory */ #ifdef CONFIG_SYS_FLASH_BASE bd->bi_flashstart = CONFIG_SYS_FLASH_BASE; #endif /* size of FLASH memory (final value) */ bd->bi_flashsize = flash_size; #if defined(CONFIG_SYS_UPDATE_FLASH_SIZE) /* Make a update of the Memctrl. */ update_flash_size(flash_size); #endif #if defined(CONFIG_OXC) || defined(CONFIG_RMU) /* flash mapped at end of memory map */ bd->bi_flashoffset = CONFIG_SYS_TEXT_BASE + flash_size; #elif CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE bd->bi_flashoffset = monitor_flash_len; /* reserved area for monitor */ #endif return 0; } #endif
__weak int board_flash_wp_on(void) { /* * Most flashes can't be detected when write protection is enabled, * so provide a way to let U-Boot gracefully ignore write protected * devices. */ return 0; }
flash_get_size
if (!flash_detect_legacy(cfi_flash_bank_addr(i), i)) flash_get_size(cfi_flash_bank_addr(i), i);
#ifdef CONFIG_FLASH_CFI_LEGACY static int flash_detect_legacy(phys_addr_t base, int banknum) { flash_info_t *info = &flash_info[banknum]; } #else static inline int flash_detect_legacy(phys_addr_t base, int banknum) { return 0; /* use CFI */ } #endif
flash_get_size(cfi_flash_bank_addr(i), i);
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; unsigned long max_size; memset(&qry, 0, sizeof(qry)); //qry清零
if (flash_detect_cfi(info, &qry))
flash_detect_cfi(info, &qry)
/* * Values for the width of the port */ #define FLASH_CFI_8BIT 0x01 #define FLASH_CFI_16BIT 0x02 #define FLASH_CFI_32BIT 0x04 #define FLASH_CFI_64BIT 0x08 /* * Values for the width of the chip */ #define FLASH_CFI_BY8 0x01 #define FLASH_CFI_BY16 0x02 #define FLASH_CFI_BY32 0x04 #define FLASH_CFI_BY64 0x08
static int flash_detect_cfi(flash_info_t *info, struct cfi_qry *qry) { debug("flash detect cfi "); for (info->portwidth = CONFIG_SYS_FLASH_CFI_WIDTH; //FLASH_CFI_8BIT 0x01 info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) { //0x08 for (info->chipwidth = FLASH_CFI_BY8; //0x01 info->chipwidth <= info->portwidth; info->chipwidth <<= 1) if (__flash_detect_cfi(info, qry)) return 1; } debug("not found "); return 0; }
Assuming the system has 4 flash chips, and each flash chip is 16 bits witdh.
So, the portwidth is 64bits, that is 4 *16. the chipwidth is 16bits.
Looks up some flash datasheet, you will perfect know what is the meaning.
__flash_detect_cfi(info, qry)
static int __flash_detect_cfi(flash_info_t *info, struct cfi_qry *qry) { int cfi_offset; /* Issue FLASH reset command */ flash_cmd_reset(info);
//static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT };
//{0x55 0x555}
for (cfi_offset = 0; cfi_offset < ARRAY_SIZE(flash_offset_cfi); cfi_offset++) { flash_write_cmd(info, 0, flash_offset_cfi[cfi_offset], FLASH_CMD_CFI);//0x98 if (flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP, 'Q') && flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') && flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) { flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP, sizeof(struct cfi_qry)); info->interface = le16_to_cpu(qry->interface_desc); info->cfi_offset = flash_offset_cfi[cfi_offset]; debug("device interface is %d ", info->interface); debug("found port %d chip %d ", info->portwidth, info->chipwidth); debug("port %d bits chip %d bits ", info->portwidth << CFI_FLASH_SHIFT_WIDTH, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); /* calculate command offsets as in the Linux driver */ info->addr_unlock1 = 0x555; info->addr_unlock2 = 0x2aa; /* * modify the unlock address if we are * in compatibility mode */ if (/* x8/x16 in x8 mode */ (info->chipwidth == FLASH_CFI_BY8 && info->interface == FLASH_CFI_X8X16) || /* x16/x32 in x16 mode */ (info->chipwidth == FLASH_CFI_BY16 && info->interface == FLASH_CFI_X16X32)) { info->addr_unlock1 = 0xaaa; info->addr_unlock2 = 0x555; } info->name = "CFI conformant"; return 1; } } return 0; }
flash_cmd_reset
void flash_cmd_reset(flash_info_t *info) __attribute__((weak, alias("__flash_cmd_reset"))); static void __flash_cmd_reset(flash_info_t *info) { /* * We do not yet know what kind of commandset to use, so we issue * the reset command in both Intel and AMD variants, in the hope * that AMD flash roms ignore the Intel command. */ flash_write_cmd(info, 0, 0, AMD_CMD_RESET);//0xF0 udelay(1); flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);//0xFF }
flash_write_cmd
/* * Write a proper sized command to the correct address */ static void flash_write_cmd(flash_info_t *info, flash_sect_t sect, uint offset, u32 cmd) { void *addr; cfiword_t cword; addr = flash_map(info, sect, offset); flash_make_cmd(info, cmd, &cword); switch (info->portwidth) { case FLASH_CFI_8BIT: debug("fwc addr %p cmd %x %x 8bit x %d bit ", addr, cmd, cword.w8, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); flash_write8(cword.w8, addr); break; case FLASH_CFI_16BIT: debug("fwc addr %p cmd %x %4.4x 16bit x %d bit ", addr, cmd, cword.w16, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); flash_write16(cword.w16, addr); break; case FLASH_CFI_32BIT: debug("fwc addr %p cmd %x %8.8x 32bit x %d bit ", addr, cmd, cword.w32, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); flash_write32(cword.w32, addr); break; case FLASH_CFI_64BIT: #ifdef DEBUG { char str[20]; print_longlong(str, cword.w64); debug("fwrite addr %p cmd %x %s 64 bit x %d bit ", addr, cmd, str, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); } #endif flash_write64(cword.w64, addr); break; } /* Ensure all the instructions are fully finished */ sync(); flash_unmap(info, sect, offset, addr); }
flash_map
/*----------------------------------------------------------------------- * create an address based on the offset and the port width */ static inline void * flash_map(flash_info_t *info, flash_sect_t sect, uint offset) { unsigned int byte_offset = offset * info->portwidth; return (void *)(info->start[sect] + byte_offset); }
flash_make_cmd
/*----------------------------------------------------------------------- * make a proper sized command based on the port and chip widths */ static void flash_make_cmd(flash_info_t *info, u32 cmd, void *cmdbuf) { int i; int cword_offset; int cp_offset; #if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA) u32 cmd_le = cpu_to_le32(cmd); #endif uchar val; uchar *cp = (uchar *) cmdbuf; for (i = info->portwidth; i > 0; i--) { cword_offset = (info->portwidth - i) % info->chipwidth; #if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA) cp_offset = info->portwidth - i; val = *((uchar *)&cmd_le + cword_offset); #else cp_offset = i - 1; val = *((uchar *)&cmd + sizeof(u32) - cword_offset - 1); #endif cp[cp_offset] = (cword_offset >= sizeof(u32)) ? 0x00 : val; } }
0x98--> 0x9898 (portwidth=16)
flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP, 'Q') //0x10 Q
flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')//0x11 R
flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')//0x12 Y
static int flash_isequal(flash_info_t *info, flash_sect_t sect, uint offset, uchar cmd) { void *addr; cfiword_t cword; int retval; addr = flash_map(info, sect, offset); flash_make_cmd(info, cmd, &cword); debug("is= cmd %x(%c) addr %p ", cmd, cmd, addr); switch (info->portwidth) { case FLASH_CFI_8BIT: debug("is= %x %x ", flash_read8(addr), cword.w8); retval = (flash_read8(addr) == cword.w8); break; case FLASH_CFI_16BIT: debug("is= %4.4x %4.4x ", flash_read16(addr), cword.w16); retval = (flash_read16(addr) == cword.w16); break; case FLASH_CFI_32BIT: debug("is= %8.8x %8.8x ", flash_read32(addr), cword.w32); retval = (flash_read32(addr) == cword.w32); break; case FLASH_CFI_64BIT: #ifdef DEBUG { char str1[20]; char str2[20]; print_longlong(str1, flash_read64(addr)); print_longlong(str2, cword.w64); debug("is= %s %s ", str1, str2); } #endif retval = (flash_read64(addr) == cword.w64); break; default: retval = 0; break; } flash_unmap(info, sect, offset, addr); return retval; }
flash_write_cmd和flash_isequal打印信息
8bit x 8 bit
debug("fwc addr %p cmd %x %x 8bit x %d bit ", addr, cmd, cword.w8, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); flash detect cfi //flash_detect_cfi开头debug fwc addr e2000000 cmd f0 f0 8bit x 8 bit //flash_cmd_reset fwc addr e2000000 cmd ff ff 8bit x 8 bit //flash_cmd_reset fwc addr e2000055 cmd 98 98 8bit x 8 bit
//static void flash_write_cmd(flash_info_t *info, flash_sect_t sect, // uint offset, u32 cmd)
//flash_write_cmd(info, 0, flash_offset_cfi[cfi_offset],FLASH_CMD_CFI); //0x55 0x98
is= cmd 51(Q) addr e2000010 is= ff 51
debug("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
debug("is= %x %x ", flash_read8(addr), cword.w8);
fwc addr e2000555 cmd 98 98 8bit x 8 bit //flash_write_cmd(info, 0, flash_offset_cfi[cfi_offset],FLASH_CMD_CFI); //0x555 0x98
is= cmd 51(Q) addr e2000010 is= ff 51
16bit x 8 bit
fwc addr e2000000 cmd f0 f0f0 16bit x 8 bit//flash_cmd_reset
fwc addr e2000000 cmd ff ffff 16bit x 8 bit//flash_cmd_reset
fwc addr e20000aa cmd 98 9898 16bit x 8 bit //0xe20000aa 16bit 写入9898
//static void flash_write_cmd(flash_info_t *info, flash_sect_t sect, // uint offset, u32 cmd)
//flash_write_cmd(info, 0, flash_offset_cfi[cfi_offset],FLASH_CMD_CFI); //0x55 0x98
//portwidth 16bit chipwidth 8bit, 0x55*2 0x98-->0x9898
is= cmd 51(Q) addr e2000020 is= 5151 5151 //0xe2000020 16bit 读出
is= cmd 52(R) addr e2000022 is= 5252 5252 is= cmd 59(Y) addr e2000024 is= 5959 5959 device interface is 2