📄 flashspecificgomad.c
字号:
/*
* COPYRIGHT (c) 1995,2000 TriMedia Technologies Inc.
*
* +-----------------------------------------------------------------+
* | THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED |
* | AND COPIED IN ACCORDANCE WITH THE TERMS AND CONDITIONS OF SUCH |
* | A LICENSE AND WITH THE INCLUSION OF THE THIS COPY RIGHT NOTICE. |
* | THIS SOFTWARE OR ANY OTHER COPIES OF THIS SOFTWARE MAY NOT BE |
* | PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. THE |
* | OWNERSHIP AND TITLE OF THIS SOFTWARE IS NOT TRANSFERRED. |
* +-----------------------------------------------------------------+
*
* Module name : FlashSpecificGomad.c 1.10
*
* Title : Low level flash manipulation routines
*
* Last update : 11:38:39 - 00/06/19
*
* Reviewed :
*
* Revision history :
*
* Description : Implementation of flash access functions
* for Philips GOMAD board (containing Am29f016B).
*
*/
/*------------------------------- Includes -----------------------------------*/
#include <stdio.h>
#include <tmlib/tmtypes.h>
#include <tmlib/tmFlash.h>
#include <tm1/mmio.h>
#include <tm1/tmPCI.h>
/*---------------------------- Physical flash --------------------------------*/
#define PCI_VENDOR_ID_SOUTH 0x056510AD
#define PHY_FLASH_BASE_ADDRESS ((Address)0xFF800000)
#define PHY_BANK_SIZE 0x00600000 /* there seems to be a Gomad problem */
#define PHY_FLASH_SIZE 0x00200000 /* with high flash banks, so */
#define PHY_BLOCK_SIZE 0x00010000 /* disable them */
#define NROF_PHY_BANKS 2
#define MEM_CTL_REG ((VAddress)0x110)
#define FLASH_BANK_SELECT 0x08
#define RETRY_COUNT 20
#define LROUND_DOWN(v,bs) (((UInt) (v)/(UInt) (bs))*(UInt) (bs))
typedef volatile Byte *VAddress;
typedef volatile UInt32 VUInt32;
/*----------------------------- Logical flash --------------------------------*/
#define LOG_BLOCK_SIZE PHY_BLOCK_SIZE
#define BLOCK_CLUSTER_FACTOR (LOG_BLOCK_SIZE / PHY_BLOCK_SIZE)
Int SZOF_FLASH_BLOCK = LOG_BLOCK_SIZE;
Int NROF_FLASH_BLOCKS = (NROF_PHY_BANKS * PHY_BANK_SIZE) / LOG_BLOCK_SIZE;
/* ------- . ------- */
UInt32
FLASH_read(Pointer address)
{
UInt32 log_address = (UInt32) address;
UInt32 bank_number = log_address / PHY_BANK_SIZE;
UInt32 lf_address = log_address % PHY_BANK_SIZE;
VUInt32 *phy_address = (UInt32*)(PHY_FLASH_BASE_ADDRESS + lf_address);
*MEM_CTL_REG = (FLASH_BANK_SELECT | bank_number);
return *phy_address;
}
/* ------- . ------- */
/* this commented out version of FLASH_block_read is more efficient,
speed wise, than the version below. However this version is too
large, codewise, for Flash booting. The uncommented out version
should be used for flash booting. For normal applications a user
can use the commented out version of FLASH_block_read as it is
more efficient speed wise */
/* version of FLASH_block_read can be used for normal applications */
/*void FLASH_block_read( Pointer address, Pointer image, Int nrof_words )
{
UInt32 log_address = (UInt32) address;
UInt32 bank_number = log_address / PHY_BANK_SIZE;
UInt32 lf_address = log_address % PHY_BANK_SIZE;
UInt32 *phy_address = (UInt32*)(PHY_FLASH_BASE_ADDRESS + lf_address);
Int32 *i = ((Int32*)image);
*MEM_CTL_REG = (FLASH_BANK_SELECT | bank_number);
while (nrof_words--) {
*(i++) = *(phy_address++);
}
}
*/
/* version of FLASH_block_read to be used for Flash File system booting */
void FLASH_block_read( Pointer flash, Pointer image, Int nrof_words )
{
Int32 *f = ((Int32*)flash);
Int32 *i = ((Int32*)image);
while (nrof_words--) {
*(i++) = FLASH_read( f++ );
}
}
/* ------- . ------- */
static void
flash_byte_write(VAddress phy_address, UInt32 lf_address, Byte data)
{
Int i;
Byte old_data = *phy_address;
Byte new_data = old_data & data;
VAddress phy_flashbase = (VAddress)(PHY_FLASH_BASE_ADDRESS + LROUND_DOWN(lf_address, PHY_FLASH_SIZE));
if (new_data == old_data) { return; }
for (i = 0; i < RETRY_COUNT; i++) {
phy_flashbase[0x555] = 0xAA;
phy_flashbase[0x2AA] = 0x55;
phy_flashbase[0x555] = 0xA0;
*phy_address = data;
while ((*phy_address ^ *phy_address) & 0x40) {}
if (*phy_address == data) {
return;
}
}
}
Bool
FLASH_write(Pointer address, UInt32 data)
{
Int i;
UInt32 log_address = (UInt32) address;
UInt32 bank_number = log_address / PHY_BANK_SIZE;
UInt32 lf_address = log_address % PHY_BANK_SIZE;
VAddress phy_address = (VAddress)(PHY_FLASH_BASE_ADDRESS + lf_address);
UInt32 data1 = data;
*MEM_CTL_REG = (FLASH_BANK_SELECT | bank_number);
#ifdef __BIG_ENDIAN__
for (i=3; i >= 0; i--) {
#else
for (i=0; i < 4; i++) {
#endif
flash_byte_write( phy_address+i, lf_address, (Byte)data1 );
data1 >>= 8;
}
return *((VUInt32*) phy_address) == data;
}
Bool
FLASH_block_write( Pointer flash, Pointer image, Int nrof_words )
{
Int32 *f = ((Int32*)flash) + nrof_words;
Int32 *i = ((Int32*)image) + nrof_words;
Bool result;
do {
result = FLASH_write( --f, *(--i) );
} while ((Pointer)f != flash && result);
return result;
}
/* ------- . ------- */
static Bool
flash_block_erase(UInt block_index)
{
UInt32 log_blockbase = block_index * PHY_BLOCK_SIZE;
UInt32 log_flashbase = LROUND_DOWN(log_blockbase, PHY_FLASH_SIZE);
VAddress phy_blockbase = (VAddress)PHY_FLASH_BASE_ADDRESS + (log_blockbase % PHY_BANK_SIZE);
VAddress phy_flashbase = (VAddress)PHY_FLASH_BASE_ADDRESS + (log_flashbase % PHY_BANK_SIZE);
UInt32 bank_number = log_blockbase / PHY_BANK_SIZE;
*MEM_CTL_REG = (FLASH_BANK_SELECT | bank_number);
*((phy_flashbase + 0x555)) = 0xAA;
*((phy_flashbase + 0x2AA)) = 0x55;
*((phy_flashbase + 0x555)) = 0x80;
*((phy_flashbase + 0x555)) = 0xAA;
*((phy_flashbase + 0x2AA)) = 0x55;
*(phy_blockbase) = 0x30;
while (*phy_blockbase != 0xff) {};
return True;
}
Bool
FLASH_block_erase(UInt ab, Bool check_if_necessary)
{
Int i;
if (check_if_necessary) {
UInt *pt = (Pointer) (ab * SZOF_FLASH_BLOCK);
Bool necessary = False;
for (i = 0; i < (SZOF_FLASH_BLOCK / sizeof (UInt)); i++) {
if (FLASH_read(pt++) != 0xffffffff) {
necessary = True;
break;
}
}
if (!necessary) {
return True;
}
}
for ( i= 0; i < BLOCK_CLUSTER_FACTOR; i++ ) {
flash_block_erase( ab * BLOCK_CLUSTER_FACTOR + i );
}
return True;
}
/*---------------------------- Initialization --------------------------------*/
Bool
FLASH_init()
{
UInt32 south_addr;
return !pciAddressFind(PCI_VENDOR_ID_SOUTH, &south_addr)
& !pciConfigWrite((south_addr | 0x4c), 0x00041300);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -