📄 sflash-st-m95.c
字号:
/***************************************** Copyright (c) 2003-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the EM86XX boot loader *//* * sflash-st-m95.c * * Serial Flash support for ST M95xxx * * by Ho Lee 11/04/2003 */#include "config.h"#include "uart.h"#include "io.h"#include "util.h"#include "hardware.h"#include "em86xxapi.h"#include "sflash.h"/* comments about ST M95xxx series * * - It doesn't suport 'bulk erase' or 'sector erase'. Writes overwrite the contents * - M95010, M95020 and M95040 send 8 bits address for reads and writes * M95040 sends address bit 8 at bit 3 of command (reads and writes) * M95080 and M95160 send 16 bits address for reads and writes. * - It should have different read parameter because of the width of address lines * M95010, M95020 : 0x0300007f * M95040 : 0x0300017f * M95080, M95160 : 0x0301007f * - Correct signature byte should be written * M95010, M95020 : 0x7f00ed7e * M95040 : 0xff00ed7e * M95080, M95160 : 0x7f01ed7e * - M95010, M95020, M95040 operates at the rate of 5MHz (maximum) * M95080L ond M95160L operates at the rate of 5MHz and M95080W and M95160W * operates at 10MHz. More slower serial flash timing is needed * - The page size of M95010, M95020 and M95040 is 16 bytes * That of M95080 and M95160 is 32 bytes * * model size sectors sector size * M95010 1Kb (128B, 0x080) 1 0x080 * M95020 2Kb (256B, 0x100) 1 0x100 * M95040 4Kb (512B, 0x200) 1 0x200 * M95080 8Kb (1KB, 0x400) 1 0x400 * M95160 16Kb (2KB, 0x800) 1 0x800 */// ST M95xxx series serial flash#define ST95_CMD_WREN 0x06 // write enable#define ST95_CMD_WRDI 0x04 // write disable#define ST95_CMD_RDSR 0x05 // read status register#define ST95_CMD_WRSR 0x01 // write status register#define ST95_CMD_READ 0x03 // read data bytes // M95040 sends A8 bits at bit 3#define ST95_CMD_PP 0x02 // page program// ST M95Pxx series status regsiter#define ST95_STAT_WIP 0x01 // write in progress bit#define ST95_STAT_WEL 0x02 // write enable latch#define ST95_STAT_BP0 0x04 // block protect bit 0#define ST95_STAT_BP1 0x08 // block protect bit 1#define ST95_STAT_SRWD 0x80 // status register write protect // only M95080 and M95160 // this bit is 1 with M95010, M95020 and M95040// page size of pageprogram command#define ST95_PAGESIZE 16 // M95010, M95020, M95040 : 16 bytes // M95080, M95160 : 32 bytesenum { SFLASH_ST_M95010, SFLASH_ST_M95020, SFLASH_ST_M95040, SFLASH_ST_M95080, SFLASH_ST_M95160, SFLASH_ST_DEFAULT = SFLASH_ST_M95080,};static sflash_db_t s_sflash_db_st_m95[] = { { SFLASH_ST_M95010, "ST-M95010", 0x080, 1, 0x080 }, { SFLASH_ST_M95020, "ST-M95020", 0x100, 1, 0x100 }, { SFLASH_ST_M95040, "ST-M95040", 0x200, 1, 0x200 }, { SFLASH_ST_M95080, "ST-M95080", 0x400, 1, 0x400 }, { SFLASH_ST_M95160, "ST-M95160", 0x800, 1, 0x800 }, { 0, NULL, 0, 0, 0 },};//// Serial Flash operations//static void sflash_st_m95_setparam(sflash_db_t *pdb, int verbose);static int sflash_st_m95_detect(sflash_op_t **pop, sflash_db_t **pdb, int verbose);static int sflash_st_m95_readstatus(void);static void sflash_st_m95_writestatus(int status);static void sflash_st_m95_waitforwip(void);static void sflash_st_m95_writeenable(void);static void sflash_st_m95_writedisable(void);static void sflash_st_m95_chiperase(sflash_db_t *pdb);static void sflash_st_m95_sectorerase(sflash_db_t *pdb, unsigned int addr);static void sflash_st_m95_pageprogram(sflash_db_t *pdb, unsigned int addr, unsigned char *data, int len);static void sflash_st_m95_read(sflash_db_t *pdb, unsigned int addr, unsigned char *to, int len);sflash_op_t g_sflash_op_st_m95 = { vendor : SFLASH_VENDOR_ST_M95, name : "ST M95 series", sflash_list : s_sflash_db_st_m95, setparam : sflash_st_m95_setparam, detect : sflash_st_m95_detect, readstatus : sflash_st_m95_readstatus, writeenable : sflash_st_m95_writeenable, writedisable : sflash_st_m95_writedisable, chiperase : sflash_st_m95_chiperase, sectorerase : sflash_st_m95_sectorerase, pageprogram : sflash_st_m95_pageprogram, read : sflash_st_m95_read, fast_read : NULL,};//// Serial Flash functions//void sflash_st_m95_setparam(sflash_db_t *pdb, int verbose){ unsigned int data_param, data_speed; // try to setup parameter for ST M95 series switch (pdb->model) { case SFLASH_ST_M95010 : case SFLASH_ST_M95020 : data_param = 0x0300007f; break; case SFLASH_ST_M95040: data_param = 0x0300017f; break; case SFLASH_ST_M95080 : case SFLASH_ST_M95160 : default : data_param = 0x0301007f; break; } data_speed= 0x0f000020; sflash_setparam(data_param, data_speed, verbose);}int sflash_st_m95_detect(sflash_op_t **pop, sflash_db_t **pdb, int verbose){ int model = -1; unsigned int JS, JI, JO; unsigned int data; if (verbose) uart_puts("Try to detect ST M95xxx...\n"); data = __raw_readl(REG_BASE_HOST + SFLA_status); JS = data & 0x01000000; JI = data & 0x00020000; JO = data & 0x00010000; if (!JI && !JO) model = SFLASH_ST_DEFAULT; if (model >= 0) { *pop = &g_sflash_op_st_m95; *pdb = &s_sflash_db_st_m95[model]; sflash_st_m95_setparam(*pdb, verbose); } return model;}int sflash_st_m95_readstatus(void){ unsigned char data; sflash_chipselect(); sflash_sendcommand(ST95_CMD_RDSR); // send command data = sflash_readb(); sflash_chipdeselect(); return data;}void sflash_st_m95_writestatus(int status){ sflash_chipselect(); sflash_sendcommand(ST95_CMD_WRSR); // send command sflash_writeb(status); sflash_chipdeselect(); sflash_st_m95_waitforwip();}void sflash_st_m95_waitforwip(void){ int status; do { em86xx_usleep(1); status = sflash_st_m95_readstatus(); } while (status & ST95_STAT_WIP);}void sflash_st_m95_writeenable(void){ int data; data = sflash_st_m95_readstatus(); data &= ~(ST95_STAT_BP0 | ST95_STAT_BP1); sflash_st_m95_writestatus(data); sflash_chipselect(); sflash_sendcommand(ST95_CMD_WREN); sflash_chipdeselect();}void sflash_st_m95_writedisable(void){ sflash_chipselect(); sflash_sendcommand(ST95_CMD_WRDI); sflash_chipdeselect();}void sflash_st_m95_chiperase(sflash_db_t *pdb){ unsigned char data[ST95_PAGESIZE]; unsigned int addr = 0; int len = pdb->size, unit; memset(data, 0xff, sizeof data); while (len > 0) { unit = (len > ST95_PAGESIZE) ? ST95_PAGESIZE : len; sflash_st_m95_pageprogram(pdb, addr, data, unit); len -= unit; addr += unit; }}void sflash_st_m95_sectorerase(sflash_db_t *pdb, unsigned int addr){ sflash_st_m95_chiperase(pdb);}void sflash_st_m95_pageprogram(sflash_db_t *pdb, unsigned int addr, unsigned char *data, int len){ int i; while (len > 0) { sflash_st_m95_writeenable(); sflash_chipselect(); sflash_writeb(ST95_CMD_PP | ((pdb->model == SFLASH_ST_M95040) ? ((addr & 0x100) >> 5) : 0)); if (pdb->model <= SFLASH_ST_M95040) sflash_writeb(addr); else sflash_writew(addr); for (i = 0; i < len && i < ST95_PAGESIZE; ++i) sflash_writeb(data[i]); sflash_chipdeselect(); addr += ST95_PAGESIZE; len -= ST95_PAGESIZE; data += ST95_PAGESIZE; sflash_st_m95_waitforwip(); sflash_st_m95_writedisable(); }}void sflash_st_m95_read(sflash_db_t *pdb, unsigned int addr, unsigned char *to, int len){ int i; sflash_chipselect(); sflash_writeb(ST95_CMD_READ | ((pdb->model == SFLASH_ST_M95040) ? ((addr & 0x100) >> 5) : 0)); if (pdb->model <= SFLASH_ST_M95040) sflash_writeb(addr); else sflash_writew(addr); for (i = 0; i < len; ++i) to[i] = sflash_readb(); sflash_chipdeselect();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -