📄 sdk7a404_strataflash.c~
字号:
/***********************************************************************
* $Workfile: sdk7a404_strataflash.c $
* $Revision: 1.0 $
* $Author: WellsK $
* $Date: Sep 04 2003 15:51:48 $
*
* Project: Basic SDK7A400/SDK7A404 StrataFlash driver
*
* Description:
* This file contains functions used to program 2 StrataFlash
* devices configured in x16 mode (with a 32-bit width) on the
* SDK7A400 and SDK7A404 EVBs.
*
* Notes:
* This driver does not attempt to detect and work with every
* configuration of StrataFlash connected in a system. It is
* targeted to support 2 devices in x16 mode only as configured on
* the SDK7A400 and SDK7A404 EVBs.
*
* Revision History:
* $Log: //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh7a404/bsps/sdk7a404/source/sdk7a404_strataflash.c-arc $
*
* Rev 1.0 Sep 04 2003 15:51:48 WellsK
* Initial revision.
*
*
***********************************************************************
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
* COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
* CAMAS, WA
**********************************************************************/
#include "sdk7a404_strataflash.h"
/***********************************************************************
* Private types and data
**********************************************************************/
/* Maximum number of block regions supported */
#define MAX_CFI_REGIONS 8
/* Maximum number of blocks supported */
#define MAX_CFI_BLOCKS 128
/* Structure used to hold device geometry */
typedef struct
{
UNS_32 baseaddr; /* Device base address */
UNS_32 devsize; /* Device size, 2^n bytes * 2 devices */
UNS_32 wb_size; /* Write buffer size in 32-bit words */
UNS_32 erblocks; /* Number of erase block regions in device */
/* Number of blocks in erase region */
UNS_16 blks[MAX_CFI_REGIONS];
/* Size of each block in erase region */
UNS_32 bsize[MAX_CFI_REGIONS];
UNS_32 blocks; /* Number of blocks in the device */
/* List of block pointers */
UNS_32 blk_addr[MAX_CFI_BLOCKS];
/* List of block sizes */
UNS_32 blk_size[MAX_CFI_BLOCKS];
} CFI_DEV_GEOM_T;
/* CFI device geometry data */
CFI_DEV_GEOM_T cfi_dg;
#if 1
/* CFI standard defines (32-bit) */
#define CFI32_TAG_Q 0x00510051 /* First tag string = '_Q_Q' */
#define CFI32_TAG_R 0x00520052 /* Second tag string = '_R_R' */
#define CFI32_TAG_Y 0x00590059 /* Third tag string = '_Y_Y' */
/* CFI query command (32-bit) */
#define CFI32_QUERY_COMMAND 0x00980098
/* CFI exit programming mode command */
#define CFI32_EXITPROG_COMMAND 0xFFFFFFFF
/* CFI read status command */
#define CFI32_READ_STATUS 0x00700070
/* CFI clear status command */
#define CFI32_CLEAR_STATUS_COMMAND 0x0050050
/* CFI set block command */
#define CFI32_SET_BLOCK_COMMAND 0x00600060
/* CFI block confirm clear (lock) command */
#define CFI32_CONFIRM_CLEAR_BLOCK_COMMAND 0x00D000D0
/* CFI block confirm buffer write command */
#define CFI32_CONFIRM_BUFWRITE_COMMAND 0x00D000D0
/* CFI block confirm command */
#define CFI32_CONFIRM_SET_BLOCK_COMMAND 0x00010001
/* CFI block erase command */
#define CFI32_BLOCKERASE_COMMAND 0x00200020
/* CFI byte (word) write command */
#define CFI32_BYTEWRITE_COMMAND 0x00400040
/* CFI write exit command */
#define CFI32_WRITE_EXIT_COMMAND 0x00FF00FF
/* CFI block write command */
#define CFI32_BLOCK_WRITE_COMMAND 0x00E800E008
#else
/* CFI standard defines (32-bit) */
#define CFI32_TAG_Q 0x0051 /* First tag string = '_Q_Q' */
#define CFI32_TAG_R 0x0052 /* Second tag string = '_R_R' */
#define CFI32_TAG_Y 0x0059 /* Third tag string = '_Y_Y' */
/* CFI query command (32-bit) */
#define CFI32_QUERY_COMMAND 0x0098
/* CFI exit programming mode command */
#define CFI32_EXITPROG_COMMAND 0xFFFF
/* CFI read status command */
#define CFI32_READ_STATUS 0x0070
/* CFI clear status command */
#define CFI32_CLEAR_STATUS_COMMAND 0x0050
/* CFI set block command */
#define CFI32_SET_BLOCK_COMMAND 0x0060
/* CFI block confirm clear (lock) command */
#define CFI32_CONFIRM_CLEAR_BLOCK_COMMAND 0x00D0
/* CFI block confirm buffer write command */
#define CFI32_CONFIRM_BUFWRITE_COMMAND 0x00D0
/* CFI block confirm command */
#define CFI32_CONFIRM_SET_BLOCK_COMMAND 0x0001
/* CFI block erase command */
#define CFI32_BLOCKERASE_COMMAND 0x0020
/* CFI byte (word) write command */
#define CFI32_BYTEWRITE_COMMAND 0x0040
/* CFI write exit command */
#define CFI32_WRITE_EXIT_COMMAND 0x00FF
/* CFI block write command */
#define CFI32_BLOCK_WRITE_COMMAND 0x00E8
#endif
/* CFI tag (QRY) register offset (32-bit) */
#define CFI32_TAG_OFFSET 0x00000010
/* CFI device geometry device size offset */
#define CFI32_DEVSIZE_OFFSET 0x00000027
/* CFI write buffer size offset */
#define CFI32_WBSIZE_OFFSET 0x0000002A
/* CFI erase block regions number offset */
#define CFI_ERBLK_OFFSET 0x0000002C
/* CFI erase block regions information offset */
#define CFI_REINFO_OFFSET 0x0000002D
/***********************************************************************
* Private functions
**********************************************************************/
/***********************************************************************
*
* Function: flash_write
*
* Purpose: Write a value to FLASH
*
* Processing:
* See function.
*
* Parameters:
* addr: Address to write to
* data: Data to write to FLASH
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
void flash_write(volatile UNS_32 *addr, UNS_32 data)
{
*addr = data;
}
/***********************************************************************
*
* Function: flash_read
*
* Purpose: Read a value from FLASH
*
* Processing:
* See function.
*
* Parameters:
* addr: Address to read
*
* Outputs: None
*
* Returns: Data read from the address
*
* Notes:
* A dummy read of another chip select is needed on consecutive
* reads to force the FLASH chip select to deassert. Be careful
* when calling this function consecutively.
*
**********************************************************************/
UNS_32 flash_read(volatile UNS_32 *addr)
{
return *addr;
}
/***********************************************************************
*
* Function: power
*
* Purpose: Compute val to the power of pow.
*
* Processing:
* See function.
*
* Parameters:
* val: Base value
* pow: Power value for val
*
* Outputs: None
*
* Returns: The computer power value of val.
*
* Notes: None
*
**********************************************************************/
UNS_32 power(UNS_32 val,
UNS_32 pow)
{
UNS_32 ret = 1;
while (pow > 0)
{
ret = ret * val;
pow--;
}
return ret;
}
/***********************************************************************
*
* Function: cfi_config_check
*
* Purpose:
* Check the configuration of a StrataFlash interface for the
* LPD SDK7A400 EVB.
*
* Processing:
* See function.
*
* Parameters:
* addr: Base address of StrataFlash device(s)
*
* Outputs: None
*
* Returns: 0 if the FLASH device was detected, otherwise (-1)
*
* Notes:
* This sequence only works for 2x16 devices connected on a 32-bit
* bus in x16 mode.
*
**********************************************************************/
INT_32 cfi_config_check(volatile UNS_32 *addr)
{
UNS_32 bbase;
INT_32 idx, ebidx, bidx, status = -1;
INT_32 i = 0, j = 0; ///xj add for test
/* Save base address of device */
cfi_dg.baseaddr = (UNS_32) addr;
/* Issue CFI query command to each device */
flash_write(addr, CFI32_QUERY_COMMAND);
/* Verify that QRY tags are correct */
if ((flash_read(addr + CFI32_TAG_OFFSET) == CFI32_TAG_Q) &&
(flash_read(addr + CFI32_TAG_OFFSET + 1) == CFI32_TAG_R) &&
(flash_read(addr + CFI32_TAG_OFFSET + 2) == CFI32_TAG_Y))
{
/* Valid StrataFlash part */
/* Get device(s) size in bytes */
cfi_dg.devsize = (flash_read(addr + CFI32_DEVSIZE_OFFSET) &
0xFF);
cfi_dg.devsize = 2 * power(2, cfi_dg.devsize);
/* Get write buffer size - the FLASH device returns this size
in bytes, but since we need to program the interface in
32-bit increments, this number is converted to 32-bit
words (2 devices * buffer size per dev / 4 bytes per word) */
cfi_dg.wb_size = ((flash_read(addr + CFI32_WBSIZE_OFFSET) &
0xFF) + ((flash_read(addr + CFI32_WBSIZE_OFFSET + 1) &
0xFF) << 8));
cfi_dg.wb_size = ((2 * power(2, cfi_dg.wb_size)) / 4);
/* Get number of erase block regions */
cfi_dg.erblocks = (flash_read(addr + CFI_ERBLK_OFFSET) & 0xFF);
/* Get regional block information */
for (idx = 0; idx < cfi_dg.erblocks; idx++) ///1 erblock for 404
{
/* Get low and high region sizes */
i = addr + CFI_REINFO_OFFSET + (idx * 4);
cfi_dg.blks[idx] = (UNS_16)
(flash_read(addr + CFI_REINFO_OFFSET + (idx * 4)) &
0xFF);
cfi_dg.blks[idx] += (UNS_16)
((flash_read(addr + CFI_REINFO_OFFSET + 1 + (idx * 4)) &
0xFF) << 8);
/* Get low and high region sizes */
cfi_dg.bsize[idx] = (UNS_16)
(flash_read(addr + CFI_REINFO_OFFSET + 2 + (idx * 4)) &
0xFF);
cfi_dg.bsize[idx] += (UNS_16)
((flash_read(addr + CFI_REINFO_OFFSET + 3 + (idx * 4)) &
0xFF) << 8);
}
/* Compute block count, addresses, and sizes */
idx = 0;
cfi_dg.blocks = 0;
bbase = (UNS_32) addr;
ebidx = 0;
while (ebidx < cfi_dg.erblocks)
{
/* Compute block info for this erase region */
bidx = 0;
while (bidx <= cfi_dg.blks[ebidx])
{
/* Save address to this block and size of block */
cfi_dg.blk_addr[cfi_dg.blocks] = bbase;
cfi_dg.blk_size[cfi_dg.blocks] = (2 * 0x100 * cfi_dg.bsize[ebidx]);
/* Increment address to next block w/ 2 devices */
bbase = bbase + cfi_dg.blk_size[cfi_dg.blocks];
/* Increment block count */
cfi_dg.blocks++;
/* Next block in erase region */
bidx++;
}
/* Next erase region */
ebidx++;
}
status = 0;
}
return status;
}
/***********************************************************************
*
* Function: cfi_read_status
*
* Purpose: Return the device statuses
*
* Processing:
* See function.
*
* Parameters:
* addr: Base address of StrataFlash device(s)
*
* Outputs: None
*
* Returns: The statuses of the devices
*
* Notes: None
*
**********************************************************************/
UNS_32 cfi_read_status(volatile UNS_32 *addr)
{
flash_write(addr, CFI32_READ_STATUS);
return flash_read(addr);
}
/***********************************************************************
*
* Function: cfi_clear_status
*
* Purpose: Clear device statuses
*
* Processing:
* See function.
*
* Parameters:
* addr: Base address of StrataFlash device(s)
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
void cfi_clear_status(volatile UNS_32 *addr)
{
flash_write(addr, CFI32_CLEAR_STATUS_COMMAND);
}
/***********************************************************************
*
* Function: cfi_wait_read
*
* Purpose: Wait for device to become ready
*
* Processing:
* See function.
*
* Parameters:
* addr: Base address of StrataFlash device(s)
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
int cfi_wait_read(volatile UNS_32 *addr)
{
int tmp;
/* Wait until device is ready on high and low devies */
//while ((cfi_read_status(addr) & 0x00000080) == 0);
//while ((cfi_read_status(addr) & 0x00800000) == 0);
while ((cfi_read_status(addr) & 0x80) == 0);
while ((cfi_read_status(addr) & 0x00800000) == 0);
return cfi_read_status(addr);
cfi_clear_status(addr);
}
/***********************************************************************
* Public functions
**********************************************************************/
/***********************************************************************
*
* Function: cfi_detect
*
* Purpose: Detect the number of CFI devices and the configuration
*
* Processing:
* See function.
*
* Parameters:
* addr: Base address of StrataFlash device(s)
*
* Outputs: None
*
* Returns: 0 if the FLASH device was detected, otherwise (-1)
*
* Notes: None
*
**********************************************************************/
INT_32 cfi_detect(volatile UNS_32 *addr)
{
/* Attempt to check device */
return cfi_config_check(addr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -