zoukankan      html  css  js  c++  java
  • u-boot nor flash 初始化过程

    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
  • 相关阅读:
    Linux Linux程序练习九
    Linux 进程与线程四(加锁--解锁)
    Linux 进程与线程三(线程比较--创建线程参数)
    Linux 进程与线程二(等待--分离--取消线程)
    Linux 进程与线程一(创建-关闭线程)
    python值传递和指针传递
    Django-Model操作数据库(增删改查、连表结构)
    django model 插入数据方法
    jQuery ajax()使用serialize()提交form数据
    python版 google密码认证器
  • 原文地址:https://www.cnblogs.com/idyllcheung/p/14134727.html
Copyright © 2011-2022 走看看