⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ar9100_pflash.c

📁 TP-LINK公司TL-WR941N无线路由器的Bootloader U_BOOT源代码
💻 C
字号:
#include <common.h>#include <jffs2/jffs2.h>#include <asm/addrspace.h>#include <asm/types.h>#include "ar7100_soc.h"//----------------------------------------------------------------------------// Common device details.#define FLASHWORD(_x)			((CFG_FLASH_WORD_SIZE)(_x))#define FLASH_Read_ID                   FLASHWORD( 0x90 )#define FLASH_Read_ID_Exit              FLASHWORD( 0xF0 )#define FLASH_Reset                     FLASHWORD( 0xFF )#define FLASH_Program                   FLASHWORD( 0xA0 )#define FLASH_Block_Erase               FLASHWORD( 0x30 )#define FLASH_Data                      FLASHWORD( 0x80 )	// Data complement#define FLASH_Busy                      FLASHWORD( 0x44 )	// "Toggle" bit#define FLASH_Err                       FLASHWORD( 0x20 )#define FLASH_Sector_Erase_Timer        FLASHWORD( 0x08 )#define FLASH_Setup_Code1               FLASHWORD( 0xAA )#define FLASH_Setup_Code2               FLASHWORD( 0x55 )#define FLASH_Setup_Erase               FLASHWORD( 0x80 )#define AMD_SPANSION			0x227e#define VENDOR_ID(x)			(ushort) ((x & 0x00ff0000) >> 16)#define DEVICE_ID(x)			(ushort) (x & 0x0000ffff)/* * globals */flash_info_t flash_info[CFG_MAX_FLASH_BANKS];typedef struct ar9100_flash_geom {    ushort vendor_id;    ushort device_id;    char *name;    ulong nsectors;    ulong sector_size;    ulong size;} ar9100_flash_geom_t;ar9100_flash_geom_t flash_geom_tbl[] = {    {0x00bf, 0x2780, "SST-39VF400", 8, 0x01000, 0x080000},	/* 512 KB */    {0x00bf, 0x2782, "SST-39VF160", 32, 0x01000, 0x200000},	/* 2 MB   */    {0x00bf, 0x236b, "SST-39VF6401", 128, 0x01000, 0x800000},	/* 8 MB   */    {0x00bf, 0x236a, "SST-39VF6402", 128, 0x01000, 0x800000},	/* 8 MB   */    {0x00bf, 0x236d, "SST-39VF6402", 128, 0x01000, 0x800000},	/* 8 MB   */    {0x0001, 0x227e, "AMD-SPANSION", 128, 0x02000, 0x1000000},	/* 16 MB  */    {0xffff, 0xffff, NULL, 0, 0}	/* end list */};/* * statics */static int write_word(flash_info_t * info, ulong dest, ulong data);static ulong read_id(void);unsigned long flash_init(void){    ulong sector_size;    ar9100_flash_geom_t *geom;    ushort venid, devid;    int i;    flash_info->flash_id = read_id();    venid = VENDOR_ID(flash_info->flash_id);    devid = DEVICE_ID(flash_info->flash_id);    for (i = 0; flash_geom_tbl[i].name != NULL; i++) {        if (venid == flash_geom_tbl[i].vendor_id &&            devid == flash_geom_tbl[i].device_id) {            break;        }    }    geom = &flash_geom_tbl[i];    if (geom->name == NULL) {        printf("Unknown flash device\n");        return -1;    }    flash_info->size = geom->size;	/* bytes */    flash_info->sector_count = geom->nsectors;    sector_size = (geom->sector_size * 16); /* One Erase block size */    for (i = 0; i < flash_info->sector_count; i++) {        flash_info->start[i] = CFG_FLASH_BASE + (i * sector_size);        flash_info->protect[i] = 0;    }    flash_print_info(flash_info);    return (flash_info->size);}void flash_print_info(flash_info_t * info){    printf("Name: ");    switch (DEVICE_ID(info->flash_id))    {    case 0x2780: printf ("SST-39VF400");            break;    case 0x2782: printf ("SST-39VF160");            break;    case 0x236b: printf ("SST-39VF6401");           break;    case 0x236a: printf ("SST-39VF6402");           break;    case 0x236d: printf ("SST-39VF6402");           break;    case 0x227e: printf ("AMD-SPANSION");           break;    default:     printf ("Unknown Vendor ");        break;    }    printf(" Flash id: 0x%X, Size: %lu bytes.\n", info->flash_id, info->size);}int flash_erase(flash_info_t * info, int s_first, int s_last){    int i = s_first;    volatile CFG_FLASH_WORD_SIZE *ROM =        (volatile CFG_FLASH_WORD_SIZE *) (info->start[0]);    int timeout;    printf("First %#x last %#x\n", s_first, s_last);    for (i = s_first; i <= s_last; i++) {        CFG_FLASH_WORD_SIZE state, prev_state, rd_data;        volatile CFG_FLASH_WORD_SIZE *addr_ptr =            (volatile CFG_FLASH_WORD_SIZE *) (info->start[i]);        // Program data [byte] - 6 step sequence        ROM[CFG_FLASH_ADDR0] = FLASH_Setup_Code1;        ROM[CFG_FLASH_ADDR1] = FLASH_Setup_Code2;        ROM[CFG_FLASH_ADDR0] = FLASH_Setup_Erase;        ROM[CFG_FLASH_ADDR0] = FLASH_Setup_Code1;        ROM[CFG_FLASH_ADDR1] = FLASH_Setup_Code2;        *addr_ptr = FLASH_Block_Erase;        printf("\b\b\b\b\b %3d\%",(( ((i-s_first) + 1) * 100) / ((s_last-s_first) + 1 )) );        if (DEVICE_ID(flash_info->flash_id) == AMD_SPANSION) {            // Wait for erase completion.            timeout = 10000000;            while (timeout) {		state = *addr_ptr;		if (FLASHWORD(0xffff) == state) {	    		break;		}		timeout--;            }        } else {            // Wait for completion (bit 6 stops toggling)            timeout = 5000000;            prev_state = *addr_ptr & FLASH_Busy;            while (timeout) {		rd_data = *addr_ptr;		state = rd_data & FLASH_Busy;		if ((prev_state == state) && (rd_data == FLASHWORD(0xffff))) {	    		break;	}	timeout--;	prev_state = state;            }        }        if (!timeout){	    printf("Error erasing flash...\n");            return -1;        }    }        printf("\n");    return 0;}/* * Copy memory to flash, returns: * Assumption: Caller has already erased the appropriate sectors. * 0 - OK * 1 - write timeout */int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt){    ulong cp, wp, data;    int i, l, rc, j=0, count;    wp = (addr & ~3);   /* get lower word aligned address */    count=cnt;    printf("\n");    /*     * handle unaligned start bytes     */    if ((l = addr - wp) != 0) {        data = 0;        for (i = 0, cp = wp; i < l; ++i, ++cp) {            data = (data << 8) | (*(uchar *) cp);        }        for (; i < 4 && cnt > 0; ++i) {            data = (data << 8) | *src++;            --cnt;            ++cp;        }        for (; cnt == 0 && i < 4; ++i, ++cp) {            data = (data << 8) | (*(uchar *) cp);        }        if ((rc = write_word(info, wp, data)) != 0) {            return (rc);        }	j = j + 4;        wp += 4;    }    /*     * handle word aligned part     */    while (cnt >= 4) {        data = 0;        for (i = 0; i < 4; ++i) {            data = (data << 8) | *src++;        }        if(!(j%1024))	   printf("\b\b\b\b\b %3d\%",((j * 100) / count));        if ((rc = write_word(info, wp, data)) != 0) {            return (rc);        }        wp += 4;        cnt -= 4;        j += 4;    }    printf("\b\b\b\b\b %3d\%\n",(((j + 4) * 100 ) / count));    if (cnt == 0) {        return (0);    }    /*     * handle unaligned tail bytes     */    data = 0;    for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {        data = (data << 8) | *src++;        --cnt;    }    for (; i < 4; ++i, ++cp) {        data = (data << 8) | (*(uchar *) cp);    }    return (write_word(info, wp, data));}static int write_word(flash_info_t * info, ulong dest, ulong data){    volatile CFG_FLASH_WORD_SIZE *ROM =        (CFG_FLASH_WORD_SIZE *) (info->start[0]);    volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *) dest;    CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *) & data;    int i;    /* Check if Flash is (sufficiently) erased */    if ((*((vu_long *) dest) & data) != data) {        return (2);    }    for (i = 0; i < 4 / sizeof(CFG_FLASH_WORD_SIZE); i++) {        CFG_FLASH_WORD_SIZE state, prev_state;        int timeout;        ROM[CFG_FLASH_ADDR0] = FLASH_Setup_Code1;        ROM[CFG_FLASH_ADDR1] = FLASH_Setup_Code2;        ROM[CFG_FLASH_ADDR0] = FLASH_Program;        dest2[i] = data2[i];        if (DEVICE_ID(flash_info->flash_id) == AMD_SPANSION) {            timeout = 10000000;            while (timeout) {		if (dest2[i] == data2[i]) {	   		 break;		}		timeout--;            }        } else {            // Wait for completion (bit 6 stops toggling)            timeout = 5000000;            prev_state = dest2[i] & FLASH_Busy;            while (timeout) {		state = dest2[i] & FLASH_Busy;		if (prev_state == state) {	    		break;		}		timeout--;		prev_state = state;            }        }        if (!timeout) {		printf("Error while Writing into flash...\n");            return -1;	}    }    return (0);}static ulong read_id(){    volatile CFG_FLASH_WORD_SIZE *ROM;    ulong id;    ROM = (volatile CFG_FLASH_WORD_SIZE *) CFG_FLASH_BASE;    ROM[CFG_FLASH_ADDR0] = FLASH_Setup_Code1;    ROM[CFG_FLASH_ADDR1] = FLASH_Setup_Code2;    ROM[CFG_FLASH_ADDR0] = FLASH_Read_ID;    udelay(10000);    id = ROM[0];    id = (id << 16) | (ROM[1] & 0xffff);    ROM[CFG_FLASH_ADDR0] = FLASH_Setup_Code1;    ROM[CFG_FLASH_ADDR1] = FLASH_Setup_Code2;    ROM[CFG_FLASH_ADDR0] = FLASH_Read_ID_Exit;    udelay(10000);    return id;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -