+++ /dev/null
-/************************************************************************/
-/* */
-/* SPI Flash Memory Drivers */
-/* File name: spiflash.c */
-/* Revision: 1.0 1/27/2004 */
-/* */
-/************************************************************************/
-
-/** Includes. **/
-#ifdef _CFE_
-#include "lib_types.h"
-#include "lib_printf.h"
-#include "lib_string.h"
-#include "bcm_map.h"
-#define printk printf
-#else // linux
-#include <linux/param.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/kernel.h>
-#include <bcm_map_part.h>
-#endif
-
-#include "bcmtypes.h"
-#include "board.h"
-#include "flash_api.h"
-
-
-/** Defines. **/
-#define OSL_DELAY(X) \
- do { { int i; for( i = 0; i < (X) * 500; i++ ) ; } } while(0)
-
-#define MAX_RETRY 3
-
-#define FAR
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#define MAX_MEMORY_MAPPED_SIZE (1024 * 1024)
-
-#define MAXSECTORS 1024 /* maximum number of sectors supported */
-
-#define FLASH_PAGE_SIZE 256
-#define SECTOR_SIZE_4K (4 * 1024)
-#define SECTOR_SIZE_32K (32 * 1024)
-#define SECTOR_SIZE_64K (64 * 1024)
-#define SST25VF020_SECTOR 64 /* 2 Mbit */
-#define SST25VF040_SECTOR 128 /* 4 Mbit */
-#define SST25VF080_SECTOR 256 /* 8 Mbit */
-#define SST25VF016B_SECTOR 512 /* 16 Mbit */
-#define AT25F512_SECTOR 2
-#define AT25F2048_SECTOR 4
-#define AMD25FL_SECTOR 4
-
-/* use 60 instead 63 for aligned on word (4 bytes) boundaries */
-#define MAX_READ 60
-#define CMD_LEN_1 1
-#define CMD_LEN_4 4
-
-/* Standard Boolean declarations */
-#define TRUE 1
-#define FALSE 0
-
-#define SPI_STATUS_OK 0
-#define SPI_STATUS_INVALID_LEN -1
-
-/* Command codes for the flash_command routine */
-#define FLASH_READ 0x03 /* read data from memory array */
-#define FLASH_PROG 0x02 /* program data into memory array */
-#define FLASH_WREN 0x06 /* set write enable latch */
-#define FLASH_WRDI 0x04 /* reset write enable latch */
-#define FLASH_RDSR 0x05 /* read status register */
-#define FLASH_WRST 0x01 /* write status register */
-#define FLASH_EWSR 0x50 /* enable write status */
-#define FLASH_WORD_AAI 0xAD /* auto address increment word program */
-#define FLASH_AAI 0xAF /* auto address increment program */
-
-#define SST_FLASH_CERASE 0x60 /* erase all sectors in memory array */
-#define SST_FLASH_SERASE 0x20 /* erase one sector in memroy array */
-#define SST_FLASH_RDID 0x90 /* read manufacturer and product id */
-
-#define ATMEL_FLASH_CERASE 0x62 /* erase all sectors in memory array */
-#define ATMEL_FLASH_SERASE 0x52 /* erase one sector in memroy array */
-#define ATMEL_FLASH_RDID 0x15 /* read manufacturer and product id */
-
-#define AMD_FLASH_CERASE 0xC7 /* erase all sectors in memory array */
-#define AMD_FLASH_SERASE 0xD8 /* erase one sector in memroy array */
-#define AMD_FLASH_RDID 0xAB /* read manufacturer and product id */
-
-/* RDSR return status bit definition */
-#define SR_WPEN 0x80
-#define SR_BP2 0x10
-#define SR_BP1 0x08
-#define SR_BP0 0x04
-#define SR_WEN 0x02
-#define SR_RDY 0x01
-
-/* Return codes from flash_status */
-#define STATUS_READY 0 /* ready for action */
-#define STATUS_BUSY 1 /* operation in progress */
-#define STATUS_TIMEOUT 2 /* operation timed out */
-#define STATUS_ERROR 3 /* unclassified but unhappy status */
-
-/* Used to mask of bytes from word data */
-#define HIGH_BYTE(a) (a >> 8)
-#define LOW_BYTE(a) (a & 0xFF)
-
-/* Define different type of flash */
-#define FLASH_UNDEFINED 0
-#define FLASH_SST 1
-#define FLASH_ATMEL 2
-#define FLASH_AMD 3
-
-/* ATMEL's manufacturer ID */
-#define ATMELPART 0x1F
-
-/* A list of ATMEL device ID's - add others as needed */
-#define ID_AT25F512 0x60
-#define ID_AT25F2048 0x63
-
-/* AMD's device ID */
-#define AMD_S25FL002D 0x11
-
-/* SST's manufacturer ID */
-#define SSTPART 0xBF
-
-/* A list of SST device ID's - add others as needed */
-#define ID_SST25VF016B 0x41
-#define ID_SST25VF020 0x43
-#define ID_SST25VF040 0x44
-#define ID_SST25VF080 0x80
-
-#define SPI_MAKE_ID(A,B) \
- (((unsigned short) (A) << 8) | ((unsigned short) B & 0xff))
-
-#define SPI_FLASH_DEVICES \
- {{SPI_MAKE_ID(ATMELPART, ID_AT25F512), "AT25F512"}, \
- {SPI_MAKE_ID(ATMELPART, ID_AT25F2048), "AT25F2048"}, \
- {SPI_MAKE_ID(AMD_S25FL002D, 0), "AMD_S25FL002D"}, \
- {SPI_MAKE_ID(SSTPART, ID_SST25VF016B), "SST25VF016B"}, \
- {SPI_MAKE_ID(SSTPART, ID_SST25VF020), "SST25VF020"}, \
- {SPI_MAKE_ID(SSTPART, ID_SST25VF040), "SST25VF040"}, \
- {SPI_MAKE_ID(SSTPART, ID_SST25VF080), "SST25VF080"}, \
- {0,""} \
- }
-
-
-/** Structs. **/
-/* A structure for identifying a flash part. There is one for each
- * of the flash part definitions. We need to keep track of the
- * sector organization, the address register used, and the size
- * of the sectors.
- */
-struct flashinfo {
- char *name; /* "AT25F512", etc. */
- unsigned long addr; /* physical address, once translated */
- int nsect; /* # of sectors */
- struct {
- long size; /* # of bytes in this sector */
- long base; /* offset from beginning of device */
- } sec[MAXSECTORS]; /* per-sector info */
-};
-
-struct flash_name_from_id {
- unsigned short fnfi_id;
- char fnfi_name[30];
-};
-
-
-/** Prototypes. **/
-int spi_flash_init(flash_device_info_t **flash_info);
-static int spi_read( unsigned char *msg_buf, int prependcnt, int nbytes );
-static int spi_write( unsigned char *msg_buf, int nbytes );
-static int spi_flash_sector_erase_int(unsigned short sector);
-static int spi_flash_reset(void);
-static int spi_flash_read_buf(unsigned short sector, int offset,
- unsigned char *buffer, int numbytes);
-static int spi_flash_ub(unsigned short sector);
-static int spi_flash_write_status(unsigned char status);
-static int spi_flash_write_buf(unsigned short sector, int offset,
- unsigned char *buffer, int numbytes);
-static int spi_flash_reset_ub(void);
-static int spi_flash_get_numsectors(void);
-static int spi_flash_get_sector_size(unsigned short sector);
-static unsigned char *spi_get_flash_memptr(unsigned short sector);
-static unsigned char *spi_flash_get_memptr(unsigned short sector);
-static int spi_flash_write(unsigned short sector, int offset, unsigned char *buf,
- int nbytes,int ub);
-static int spi_flash_status(void);
-static unsigned short spi_flash_get_device_id(unsigned short sector);
-static int spi_flash_get_blk(int addr);
-static int spi_flash_get_total_size(void);
-static int spi_flash_get_total_memory_mapped_size(void);
-
-
-/** Variables. **/
-static flash_device_info_t flash_spi_dev =
- {
- 0xffff,
- "",
- spi_flash_sector_erase_int,
- spi_flash_read_buf,
- spi_flash_write_buf,
- spi_flash_get_numsectors,
- spi_flash_get_sector_size,
- spi_flash_get_memptr,
- spi_flash_get_blk,
- spi_flash_get_total_size,
- spi_flash_get_total_memory_mapped_size
- };
-
-/*********************************************************************/
-/* 'meminfo' should be a pointer, but most C compilers will not */
-/* allocate static storage for a pointer without calling */
-/* non-portable functions such as 'new'. We also want to avoid */
-/* the overhead of passing this pointer for every driver call. */
-/* Systems with limited heap space will need to do this. */
-/*********************************************************************/
-static struct flashinfo meminfo; /* Flash information structure */
-static int totalSize = 0;
-static int flashFamily = FLASH_UNDEFINED;
-static int sstAaiWordProgram = FALSE;
-
-static int spi_read( unsigned char *msg_buf, int prependcnt, int nbytes )
-{
- int i;
- SPI->spiMsgCtl = (nbytes << SPI_BYTE_CNT_SHIFT |
- HALF_DUPLEX_R << SPI_MSG_TYPE_SHIFT);
-
- for (i = 0; i < prependcnt; i++)
- SPI->spiMsgData[i] = msg_buf[i];
-
- SPI->spiIntStatus = SPI_INTR_CLEAR_ALL;
-
- SPI->spiCmd = (SPI_CMD_START_IMMEDIATE << SPI_CMD_COMMAND_SHIFT |
- 0 << SPI_CMD_DEVICE_ID_SHIFT |
- prependcnt << SPI_CMD_PREPEND_BYTE_CNT_SHIFT );
-
-
- while (!(SPI->spiIntStatus & SPI_INTR_CMD_DONE));
-
- SPI->spiIntStatus = SPI_INTR_CLEAR_ALL;
-
- for(i = 0; i < nbytes; i++) {
- msg_buf[i] = SPI->spiRxDataFifo[i];
- }
- return SPI_STATUS_OK;
-}
-
-static int spi_write( unsigned char *msg_buf, int nbytes )
-{
- int i;
-
- SPI->spiMsgCtl = (nbytes << SPI_BYTE_CNT_SHIFT |
- HALF_DUPLEX_W << SPI_MSG_TYPE_SHIFT);
-
- for (i = 0; i < nbytes; i++)
- SPI->spiMsgData[i] = msg_buf[i];
-
- SPI->spiCmd = (SPI_CMD_START_IMMEDIATE << SPI_CMD_COMMAND_SHIFT |
- 0 << SPI_CMD_DEVICE_ID_SHIFT |
- 0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT );
-
- while (!(SPI->spiIntStatus & SPI_INTR_CMD_DONE));
-
- SPI->spiIntStatus = SPI_INTR_CLEAR_ALL;
-
- return SPI_STATUS_OK;
-}
-
-/*********************************************************************/
-/* Init_flash is used to build a sector table. This information is */
-/* translated from erase_block information to base:offset information*/
-/* for each individual sector. This information is then stored */
-/* in the meminfo structure, and used throughout the driver to access*/
-/* sector information. */
-/* */
-/* This is more efficient than deriving the sector base:offset */
-/* information every time the memory map switches (since on the */
-/* development platform can only map 64k at a time). If the entire */
-/* flash memory array can be mapped in, then the addition static */
-/* allocation for the meminfo structure can be eliminated, but the */
-/* drivers will have to be re-written. */
-/* */
-/* The meminfo struct occupies 44 bytes of heap space, depending */
-/* on the value of the define MAXSECTORS. Adjust to suit */
-/* application */
-/*********************************************************************/
-
-int spi_flash_init(flash_device_info_t **flash_info)
-{
- struct flash_name_from_id fnfi[] = SPI_FLASH_DEVICES;
- struct flash_name_from_id *fnfi_ptr;
- int i=0, count=0;
- int basecount=0L;
- unsigned short device_id;
- unsigned short blkEnables;
- int sectorsize = 0;
- int numsector = 0;
-
- *flash_info = &flash_spi_dev;
-
-#if 0
- /*
- * in case of flash corrupt, the following steps can erase the flash
- * 1. jumper USE_SPI_SLAVE to make SPI in slave mode
- * 2. start up JTAG debuger and remove the USE_SPI_SLAVE jumper
- * 3. run the following code to erase the flash
- */
- flash_sector_erase_int(0);
- flash_sector_erase_int(1);
- printk("flash_init: erase all sectors\n");
- return FLASH_API_OK;
-#endif
- blkEnables = PERF->blkEnables;
- if ((blkEnables & SPI_CLK_EN) == 0) {
- blkEnables |= SPI_CLK_EN;
- PERF->blkEnables = blkEnables;
- }
-
- flash_spi_dev.flash_device_id = device_id = spi_flash_get_device_id(0);
-
- if ((((char)(device_id >> 8)) == ATMELPART)) {
- flashFamily = FLASH_ATMEL;
- switch ((char)(device_id & 0x00ff)) {
- case ID_AT25F512:
- numsector = AT25F512_SECTOR;
- sectorsize = SECTOR_SIZE_32K;
- break;
- case ID_AT25F2048:
- numsector = AT25F2048_SECTOR;
- sectorsize = SECTOR_SIZE_64K;
- break;
- default:
- break;
- }
- }
- else if (((char)(device_id >> 8)) == (char)SSTPART) {
- flashFamily = FLASH_SST;
- sectorsize = SECTOR_SIZE_4K;
- switch ((unsigned char)(device_id & 0x00ff)) {
- case ID_SST25VF016B:
- numsector = SST25VF016B_SECTOR;
- sstAaiWordProgram = TRUE;
- break;
- case ID_SST25VF080:
- numsector = SST25VF080_SECTOR;
- break;
- case ID_SST25VF040:
- numsector = SST25VF040_SECTOR;
- break;
- case ID_SST25VF020:
- default:
- numsector = SST25VF020_SECTOR;
- break;
- }
- }
- else if (((char)(device_id >> 8)) == (char)AMD_S25FL002D) {
- flashFamily = FLASH_AMD;
- numsector = AMD25FL_SECTOR;
- sectorsize = SECTOR_SIZE_64K;
- device_id &= 0xff00;
- }
- else {
- meminfo.addr = 0L;
- meminfo.nsect = 1;
- meminfo.sec[0].size = SECTOR_SIZE_4K;
- meminfo.sec[0].base = 0x00000;
- return FLASH_API_ERROR;
- }
-
- meminfo.addr = 0L;
- meminfo.nsect = numsector;
- for (i = 0; i < numsector; i++) {
- meminfo.sec[i].size = sectorsize;
- meminfo.sec[i].base = basecount;
- basecount += meminfo.sec[i].size;
- count++;
- }
- totalSize = meminfo.sec[count-1].base + meminfo.sec[count-1].size;
-
- for( fnfi_ptr = fnfi; fnfi_ptr->fnfi_id != 0; fnfi_ptr++ ) {
- if( fnfi_ptr->fnfi_id == device_id ) {
- strcpy( flash_spi_dev.flash_device_name, fnfi_ptr->fnfi_name );
- break;
- }
- }
-
- return (FLASH_API_OK);
-}
-
-/*********************************************************************/
-/* Flash_sector_erase_int() wait until the erase is completed before */
-/* returning control to the calling function. This can be used in */
-/* cases which require the program to hold until a sector is erased, */
-/* without adding the wait check external to this function. */
-/*********************************************************************/
-
-static int spi_flash_sector_erase_int(unsigned short sector)
-{
- unsigned char buf[4];
- unsigned int addr;
- int rc;
-
- if (flashFamily == FLASH_UNDEFINED)
- return FLASH_API_ERROR;
-
- /* set device to write enabled */
- spi_flash_reset();
- spi_flash_ub(sector);
-
- switch (flashFamily) {
- case FLASH_SST:
- buf[0] = SST_FLASH_SERASE;
- break;
- case FLASH_ATMEL:
- buf[0] = ATMEL_FLASH_SERASE;
- break;
- case FLASH_AMD:
- buf[0] = AMD_FLASH_SERASE;
- break;
- };
-
-
- /* erase the sector */
- addr = (unsigned int) spi_get_flash_memptr(sector);
- buf[1] = (unsigned char)((addr & 0x00ff0000) >> 16);
- buf[2] = (unsigned char)((addr & 0x0000ff00) >> 8);
- buf[3] = (unsigned char)(addr & 0x000000ff);
- rc = spi_write(buf, sizeof(buf));
-
- /* check device is ready */
- if (rc == SPI_STATUS_OK) {
- while (spi_flash_status() != STATUS_READY) {}
- }
-
- return(FLASH_API_OK);
-}
-
-/*********************************************************************/
-/* flash_chip_erase_int() wait until the erase is completed before */
-/* returning control to the calling function. This can be used in */
-/* cases which require the program to hold until a sector is erased, */
-/* without adding the wait check external to this function. */
-/*********************************************************************/
-
-#if 0 /* not used */
-unsigned char spi_flash_chip_erase_int(void)
-{
- unsigned char buf[4];
- int rc;
-
- if (flashFamily == FLASH_UNDEFINED)
- return FLASH_API_ERROR;
-
- /* set device to write enabled */
- buf[0] = FLASH_WREN;
- rc = spi_write(buf, 1);
-
- /* check device is ready */
- if (rc == SPI_STATUS_OK) {
- do {
- buf[0] = FLASH_RDSR;
- rc = spi_read(buf, 1, 1);
- if (rc == SPI_STATUS_OK) {
- if (buf[0] & SR_WEN) {
- break;
- }
- } else {
- break;
- }
- } while (1);
- }
-
- switch (flashFamily) {
- case FLASH_SST:
- buf[0] = SST_FLASH_CERASE;
- break;
- case FLASH_ATMEL:
- buf[0] = ATMEL_FLASH_CERASE;
- break;
- case FLASH_AMD:
- buf[0] = AMD_FLASH_CERASE;
- break;
- };
- /* erase the sector */
- rc = spi_write(buf, 1);
-
- /* check device is ready */
- if (rc == SPI_STATUS_OK) {
- while (spi_flash_status() != STATUS_READY) {}
- }
-
- return(FLASH_API_OK);
-}
-#endif
-
-/*********************************************************************/
-/* flash_reset() will reset the flash device to reading array data. */
-/* It is good practice to call this function after autoselect */
-/* sequences had been performed. */
-/*********************************************************************/
-
-static int spi_flash_reset(void)
-{
- if (flashFamily == FLASH_UNDEFINED)
- return FLASH_API_ERROR;
- spi_flash_reset_ub();
- while (spi_flash_status() != STATUS_READY) { }
- return(FLASH_API_OK);
-}
-
-/*********************************************************************/
-/* flash_read_buf() reads buffer of data from the specified */
-/* offset from the sector parameter. */
-/*********************************************************************/
-
-static int spi_flash_read_buf(unsigned short sector, int offset,
- unsigned char *buffer, int numbytes)
-{
- unsigned char buf[MAX_READ];
- unsigned int addr;
- int maxread;
- int idx;
-
- if (flashFamily == FLASH_UNDEFINED)
- return FLASH_API_ERROR;
-
- spi_flash_reset();
-
- addr = (unsigned int) spi_get_flash_memptr(sector);
- addr += offset;
- idx = 0;
- while (numbytes) {
- maxread = (numbytes < sizeof(buf)) ? numbytes : sizeof(buf);
- buf[0] = FLASH_READ;
- buf[1] = (unsigned char)((addr & 0x00ff0000) >> 16);
- buf[2] = (unsigned char)((addr & 0x0000ff00) >> 8);
- buf[3] = (unsigned char)(addr & 0x000000ff);
- spi_read(buf, 4, maxread);
- while (spi_flash_status() != STATUS_READY) {}
- memcpy(buffer+idx, buf, maxread);
- idx += maxread;
- numbytes -= maxread;
- addr += maxread;
- }
-
- return (FLASH_API_OK);
-}
-
-/*********************************************************************/
-/* flash_ub() places the flash into unlock bypass mode. This */
-/* is REQUIRED to be called before any of the other unlock bypass */
-/* commands will become valid (most will be ignored without first */
-/* calling this function. */
-/*********************************************************************/
-
-static int spi_flash_ub(unsigned short sector)
-{
- unsigned char buf[4];
- int rc;
-
- do {
- buf[0] = FLASH_RDSR;
- rc = spi_read(buf, 1, 1);
-
- if (rc == SPI_STATUS_OK) {
- while (spi_flash_status() != STATUS_READY) {}
- if (buf[0] & (SR_BP2|SR_BP1|SR_BP0)) {
- spi_flash_write_status((unsigned char)~(SR_WPEN|SR_BP2|SR_BP1|SR_BP0));
- } else {
- break;
- }
- } else {
- break;
- }
- } while (1);
-
- /* set device to write enabled */
- buf[0] = FLASH_WREN;
- rc = spi_write(buf, 1);
-
- /* check device is ready */
- if (rc == SPI_STATUS_OK) {
- while (spi_flash_status() != STATUS_READY) {}
- do {
- buf[0] = FLASH_RDSR;
- rc = spi_read(buf, 1, 1);
- if (rc == SPI_STATUS_OK) {
- while (spi_flash_status() != STATUS_READY) {}
- if (buf[0] & SR_WEN) {
- break;
- }
- } else {
- break;
- }
- } while (1);
- }
-
- return(FLASH_API_OK);
-}
-
-static int spi_flash_write_status(unsigned char status)
-{
- unsigned char buf[4];
- int rc = SPI_STATUS_OK;
-
- if (flashFamily == FLASH_UNDEFINED)
- return FLASH_API_ERROR;
-
- switch (flashFamily) {
- case FLASH_SST:
- buf[0] = FLASH_EWSR;
- rc = spi_write(buf, 1);
- break;
- default:
- break;
- }
- if (rc == SPI_STATUS_OK) {
- buf[0] = FLASH_WRST;
- buf[1] = (status & (SR_WPEN|SR_BP2|SR_BP1|SR_BP0));
- rc = spi_write(buf, 2);
- if (rc == SPI_STATUS_OK)
- while (spi_flash_status() != STATUS_READY) {}
- }
-
- return FLASH_API_OK;
-}
-
-/*********************************************************************/
-/* flash_write_buf() utilizes */
-/* the unlock bypass mode of the flash device. This can remove */
-/* significant overhead from the bulk programming operation, and */
-/* when programming bulk data a sizeable performance increase can be */
-/* observed. */
-/*********************************************************************/
-
-static int spi_flash_write_buf(unsigned short sector, int offset,
- unsigned char *buffer, int numbytes)
-{
- int ret = FLASH_API_ERROR;
-
- if (flashFamily == FLASH_UNDEFINED)
- return FLASH_API_ERROR;
-
- ret = spi_flash_write(sector, offset, buffer, numbytes, TRUE);
-
- if( ret == -1 )
- printk( "Flash write error. Verify failed\n" );
-
- return( ret );
-}
-
-/*********************************************************************/
-/* flash_reset_ub() is required to remove the flash from unlock */
-/* bypass mode. This is important, as other flash commands will be */
-/* ignored while the flash is in unlock bypass mode. */
-/*********************************************************************/
-
-static int spi_flash_reset_ub(void)
-{
- unsigned char buf[4];
-
- if (flashFamily == FLASH_UNDEFINED)
- return FLASH_API_ERROR;
- /* set device to write disabled */
- buf[0] = FLASH_WRDI;
- spi_write(buf, 1);
- while (spi_flash_status() != STATUS_READY) {}
-
- return(FLASH_API_OK);
-}
-
-/*********************************************************************/
-/* Usefull funtion to return the number of sectors in the device. */
-/* Can be used for functions which need to loop among all the */
-/* sectors, or wish to know the number of the last sector. */
-/*********************************************************************/
-
-static int spi_flash_get_numsectors(void)
-{
- return meminfo.nsect;
-}
-
-/*********************************************************************/
-/* flash_get_sector_size() is provided for cases in which the size */
-/* of a sector is required by a host application. The sector size */
-/* (in bytes) is returned in the data location pointed to by the */
-/* 'size' parameter. */
-/*********************************************************************/
-
-static int spi_flash_get_sector_size(unsigned short sector)
-{
- return meminfo.sec[sector].size;
-}
-
-/*********************************************************************/
-/* The purpose of get_flash_memptr() is to return a memory pointer */
-/* which points to the beginning of memory space allocated for the */
-/* flash. All function pointers are then referenced from this */
-/* pointer. */
-/* */
-/* Different systems will implement this in different ways: */
-/* possibilities include: */
-/* - A direct memory pointer */
-/* - A pointer to a memory map */
-/* - A pointer to a hardware port from which the linear */
-/* address is translated */
-/* - Output of an MMU function / service */
-/* */
-/* Also note that this function expects the pointer to a specific */
-/* sector of the device. This can be provided by dereferencing */
-/* the pointer from a translated offset of the sector from a */
-/* global base pointer (e.g. flashptr = base_pointer + sector_offset)*/
-/* */
-/* Important: Many AMD flash devices need both bank and or sector */
-/* address bits to be correctly set (bank address bits are A18-A16, */
-/* and sector address bits are A18-A12, or A12-A15). Flash parts */
-/* which do not need these bits will ignore them, so it is safe to */
-/* assume that every part will require these bits to be set. */
-/*********************************************************************/
-
-static unsigned char *spi_get_flash_memptr(unsigned short sector)
-{
- unsigned char *memptr = (unsigned char*)
- (FLASH_BASE + meminfo.sec[sector].base);
-
- return (memptr);
-}
-
-static unsigned char *spi_flash_get_memptr(unsigned short sector)
-{
- return( spi_get_flash_memptr(sector) );
-}
-
-/*********************************************************************/
-/* Flash_write extends the functionality of flash_program() by */
-/* providing an faster way to program multiple data words, without */
-/* needing the function overhead of looping algorithms which */
-/* program word by word. This function utilizes fast pointers */
-/* to quickly loop through bulk data. */
-/*********************************************************************/
-static int spi_flash_write(unsigned short sector, int offset, unsigned char *buf,
- int nbytes, int ub)
-{
- unsigned char wbuf[64];
- unsigned int addr;
- unsigned int dst;
- unsigned char *pbuf;
- int cmdlen;
- int maxwrite;
- int pagelimit;
-
- addr = (unsigned int) spi_get_flash_memptr(sector);
- dst = addr + offset;
-
- pbuf = buf;
- switch (flashFamily) {
- case FLASH_SST:
- if( sstAaiWordProgram == FALSE )
- {
- /* Auto Address Increment one byte at a time. */
- spi_flash_ub(sector); /* enable write */
- wbuf[0] = FLASH_AAI;
- while (nbytes) {
- if (pbuf != buf) {
- wbuf[1] = *pbuf;
- cmdlen = CMD_LEN_1;
- } else {
- wbuf[1] = (unsigned char)((dst & 0x00ff0000) >> 16);
- wbuf[2] = (unsigned char)((dst & 0x0000ff00) >> 8);
- wbuf[3] = (unsigned char)(dst & 0x000000ff);
- wbuf[4] = *pbuf;
- cmdlen = CMD_LEN_4;
- }
- spi_write(wbuf, 1+cmdlen);
- while (spi_flash_status() != STATUS_READY) {}
- pbuf++; /* update address and count by one byte */
- nbytes--;
- }
- spi_flash_reset_ub();
- while (spi_flash_status() != STATUS_READY) {}
- }
- else
- {
- /* Auto Address Increment one word (2 bytes) at a time. */
- spi_flash_ub(sector); /* enable write */
- wbuf[0] = FLASH_WORD_AAI;
- while (nbytes) {
- if (pbuf != buf) {
- wbuf[1] = *pbuf;
- wbuf[2] = *(pbuf + 1);
- cmdlen = 3;
- } else {
- wbuf[1] = (unsigned char)((dst & 0x00ff0000) >> 16);
- wbuf[2] = (unsigned char)((dst & 0x0000ff00) >> 8);
- wbuf[3] = (unsigned char)(dst & 0x000000ff);
- wbuf[4] = *pbuf;
- wbuf[5] = *(pbuf + 1);
- cmdlen = 6;
- }
- spi_write(wbuf, cmdlen);
- while (spi_flash_status() != STATUS_READY) {}
- pbuf += 2; /* update address and count by two bytes */
- nbytes -= 2;
- }
- spi_flash_reset_ub();
- while (spi_flash_status() != STATUS_READY) {}
- }
- break;
-
- case FLASH_ATMEL:
- while (nbytes) {
- spi_flash_ub(sector); /* enable write */
- maxwrite = (nbytes < (sizeof(SPI->spiMsgData)-CMD_LEN_4))
- ? nbytes : (sizeof(SPI->spiMsgData)-CMD_LEN_4);
- /* maxwrite is limit to page boundary */
- pagelimit = FLASH_PAGE_SIZE - (dst & 0x000000ff);
- maxwrite = (maxwrite < pagelimit) ? maxwrite : pagelimit;
-
- wbuf[0] = FLASH_PROG;
- wbuf[1] = (unsigned char)((dst & 0x00ff0000) >> 16);
- wbuf[2] = (unsigned char)((dst & 0x0000ff00) >> 8);
- wbuf[3] = (unsigned char)(dst & 0x000000ff);
- memcpy(&wbuf[4], pbuf, maxwrite);
- spi_write(wbuf, maxwrite+CMD_LEN_4);
- while (spi_flash_status() != STATUS_READY) {}
- pbuf += maxwrite;
- nbytes -= maxwrite;
- dst += maxwrite;
- }
- break;
-
- case FLASH_AMD:
- while (nbytes) {
- spi_flash_ub(sector); /* enable write */
- maxwrite = (nbytes < (sizeof(SPI->spiMsgData)-CMD_LEN_4))
- ? nbytes : (sizeof(SPI->spiMsgData)-CMD_LEN_4);
- /* maxwrite is limit to page boundary */
- pagelimit = FLASH_PAGE_SIZE - (dst & 0x000000ff);
- maxwrite = (maxwrite < pagelimit) ? maxwrite : pagelimit;
-
- wbuf[0] = FLASH_PROG;
- wbuf[1] = (unsigned char)((dst & 0x00ff0000) >> 16);
- wbuf[2] = (unsigned char)((dst & 0x0000ff00) >> 8);
- wbuf[3] = (unsigned char)(dst & 0x000000ff);
- memcpy(&wbuf[4], pbuf, maxwrite);
- spi_write(wbuf, maxwrite+CMD_LEN_4);
- while (spi_flash_status() != STATUS_READY) {}
- pbuf += maxwrite;
- nbytes -= maxwrite;
- dst += maxwrite;
- }
- break;
-
- default:
- return 0;
- }
-
- return (pbuf-buf);
-}
-
-/*********************************************************************/
-/* Flash_status return an appropriate status code */
-/*********************************************************************/
-
-static int spi_flash_status(void)
-{
- unsigned char buf[4];
- int rc;
- int retry = 10;
-
- /* check device is ready */
- do {
- buf[0] = FLASH_RDSR;
- rc = spi_read(buf, 1, 1);
- if (rc == SPI_STATUS_OK) {
- if (!(buf[0] & SR_RDY)) {
- return STATUS_READY;
- }
- } else {
- return STATUS_ERROR;
- }
- OSL_DELAY(10);
- } while (retry--);
-
- return STATUS_TIMEOUT;
-}
-
-/*********************************************************************/
-/* flash_get_device_id() return the device id of the component. */
-/*********************************************************************/
-
-static unsigned short spi_flash_get_device_id(unsigned short sector)
-{
- unsigned char buf[4];
- int prependcnt;
- int i;
-
- for (i = 0; i < MAX_RETRY; i++) {
- /* read product id command */
- buf[0] = SST_FLASH_RDID;
- buf[1] = 0;
- buf[2] = 0;
- buf[3] = 0;
- prependcnt = 4;
- spi_read(buf, prependcnt, sizeof(unsigned short));
- while (spi_flash_status() != STATUS_READY) {}
-
- if (buf[0] == SSTPART) {
- return( *(unsigned short *)&buf[0] );
- }
- }
-
- for (i = 0; i < MAX_RETRY; i++) {
- buf[0] = ATMEL_FLASH_RDID;
- prependcnt = 1;
- spi_read(buf, prependcnt, sizeof(unsigned short));
- while (spi_flash_status() != STATUS_READY) {}
-
- if (buf[0] == ATMELPART) {
- return( *(unsigned short *)&buf[0] );
- }
- }
-
- for (i = 0; i < MAX_RETRY; i++) {
- buf[0] = AMD_FLASH_RDID;
- buf[1] = 0;
- buf[2] = 0;
- buf[3] = 0;
- prependcnt = 4;
- spi_read(buf, prependcnt, sizeof(unsigned short));
- while (spi_flash_status() != STATUS_READY) {}
-
- if (buf[0] == AMD_S25FL002D) {
- return( *(unsigned short *)&buf[0] );
- }
- }
-
- /* return manufacturer code and device code */
- return( *(unsigned short *)&buf[0] );
-}
-
-/*********************************************************************/
-/* The purpose of flash_get_blk() is to return a the block number */
-/* for a given memory address. */
-/*********************************************************************/
-
-static int spi_flash_get_blk(int addr)
-{
- int blk_start, i;
- int last_blk = spi_flash_get_numsectors();
- int relative_addr = addr - (int) FLASH_BASE;
-
- for(blk_start=0, i=0; i < relative_addr && blk_start < last_blk; blk_start++)
- i += spi_flash_get_sector_size(blk_start);
-
- if( (unsigned int)i > (unsigned int)relative_addr ) {
- blk_start--; // last blk, dec by 1
- } else {
- if( blk_start == last_blk )
- {
- printk("Address is too big.\n");
- blk_start = -1;
- }
- }
-
- return( blk_start );
-}
-
-/************************************************************************/
-/* The purpose of flash_get_total_size() is to return the total size of */
-/* the flash */
-/************************************************************************/
-static int spi_flash_get_total_size(void)
-{
- return totalSize;
-}
-
-static int spi_flash_get_total_memory_mapped_size(void)
-{
- return((totalSize < MAX_MEMORY_MAPPED_SIZE)
- ? totalSize : MAX_MEMORY_MAPPED_SIZE);
-}
-