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

📄 sflash.c

📁 em86xx 完整启动程序,支持网络下载与串通下载
💻 C
字号:
/***************************************** Copyright (c) 2003-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the EM86XX boot loader *//* * sflash.c * * Serial Flash support * * by Ho Lee 02/04/2003 */#include "config.h"#include "uart.h"#include "io.h"#include "util.h"#include "hardware.h"#include "em86xxapi.h"#include "sflash.h"//// Serial Flash model information//static struct {    int model;      sflash_op_t *pop;    sflash_db_t *pdb;} s_sflash_info = {    -1,     NULL,    NULL};//// Serial Flash operations// extern sflash_op_t g_sflash_op_sst;extern sflash_op_t g_sflash_op_st_m25;extern sflash_op_t g_sflash_op_st_m95;static sflash_op_t *g_sflash_op_list[] = {#ifdef CONFIG_ENABLE_SFLASH_SST    &g_sflash_op_sst,#endif#ifdef CONFIG_ENABLE_SFLASH_ST_M25    &g_sflash_op_st_m25,#endif#ifdef CONFIG_ENABLE_SFLASH_ST_M95    &g_sflash_op_st_m95,#endif    NULL};//// Primitive functions//static int s_chipselect_nested = 0;void sflash_chipselect(void){    if (s_chipselect_nested++ == 0)        __raw_writel(1, REG_BASE_HOST + SFLA_chip_select);}void sflash_chipdeselect(void){    if (--s_chipselect_nested == 0)        __raw_writel(1, REG_BASE_HOST + SFLA_chip_deselect);}void sflash_sendcommand(unsigned int cmd){    __raw_writeb(cmd, REG_BASE_HOST + SFLA_send_8);}unsigned char sflash_readb(void){    __raw_writeb(0, REG_BASE_HOST + SFLA_send_get_8);       // send stuff bits and get #ifdef CONFIG_ARCH_TANGO    // In Tango, these operations are asynchronous    // wait until 'B' bit is cleared    while (__raw_readl(REG_BASE_HOST + SFLA_status) & 0x01)        ;#endif    return __raw_readb(REG_BASE_HOST + SFLA_read_data); // read result}void sflash_writeb(unsigned int data){    __raw_writeb(data, REG_BASE_HOST + SFLA_send_8);}unsigned short sflash_readw(void){    __raw_writew(0, REG_BASE_HOST + SFLA_send_get_16);  // send stuff bits and get #ifdef CONFIG_ARCH_TANGO    while (__raw_readl(REG_BASE_HOST + SFLA_status) & 0x01)        ;#endif    return __raw_readw(REG_BASE_HOST + SFLA_read_data); // read result}void sflash_writew(unsigned int data){    __raw_writew(data, REG_BASE_HOST + SFLA_send_16);}unsigned int sflash_readl(void){    __raw_writel(0, REG_BASE_HOST + SFLA_send_get_32);  // send stuff bits and get #ifdef CONFIG_ARCH_TANGO    while (__raw_readl(REG_BASE_HOST + SFLA_status) & 0x01)        ;#endif    return __raw_readl(REG_BASE_HOST + SFLA_read_data); // read result}void sflash_writel(unsigned int data){#if defined(CONFIG_ARCH_TANGO) && (CONFIG_ARCH_TANGO10_REV == 1)    // In Tango, SFLA_send_32 seems broken    // use SFLA_send_16 instead    __raw_writel((data >> 16) & 0xffff, REG_BASE_HOST + SFLA_send_16);    __raw_writel((data >> 0) & 0xffff, REG_BASE_HOST + SFLA_send_16);#else    __raw_writel(data, REG_BASE_HOST + SFLA_send_32);#endif}void sflash_setparam(unsigned int data_param, unsigned int data_speed, int verbose){    unsigned int data;#ifdef CONFIG_ARCH_TANGO    __raw_writel(1, REG_BASE_HOST + SFLA_drive_pads);#endif    // try to setup parameter for serial flash    data = __raw_readl(REG_BASE_HOST + SFLA_read_parameters);    if (data != data_param) {        if (verbose)            uart_printf("  Set Serial Flash Parameter : 0x%08x => 0x%08x\n", data, data_param);        __raw_writel(data_param, REG_BASE_HOST + SFLA_read_parameters);    }    data = __raw_readl(REG_BASE_HOST + SFLA_driver_speed);    if (data != data_speed) {        if (verbose)            uart_printf("  Set Serial Flash Timing : 0x%08x => 0x%08x\n", data, data_speed);        __raw_writel(data_speed, REG_BASE_HOST + SFLA_driver_speed);    }}//// Common Functions// void sflash_chiperase(void){    sflash_op_t *pop = s_sflash_info.pop;    sflash_db_t *pdb = s_sflash_info.pdb;    if (pop) {        pop->chiperase(pdb);    }}void sflash_sectorerase(unsigned int addr){    sflash_op_t *pop = s_sflash_info.pop;    sflash_db_t *pdb = s_sflash_info.pdb;    if (pop) {        pop->sectorerase(pdb, addr);    }}void sflash_pageprogram(unsigned int addr, unsigned char *data, int len){    sflash_op_t *pop = s_sflash_info.pop;    sflash_db_t *pdb = s_sflash_info.pdb;    if (pop) {        pop->pageprogram(pdb, addr, data, len);    }}// // Advanced Functions//// return 0 or positive value if serial flash found, otherwise negative valueint sflash_force(const char *name){    int i;    sflash_op_t **pop_list;    sflash_db_t *pdb_list;    for (pop_list = g_sflash_op_list; *pop_list != NULL; ++pop_list) {        pdb_list = (*pop_list)->sflash_list;        for (i = 0; pdb_list->size; ++i, ++pdb_list) {            if (strcasecmp(pdb_list->name, name) == 0) {                s_sflash_info.pop = *pop_list;                s_sflash_info.pdb = pdb_list;                s_sflash_info.model = i;                (*pop_list)->setparam(pdb_list, 1);                sflash_showinfo();                return s_sflash_info.model;            }        }    }    return -1;}void sflash_show_supportlist(void){    sflash_op_t **pop_list;    sflash_db_t *pdb_list;    for (pop_list = g_sflash_op_list; *pop_list != NULL; ++pop_list) {        uart_printf("Class : %s\n", (*pop_list)->name);        for (pdb_list = (*pop_list)->sflash_list; pdb_list->size; ++pdb_list) {            uart_printf("  %s : ", pdb_list->name);            if (pdb_list->size > 0x400)                uart_printf("%dKB\n", pdb_list->size >> 10);            else                uart_printf("%d Bytes\n", pdb_list->size);        }    }}// return 0 or positive value if serial flash found, otherwise negative valueint sflash_detect(int verbose){    int i;    for (i = 0; g_sflash_op_list[i] != NULL; ++i)        if ((s_sflash_info.model = g_sflash_op_list[i]->detect(&s_sflash_info.pop, &s_sflash_info.pdb, verbose)) >= 0)            break;    sflash_showinfo();    return s_sflash_info.model;}int sflash_exist(void){    return (s_sflash_info.model >= 0) ? 1 : 0;}void sflash_showinfo(void){    if (s_sflash_info.model >= 0) {        uart_printf("Serial Flash model %s ", s_sflash_info.pdb->name);        if (s_sflash_info.pdb->size >= 0x400)            uart_printf("(%dKB)\n", s_sflash_info.pdb->size >> 10);        else            uart_printf("(%d Bytes)\n", s_sflash_info.pdb->size);    } else        uart_puts("Serial Flash not found\n");}unsigned int sflash_getsize(void){    sflash_db_t *pdb = s_sflash_info.pdb;    return pdb ? pdb->size : 0;}int sflash_calcblock(unsigned int addr, unsigned int *pstart, unsigned int *pend){    int i;    unsigned int start = 0, end = 0;    sflash_db_t *pdb = s_sflash_info.pdb;    *pstart = 0;    *pend = 0;        if (s_sflash_info.model >= 0) {        for (i = 0; i < pdb->nsector; ++i) {            end += pdb->sectorsize;            if (addr >= start && addr < end) {                *pstart = start;                *pend = end;                return 0;            }            start += pdb->sectorsize;        }    }    return -1;}int sflash_calcblockrange(unsigned int addr, int len, unsigned int *pstart, unsigned int *pend){    unsigned int dummy;    if (sflash_calcblock(addr, pstart, &dummy) == 0)        if (sflash_calcblock(addr + len - 1, &dummy, pend) == 0)            return 0;    return -1;}int sflash_writable(unsigned int addr, int len){    int i;    for (i = 0; i < len; ++i) {        if (((unsigned char *) (LOADER_SFLASHBASE + addr))[i] != 0xff)            return 0;    }    return 1;}void sflash_readdata(unsigned int addr, unsigned char *data, int len){    sflash_op_t *pop = s_sflash_info.pop;    sflash_db_t *pdb = s_sflash_info.pdb;    if (pop)        pop->read(pdb, addr, data, len);}void sflash_erasedata(unsigned int addr, int len){    unsigned int start, end;    sflash_op_t *pop = s_sflash_info.pop;    sflash_db_t *pdb = s_sflash_info.pdb;    if (pop) {        while (len > 0 && sflash_calcblock(addr, &start, &end) == 0) {            pop->sectorerase(pdb, start);            addr += end - start;            len -= end - start;        }    }}void sflash_writedata(unsigned int addr, unsigned char *data, int len){    sflash_op_t *pop = s_sflash_info.pop;    sflash_db_t *pdb = s_sflash_info.pdb;    if (pop) {        if (!sflash_writable(addr, len))             sflash_erasedata(addr, len);        pop->pageprogram(pdb, addr, data, len);    }}//// Test functions//#ifdef CONFIG_ENABLE_FULLFUNCTIONvoid sflash_test_status(void){    sflash_op_t *pop = s_sflash_info.pop;    uart_puts("Status register test :\n");    uart_printf("  current status register : %02x\n", pop->readstatus());    pop->writeenable();    uart_printf("  after write enable : %02x\n", pop->readstatus());    pop->writedisable();    uart_printf("  after write disable : %02x\n", pop->readstatus());}void sflash_test_read(void){    sflash_op_t *pop = s_sflash_info.pop;    sflash_db_t *pdb = s_sflash_info.pdb;    unsigned int i, len = sflash_getsize();    unsigned char buf[0x10000], *pbuf, *pdirect;    int nmiss = 0;        uart_puts("Read test :\n");        if (len > sizeof buf)        len = sizeof buf;        pop->read(pdb, 0, buf, len);        pdirect = (unsigned char *) LOADER_SFLASHBASE;    pbuf = buf;    if (*(unsigned int *) (pdirect + sflash_getsize() - 4) != *(unsigned int *) pbuf) {        uart_puts("  Signature mismatch\n");        ++nmiss;    }        pbuf += 4;    len -= 4;        for (i = 0; i < len; ++i) {        if (*pbuf++ != *pdirect++) {            uart_printf("  Mismatch at addr %d\n", i + 4);            ++nmiss;            break;        }    }    if (nmiss == 0)        uart_puts("  OK\n");}            void sflash_test_write(void){    sflash_op_t *pop = s_sflash_info.pop;    sflash_db_t *pdb = s_sflash_info.pdb;    unsigned int len = sflash_getsize();    unsigned char buf[0x10000], emptybuf[256];    int i, testlen = sizeof emptybuf, found = 0;        uart_puts("Write test :\n");        if (len > sizeof buf)        len = sizeof buf;        pop->read(pdb, 0, buf, len);        memset(emptybuf, 0xff, sizeof emptybuf);        while (len >= testlen) {        len -= testlen;        if (memcmp(buf + len, emptybuf, testlen) == 0) {            found = 1;            break;        }    }        if (!found) {        uart_puts("  No empty block found. Test failed\n");        return;    }        uart_printf("  Empty block is found at address %04x (%d)\n", len, len);        uart_puts("  Writing...\n");    for (i = 0; i < testlen; ++i)        emptybuf[i] = i;    pop->pageprogram(pdb, len, emptybuf, testlen);        uart_puts("  Reading...\n");    pop->read(pdb, len, buf, testlen);        uart_puts("  Verifying : ");    if (memcmp(buf, emptybuf, testlen) == 0)        uart_puts("OK\n");    else        uart_puts("Mismatch\n");}            void sflash_test(int argc, char *argv[]){    int doall = (argv[0] && strcmp(argv[0], "all") == 0) ? 1 : 0;    if (argv[0] == NULL) {        uart_puts("Serial Flash Test :\n");        uart_puts("  Available commands : "            "status "            "read "            "write "            "\n");    } else {        if (!sflash_exist()) {            uart_puts("Serial Flash doesn't exist. Test failed\n");            return;        }        if (doall || strcmp(argv[0], "status") == 0)            sflash_test_status();        if (doall || strcmp(argv[0], "read") == 0)            sflash_test_read();        if (doall || strcmp(argv[0], "write") == 0)            sflash_test_write();    }}#endif

⌨️ 快捷键说明

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