📄 sflash-sst.c
字号:
/***************************************** Copyright (c) 2003-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the EM86XX boot loader *//* * sflash-sst.c * * Serial Flash support - SST * Supported Model : SST25VF512 * * by Ho Lee 04/22/2003 */#include "config.h"#include "uart.h"#include "io.h"#include "util.h"#include "hardware.h"#include "em86xxapi.h"#include "sflash.h"/* comments about SST25 series * * - It supports vendor ID and device ID, so it's possible to read the ID * and to set the correct model number. * - There are protection bits in status register. It protects the serial * flash from programming. These bits should be turned off before programming * and on after programming. * * model size sectors sector size * SSTVF512 512Kb (64KB) 16 0x01000 (4KB) * SSTVF010 1Mb (128KB) 32 0x01000 (4KB) * SSTVF020 2Mb (256KB) 32 0x01000 (4KB) * SSTVF040 4Mb (512KB) 32 0x01000 (4KB) *///// For SST Serial Flash series//// IDs#define SST_VENDORID 0xbf#define SST_DEVICEID_25VF512 0x48#define SST_DEVICEID_25VF010 0x49#define SST_DEVICEID_25VF020 0x43#define SST_DEVICEID_25VF040 0x44// Commands#define SST25_CMD_WREN 0x06 // write enable#define SST25_CMD_WRDI 0x04 // write disable#define SST25_CMD_RDSR 0x05 // read status register#define SST25_CMD_WRSR 0x01 // write status register#define SST25_CMD_EWSR 0x50 // enable write status register#define SST25_CMD_READ 0x03 // read data bytes#define SST25_CMD_AAIP 0xaf // auto address increment program#define SST25_CMD_BP 0x02 // byte program#define SST25_CMD_SE 0x20 // sector erase#define SST25_CMD_BE 0x52 // block erase#define SST25_CMD_CE 0x60 // chip erase#define SST25_CMD_READID 0xab // read ID// Status register#define SST25_STAT_WIP 0x01 // write in progress bit (busy)#define SST25_STAT_WEL 0x02 // write enable latch#define SST25_STAT_BP0 0x04 // block protect bit 0#define SST25_STAT_BP1 0x08 // block protect bit 1#define SST25_STAT_AAI 0x40 // auto address increment programming status#define SST25_STAT_BPL 0x80 // block write protect write protect// page size of pageprogram command#define SST25_PAGESIZE 256enum { SFLASH_SST_25VF512, SFLASH_SST_25VF010, SFLASH_SST_25VF020, SFLASH_SST_25VF040,};static sflash_db_t s_sflash_db_sst[] = { { SFLASH_SST_25VF512, "SST-25VF512", 0x10000, 16, 0x01000 }, { SFLASH_SST_25VF010, "SST-25VF010", 0x20000, 32, 0x01000 }, { SFLASH_SST_25VF020, "SST-25VF020", 0x40000, 64, 0x01000 }, { SFLASH_SST_25VF040, "SST-25VF040", 0x80000, 128, 0x01000 }, { 0, NULL, 0, 0, 0 },};//// Serial Flash operations//static void sflash_sst_setparam(sflash_db_t *pdb, int verbose);static int sflash_sst_detect(sflash_op_t **pop, sflash_db_t **pdb, int verbose);static int sflash_sst_readid(int *pvendor, int *pdevice);static int sflash_sst_readstatus(void);static void sflash_sst_writeenable(void);static void sflash_sst_writedisable(void);static void sflash_sst_setprotection(int enable);static void sflash_sst_chiperase(sflash_db_t *pdb);static void sflash_sst_sectorerase(sflash_db_t *pdb, unsigned int addr);static void sflash_sst_pageprogram(sflash_db_t *pdb, unsigned int addr, unsigned char *data, int len);static void sflash_sst_read(sflash_db_t *pdb, unsigned int addr, unsigned char *to, int len);sflash_op_t g_sflash_op_sst = { vendor : SFLASH_VENDOR_SST_25, name : "SST 25VF series", sflash_list : s_sflash_db_sst, setparam : sflash_sst_setparam, detect : sflash_sst_detect, readstatus : sflash_sst_readstatus, writeenable : sflash_sst_writeenable, writedisable : sflash_sst_writedisable, chiperase : sflash_sst_chiperase, sectorerase : sflash_sst_sectorerase, pageprogram : sflash_sst_pageprogram, read : sflash_sst_read, fast_read : NULL,};//// Serial Flash functions//void sflash_sst_setparam(sflash_db_t *pdb, int verbose){ unsigned int data_param, data_speed; // try to setup parameter for SST 25VF series data_param = 0x0302007f; data_speed = 0x0f000003; sflash_setparam(data_param, data_speed, verbose);}int sflash_sst_detect(sflash_op_t **pop, sflash_db_t **pdb, int verbose){ int model = -1; unsigned int JS, JI, JO; int vendorid, deviceid; unsigned int data; if (verbose) uart_puts("Try to detect SST 25VFxxx...\n"); sflash_sst_setparam(NULL, verbose); // read jumper settings data = __raw_readl(REG_BASE_HOST + SFLA_status); JS = data & 0x01000000; JI = data & 0x00020000; JO = data & 0x00010000; if (!JI && !JO) { sflash_sst_readid(&vendorid, &deviceid); if (vendorid == SST_VENDORID) { switch (deviceid) { case SST_DEVICEID_25VF512 : model = SFLASH_SST_25VF512; break; case SST_DEVICEID_25VF010 : model = SFLASH_SST_25VF010; break; case SST_DEVICEID_25VF020 : model = SFLASH_SST_25VF020; break; case SST_DEVICEID_25VF040 : model = SFLASH_SST_25VF040; break; } } } if (model >= 0) { *pop = &g_sflash_op_sst; *pdb = &s_sflash_db_sst[model]; sflash_sst_setparam(*pdb, verbose); } return model;}int sflash_sst_readid(int *pvendor, int *pdevice){ int i; int data[2]; sflash_chipselect(); sflash_writel((SST25_CMD_READID << 24) | 0); for (i = 0; i < 2; ++i) data[i] = sflash_readb(); if (pvendor) *pvendor = data[0]; if (pdevice) *pdevice = data[1]; sflash_chipdeselect(); return 0;}int sflash_sst_readstatus(void){ unsigned char data; sflash_chipselect(); sflash_sendcommand(SST25_CMD_RDSR); // send command data = sflash_readb(); sflash_chipdeselect(); return data;}void sflash_sst_writeenable(void){ sflash_chipselect(); sflash_sendcommand(SST25_CMD_WREN); sflash_chipdeselect();}void sflash_sst_writedisable(void){ sflash_chipselect(); sflash_sendcommand(SST25_CMD_WRDI); sflash_chipdeselect();}void sflash_sst_setprotection(int enable){ int status = sflash_sst_readstatus(); // send Enable Write Status Register command sflash_chipselect(); sflash_sendcommand(SST25_CMD_EWSR); sflash_chipdeselect(); // set status // BP0 = BP1 = enable // BPL = 0 status &= ~SST25_STAT_BPL; if (enable) status |= (SST25_STAT_BP0 | SST25_STAT_BP1); else status &= ~(SST25_STAT_BP0 | SST25_STAT_BP1); // send Write Status Register command sflash_chipselect(); sflash_sendcommand(SST25_CMD_WRSR); sflash_writeb(status); sflash_chipdeselect();}void sflash_sst_chiperase(sflash_db_t *pdb){ int status; sflash_sst_setprotection(0); sflash_sst_writeenable(); sflash_chipselect(); sflash_sendcommand(SST25_CMD_CE); sflash_chipdeselect(); do { em86xx_usleep(10); status = sflash_sst_readstatus(); } while (status & SST25_STAT_WIP); sflash_sst_writedisable(); sflash_sst_setprotection(1);}void sflash_sst_sectorerase(sflash_db_t *pdb, unsigned int addr){ int status; sflash_sst_setprotection(0); sflash_sst_writeenable(); sflash_chipselect(); sflash_writel((SST25_CMD_SE << 24) | addr); sflash_chipdeselect(); do { em86xx_usleep(10); status = sflash_sst_readstatus(); } while (status & SST25_STAT_WIP); sflash_sst_writedisable(); sflash_sst_setprotection(1);}#define PROGRAMDELAY do { int x; for (x = 0; x < 10; ++x); ++x; } while (0)void sflash_sst_pageprogram(sflash_db_t *pdb, unsigned int addr, unsigned char *data, int len){ int i; int status; sflash_sst_setprotection(0); while (len > 0) { sflash_sst_writeenable(); sflash_chipselect(); sflash_writel((SST25_CMD_AAIP << 24) | addr); for (i = 0; i < len && i < SST25_PAGESIZE; ++i) { if (i != 0) { sflash_chipselect(); sflash_sendcommand(SST25_CMD_AAIP); } sflash_writeb(data[i]); sflash_chipdeselect(); PROGRAMDELAY; do { status = sflash_sst_readstatus(); } while (status & SST25_STAT_WIP); PROGRAMDELAY; } addr += SST25_PAGESIZE; len -= SST25_PAGESIZE; data += SST25_PAGESIZE; do { em86xx_usleep(1); status = sflash_sst_readstatus(); } while (status & SST25_STAT_WIP); sflash_sst_writedisable(); } sflash_sst_setprotection(1);}void sflash_sst_read(sflash_db_t *pdb, unsigned int addr, unsigned char *to, int len){ int i; sflash_chipselect(); sflash_writel((SST25_CMD_READ << 24) | addr); for (i = 0; i < len; ++i) to[i] = sflash_readb(); sflash_chipdeselect();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -