📄 flash.c
字号:
/*
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
* This software is copyrighted by and is the sole property of
* VIA Networking Technologies, Inc. This software may only be used
* in accordance with the corresponding license agreement. Any unauthorized
* use, duplication, transmission, distribution, or disclosure of this
* software is expressly forbidden.
*
* This software is provided by VIA Networking Technologies, Inc. "as is"
* and any express or implied warranties, including, but not limited to, the
* implied warranties of merchantability and fitness for a particular purpose
* are disclaimed. In no event shall VIA Networking Technologies, Inc.
* be liable for any direct, indirect, incidental, special, exemplary, or
* consequential damages.
*
*
* File: flash.c
*
* Purpose: FLASH hardware accessing functions
*
* Author: Tevin Chen
*
* Date: Jan 08, 2002
*
* Functions:
*
* Revision History:
*
*/
#if !defined(__KERNEL_H__)
#include "kernel.h"
#endif
#if !defined(__UASSERT_H__)
#include "uassert.h"
#endif
#if !defined(__MACRO_H__)
#include "macro.h"
#endif
#if !defined(__DEVICE_H__)
#include "device.h"
#endif
#if !defined(__STR_H__)
#include "str.h"
#endif
#if !defined(__SOC_H__)
#include "soc.h"
#endif
#if !defined(__FLASH_H__)
#include "flash.h"
#endif
/*--------------------- Static Definitions ------------------------*/
#define DEBUG_FLSH 0
#if DEBUG_FLSH
#define DBG_PRN_FLSH DBG_PRN
#else
#define DBG_PRN_FLSH(...) FUNC_NULL()
#endif
#define FLSH_BUFFER_SIZE 0x00010000 // 64k bytes
#define SST_MANU_ID 0xBFD7 // manufacturerID(BF << 8) | deviceID(D7)
#define AMD_MANU_ID 0x01F9 // manufacturerID(01 << 8) | deviceID(F9)
/*--------------------- Static Types ------------------------------*/
/*--------------------- Static Macros -----------------------------*/
// host to flash short int (WORD) endian convert
#if defined(__BIG_ENDIAN) && (defined(__SWITCH_CPUIF_PCI) || defined(__CPU_S3C2510A))
#define htofs(n) REV_WORD(n)
#else
#define htofs(n) (n)
#endif
// flash to host short int (WORD) endian convert
#if defined(__BIG_ENDIAN) && (defined(__SWITCH_CPUIF_PCI) || defined(__CPU_S3C2510A))
#define ftohs(n) REV_WORD(n)
#else
#define ftohs(n) (n)
#endif
/*--------------------- Static Classes ----------------------------*/
/*--------------------- Static Variables --------------------------*/
static UINT8 sg_abyBuf[FLSH_BUFFER_SIZE];
static UINT16 sg_wFlshID;
static UINT32 sg_u32FlshBase;
/*--------------------- Static Functions --------------------------*/
static UINT16 s_u16ReadAmdId(UINT32 u32Addr);
static UINT16 s_u16ReadSstId(UINT32 u32Addr);
static void s_vConfigFlshIdAndBase(UINT32 u32Addr);
static void s_vEraseSect(UINT32 u32SectAddr);
static void s_vProgramSect(UINT32 u32SectAddr, UINT32 u32SectSize, BOOL bEndianConvt);
static BOOL s_bVerifyBlock(UINT32 u32Addr, PUINT8 pu8Data, UINT32 u32BlockSize, BOOL bEndianConvt);
/*--------------------- Export Variables --------------------------*/
BOOL FLSH_bReadU8(UINT32 u32Addr, PUINT8 pu8Data)
{
u32Addr |= ASIC_NON_CACHE_ADDR; // For non-cache access
*pu8Data = *(PUINT8)u32Addr;
return TRUE;
}
BOOL FLSH_bWriteU8(UINT32 u32Addr, UINT8 u8Data)
{
FLSH_bWriteBlock(u32Addr, &u8Data, 1, FALSE);
return s_bVerifyBlock(u32Addr, &u8Data, 1, FALSE);
}
BOOL FLSH_bReadU16(UINT32 u32Addr, PUINT16 pu16Data)
{
u32Addr |= ASIC_NON_CACHE_ADDR; // For non-cache access
*pu16Data = *(PUINT16)u32Addr;
return TRUE;
}
BOOL FLSH_bWriteU16(UINT32 u32Addr, UINT16 u16Data)
{
FLSH_bWriteBlock(u32Addr, (PUINT8)&u16Data, 2, FALSE);
return s_bVerifyBlock(u32Addr, (PUINT8)&u16Data, 2, FALSE);
}
BOOL FLSH_bReadU32(UINT32 u32Addr, PUINT32 pu32Data)
{
u32Addr |= ASIC_NON_CACHE_ADDR; // For non-cache access
*pu32Data = *(PUINT32)u32Addr;
return TRUE;
}
BOOL FLSH_bWriteU32(UINT32 u32Addr, UINT32 u32Data)
{
FLSH_bWriteBlock(u32Addr, (PUINT8)&u32Data, 4, FALSE);
return s_bVerifyBlock(u32Addr, (PUINT8)&u32Data, 4, FALSE);
}
BOOL FLSH_bReadBlock (UINT32 u32Addr, PUINT8 pu8Data, UINT32 u32BlockSize)
{
UINT32 u32Idx;
for (u32Idx = 0; u32Idx < u32BlockSize; u32Idx++)
FLSH_bReadU8(u32Addr + u32Idx, pu8Data + u32Idx);
return TRUE;
}
BOOL FLSH_bWriteBlock (UINT32 u32Addr, PUINT8 pu8Data, UINT32 u32BlockSize, BOOL bEndianConvt)
{
UINT32 u32CurSector = 0, u32CurIndex = 0, u32Rest = u32BlockSize;
UINT32 u32SectSize, u32SecOffset;
PUINT8 pu8OrgData = pu8Data;
u32Addr |= ASIC_NON_CACHE_ADDR; // For non-cache access
// Read info to distinguish SST or AMD flash
s_vConfigFlshIdAndBase(u32Addr);
u32SecOffset = u32Addr - sg_u32FlshBase;
if (sg_wFlshID == AMD_MANU_ID) {
UINT8 bySectorNo;
if ((u32SecOffset & 0xFFFF0000) == 0) {
// sector 0~7, size is 8k bytes
bySectorNo = (u32SecOffset & 0xE000) >> 13;
u32CurSector = sg_u32FlshBase + (u32SecOffset & 0xE000);
u32CurIndex = u32SecOffset & 0x1FFF;
}
else {
// sector 8~70, size is 64k bytes
bySectorNo = ((u32SecOffset & 0xFFFF0000) >> 16) + 7;
u32CurSector = sg_u32FlshBase + (u32SecOffset & 0xFFFF0000);
u32CurIndex = u32SecOffset & 0xFFFF;
}
do {
if (bySectorNo < 8)
u32SectSize = 0x2000; // 8k bytes
else
u32SectSize = 0x10000; // 64k bytes
// Backup current sector to buffer
FLSH_bReadBlock(u32CurSector, sg_abyBuf, u32SectSize);
// Modify buffer
u32SecOffset = (u32Rest <= (u32SectSize - u32CurIndex)) ? u32Rest : (u32SectSize - u32CurIndex);
STR_pvMemcpy(sg_abyBuf + u32CurIndex, pu8OrgData, u32SecOffset);
// protect flash erase/program address sequence from being interrupted
INTR_vCriticalSectionEnter();
s_vEraseSect(u32CurSector); //1. Erase the sector
s_vProgramSect(u32CurSector, u32SectSize, bEndianConvt); //2. Program the sector
INTR_vCriticalSectionLeave();
u32CurSector += u32SectSize; // The next sector address
u32CurIndex = 0; // Reset index to 0
u32Rest -= u32SecOffset; // Sub. the writed block
pu8OrgData += u32SecOffset;
bySectorNo++;
} while (u32Rest > 0); // If u32Rest>0, continue write the next sector
}
else if (sg_wFlshID == SST_MANU_ID) {
// account current sector and index
u32CurSector = (sg_u32FlshBase | (u32SecOffset & 0x0FF000));
u32CurIndex = (u32SecOffset & 0x000FFF);
u32SectSize = 0x1000; // 4k bytes
do {
// Backup current sector to buffer
STR_pvMemset(sg_abyBuf, 0, u32SectSize);
FLSH_bReadBlock(u32CurSector, sg_abyBuf, u32SectSize);
// Modify buffer
u32SecOffset = (u32Rest <= (u32SectSize - u32CurIndex)) ? u32Rest : (u32SectSize - u32CurIndex);
STR_pvMemcpy(sg_abyBuf + u32CurIndex, pu8OrgData, u32SecOffset);
// protect flash erase/program address sequence from being interrupted
INTR_vCriticalSectionEnter();
s_vEraseSect(u32CurSector); //1. Erase the sector
s_vProgramSect(u32CurSector, u32SectSize, FALSE); //2. Program the sector
INTR_vCriticalSectionLeave();
u32CurSector += u32SectSize; // The next sector address
u32CurIndex = 0; // Reset index to 0
u32Rest -= u32SecOffset; // Sub. the writed block
pu8OrgData += u32SecOffset;
} while (u32Rest > 0); // If u32Rest>0, continue write the next sector
}
if (sg_wFlshID == AMD_MANU_ID)
return s_bVerifyBlock(u32Addr, pu8Data, u32BlockSize, bEndianConvt);
else
return s_bVerifyBlock(u32Addr, pu8Data, u32BlockSize, FALSE);
}
static UINT16 s_u16ReadAmdId (UINT32 u32Addr)
{
volatile UINT16 *pu16OpA, *pu16OpB, *pu16OpC;
UINT16 u16FlshID;
UINT16 u16Tmp;
u32Addr |= ASIC_NON_CACHE_ADDR; // For non-cache access
u16FlshID = 0;
// AMD read manufacturer id procedure
pu16OpA = (PUINT16)((u32Addr & 0xFFFF0000) | (0x555 << 1));
pu16OpB = (PUINT16)((u32Addr & 0xFFFF0000) | (0x2AA << 1));
pu16OpC = (PUINT16)(u32Addr & 0xFFFFFF00);
// protect flash erase/program address sequence from being interrupted
INTR_vCriticalSectionEnter();
// enter autoselect mode
*pu16OpA = htofs(0x00AA);
*pu16OpB = htofs(0x0055);
*pu16OpA = htofs(0x0090);
// read manufacturer id
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -