📄 drv.c
字号:
// memory map the file and update block addresses of binfo array
#ifdef WIN32
image_addr = MapViewOfFile( map_fd,
FILE_MAP_ALL_ACCESS,
0,
0,
0);
#else //WIN32
image_addr = mmap(0, image_size, PROT_READ|PROT_WRITE,
MAP_FILE|MAP_SHARED, image_fd, 0);
#endif //WIN32
}
tw(tr(TR_END, TrDrvInit, "}\n"));
return image_addr;
}
#endif // (TARGET == 0)
/******************************************************************************
* Device Detection and Copying of Driver to RAM
******************************************************************************/
#if (TARGET == 1)
// Note that this function reads device code of any of the three known flash
// families; Intel, AMD and SST. This works because Intel and AMD use
// the same command data for entering READ_IDENTIFIER mode (0x90).
// The function should be copied and executed from RAM!
#if (CHIPSET != 15)
void ffsdrv_device_id_read(uint32 base_addr, uint16 *manufact, uint16 *device)
{
int addr, i;
// This silly looking code has one purpose; to set addr = 0xAAAA. It is
// necessary in order to force the compiler NOT to produce code that
// uses LDR opcode(s) with PC-relative addressing. The assember code
// produced from this C code is completely relocatable!
for (i = 0, addr = 0; i < 2; i++)
addr |= addr << 8 | 0xAA;
FLASH_WRITE_HALFWORD (base_addr + addr, 0xAA);
FLASH_WRITE_HALFWORD (base_addr + (addr >> 1), 0x55);
// Intel/AMD read id command
FLASH_WRITE_HALFWORD (base_addr + addr, 0x90);
*manufact = FLASH_READ_HALFWORD (base_addr); // flash a0 = 0
device[0] = FLASH_READ_HALFWORD (base_addr + 2); // flash a0 = 1
// Read extended id
device[1] = FLASH_READ_HALFWORD (base_addr + (0xE << 1));
device[2] = FLASH_READ_HALFWORD (base_addr + (0xF << 1));
FLASH_WRITE_HALFWORD (base_addr, 0xFF); // Intel read-array command
// AMD devices do not need the two unlock cycles but SST devices do,
// even though the SST datasheets states otherwise ;-)
FLASH_WRITE_HALFWORD (base_addr + addr, 0xAA);
FLASH_WRITE_HALFWORD (base_addr + (addr >> 1), 0x55);
// AMD read-array/reset command
FLASH_WRITE_HALFWORD (base_addr + addr, 0xF0);
}
#else
/* for CHIPSET == 15 */
// Convert a offset_t value to a block index
void ffsdrv_device_id_read(uint32 base_addr, uint16 *manufact, uint16 *device)
{
#ifdef INTEL_FLASH
/* unlock cycle */
FLASH_WRITE_HALFWORD (base_addr, 0x60);
FLASH_WRITE_HALFWORD (base_addr, 0xD0);
//Enter into auto select command
FLASH_WRITE_HALFWORD (base_addr, 0x90);
*manufact = FLASH_READ_HALFWORD (base_addr);
device[0]=FLASH_READ_HALFWORD ((base_addr+0x02));
// Read extended id
device[1]=FLASH_READ_HALFWORD ((base_addr+0x0A));
device[2]=0; //FLASH_READ_HALFWORD ((base_addr+0xF));
/* Exit from auto select --- reset */
FLASH_WRITE_HALFWORD (base_addr, 0xFF);
#else
int addr, i;
// This silly looking code has one purpose; to set addr = 0x555. It is
// necessary in order to force the compiler NOT to produce code that
// uses LDR opcode(s) with PC-relative addressing. The assember code
// produced from this C code is completely relocatable!
for (i = 0, addr = 0; i < 2; i++)
addr |= addr << 4 | 0xAA;
/* unlock cycle */
FLASH_WRITE_HALFWORD ((base_addr+addr), 0xAA);
FLASH_WRITE_HALFWORD ((base_addr+(addr>>1)), 0x55);
//Enter into auto select command
FLASH_WRITE_HALFWORD ((base_addr+addr), 0x90);
*manufact = FLASH_READ_HALFWORD (base_addr);
device[0]=FLASH_READ_HALFWORD ((base_addr+0x02));
// Read extended id
device[1]=FLASH_READ_HALFWORD ((base_addr+(0x0E<<1)));
device[2]=FLASH_READ_HALFWORD ((base_addr+(0xF<<1)));
/* Exit from auto select --- reset */
FLASH_WRITE_HALFWORD (base_addr, 0xF0);
#endif
}
#endif
#define offset2block(offset) (((uint32) offset) >> dev.binfo[0].size_ld)
#ifdef AMD_FLASH
void ffsdrv_amd_fg_write_halfword(volatile uint16 *addr, uint16 value)
{
volatile uint16 *flash = (volatile uint16*)dev.base;
uint32 cpsr;
uint8 * offset;
uint32 unlockOffset;
static int badFlashCount=0;
offset = (uint8*)addr - (uint32)(dev.base);
unlockOffset = (dev.binfo[offset2block(offset)].offset+ 0x80)>>1;
/* device state is write state */
OS_LOCK_MUTEX(&ffs_write_mutex);
dev.state=DEV_WRITE;
/* Dissable the interrupts */
cpsr=int_disable();
/*LOCOSTO-Live Unlock Fix */
flash[0]=0x0f0;
flash[0]= 0x0060; // sector unlock sequence
flash[0]= 0x0060; // sector unlock sequence
flash[unlockOffset]= 0x0060; // sector unlock sequence (address 6 = VIH)
redowrite:
flash[0]=0x0f0;
/* two unlock cycles */
flash[0x555]=0xAA;
flash[0x2AA]=0x55;
/* issue the program command now */
flash[0x555]=0xA0;
dev.addr=addr; /* record the last write */
dev.data=value;
*addr = value; /* this will be base+offset */
/* Enable the interrupts */
int_enable(cpsr);
/* Wait for the write to complete */
while (1)
{
unsigned short temp= (*addr);
badFlashCount++;
if(!((temp ^ dev.data) & 0x80))
break;
else if ((temp & 0x20))
{
if((((*addr) ^ dev.data) & 0x80))
goto redowrite;
break;
}
else
continue;
}/* Data polling */
/* change the state to default read mode */
dev.state=DEV_READ;
OS_UNLOCK_MUTEX(&ffs_write_mutex);
}
void ffsdrv_amd_fg_write_halfword_local(volatile uint16 *addr, uint16 value)
{
volatile uint16 *flash = (volatile uint16*)dev.base;
uint32 cpsr;
uint8 * offset;
uint32 unlockOffset;
static int badFlashCount=0;
// offset = (uint8*)addr - (uint32)(dev.base);
// unlockOffset = (dev.binfo[offset2block(offset)].offset+ 0x80)>>1;
/* device state is write state */
OS_LOCK_MUTEX(&ffs_write_mutex);
dev.state=DEV_WRITE;
/* Dissable the interrupts */
cpsr=int_disable();
/*LOCOSTO-Live Unlock Fix */
// flash[0]=0x0f0;
// flash[0]= 0x0060; // sector unlock sequence
// flash[0]= 0x0060; // sector unlock sequence
// flash[unlockOffset]= 0x0060; // sector unlock sequence (address 6 = VIH)
redowrite:
flash[0]=0x0f0;
/* two unlock cycles */
flash[0x555]=0xAA;
flash[0x2AA]=0x55;
/* issue the program command now */
flash[0x555]=0xA0;
dev.addr=addr; /* record the last write */
dev.data=value;
*addr = value; /* this will be base+offset */
/* Enable the interrupts */
int_enable(cpsr);
/* Wait for the write to complete */
while (1)
{
unsigned short temp= (*addr);
badFlashCount++;
if(!((temp ^ dev.data) & 0x80))
break;
else if ((temp & 0x20))
{
if((((*addr) ^ dev.data) & 0x80))
goto redowrite;
break;
}
else
continue;
}/* Data polling */
/* change the state to default read mode */
dev.state=DEV_READ;
OS_UNLOCK_MUTEX(&ffs_write_mutex);
}
void ffsdrv_amd_fg_write_halfword_unlock_bypass(volatile uint16 *addr, uint16 value)
{
volatile uint16 *flash = (volatile uint16*)dev.base;
uint32 cpsr;
uint8 * offset;
uint32 unlockOffset;
static int badFlashCount=0;
// offset = (uint8*)addr - (uint32)(dev.base);
// unlockOffset = (dev.binfo[offset2block(offset)].offset+ 0x80)>>1;
/* device state is write state */
OS_LOCK_MUTEX(&ffs_write_mutex);
dev.state=DEV_WRITE;
/* Dissable the interrupts */
cpsr=int_disable();
/*LOCOSTO-Live Unlock Fix */
// flash[0]=0x0f0;
// flash[0]= 0x0060; // sector unlock sequence
// flash[0]= 0x0060; // sector unlock sequence
// flash[unlockOffset]= 0x0060; // sector unlock sequence (address 6 = VIH)
redowrite:
flash[0]=0x0f0;
/* two unlock cycles */
// flash[0x555]=0xAA;
// flash[0x2AA]=0x55;
/* issue the program command now */
flash[0x555]=0xA0;
dev.addr=addr; /* record the last write */
dev.data=value;
*addr = value; /* this will be base+offset */
/* Enable the interrupts */
int_enable(cpsr);
/* Wait for the write to complete */
while (1)
{
unsigned short temp= (*addr);
badFlashCount++;
if(!((temp ^ dev.data) & 0x80))
break;
else if ((temp & 0x20))
{
if((((*addr) ^ dev.data) & 0x80))
goto redowrite;
break;
}
else
continue;
}/* Data polling */
/* change the state to default read mode */
dev.state=DEV_READ;
OS_UNLOCK_MUTEX(&ffs_write_mutex);
}
void ffsdrv_amd_fg_write(void *dst, const void *src, uint16 size)
{
uint8 *mydst = dst;
const uint8 *mysrc = src;
volatile uint16 *flash = (volatile uint16*)dev.base;
uint8 * offset;
uint32 unlockOffset;
uint32 unlock_bypass=0x0;
uint32 cpsr;
/*#ifdef WCP_PROF
prf_LogFunctionEntry((unsigned long) ffsdrv_amd_fg_write);
#endif */
if (size > 0)
{
if ((unsigned int) mydst & 1) {
ffsdrv_write_byte(mydst++, *mysrc++);
size--;
}
if (size >=2)
{
offset = (uint8 *)dst - (uint32)(dev.base);
unlockOffset = (dev.binfo[offset2block(offset)].offset+ 0x80)>>1;
cpsr=int_disable();
flash[0]=0x0f0;
flash[0]= 0x0060; // sector unlock sequence
flash[0]= 0x0060; // sector unlock sequence
flash[unlockOffset]= 0x0060; // sector unlock sequence (address 6 = VIH)
int_enable(cpsr);
cpsr=int_disable();
// two unlock cycles
flash[0x555]=0xAA;
flash[0x2AA]=0x55;
// issue the program command now
flash[0x555]=0x20;
int_enable(cpsr);
unlock_bypass=1;
}
// cpsr=int_disable();
while (size >= 2) {
// ffsdrv_amd_fg_write_halfword_local((uint16 *) mydst, mysrc[0] | (mysrc[1] << 8));
ffsdrv_amd_fg_write_halfword_unlock_bypass((uint16 *) mydst, mysrc[0] | (mysrc[1] << 8));
size -= 2;
mysrc += 2;
mydst += 2;
}
// int_enable(cpsr);
//#if 0
if(unlock_bypass==1)
{
offset = (uint8*)dev.addr - (uint32)(dev.base);
cpsr=int_disable();
flash[dev.binfo[offset2block(offset)].offset] = 0x90;
*(dev.addr) = 0x00;
// flash[0]=0x0f0;
int_enable(cpsr);
}
//#endif
if (size == 1)
ffsdrv_write_byte(mydst++, *mysrc++);
}
/*#ifdef WCP_PROF
prf_LogFunctionExit((unsigned long) ffsdrv_amd_fg_write);
#endif */
}
void ffsdrv_amd_fg_erase(uint8 block)
{
uint16 *addr = (uint16 *) block2addr(block);
ffsdrv.erase_sector(addr);
}
void ffsdrv_amd_fg_erase_sector(void *dst)
{
volatile uint16 *flash = (volatile uint16*)dev.base;
uint32 cpsr;
uint32 unlockOffset;
dev.addr = (uint16 *) dst;
unlockOffset = ((uint32)(dev.addr)-(uint32)(dev.base) + 0x80) >> 1;
/* change the device status */
dev.state=DEV_ERASE;
/* disable the interrupts */
cpsr=int_disable();
/*LOCOSTO-Live Unlock Fix */
flash[0]=0x0f0;
flash[0]= 0x0060; // sector unlock sequence
flash[0]= 0x0060; // sector unlock sequence
flash[unlockOffset]= 0x0060; // sector unlock sequence (address 6 = VIH)
flash[0]=0x0f0;
/* sector erase command -- 6 cycles */
flash[0x555] =0xAA;
flash[0x2AA]=0x55;
flash[0x555]=0x80;
flash[0x555]= 0xAA;
flash[0x2AA]=0x55;
*((volatile uint16*)(dev.addr))=0x30; /* write the command to sector address */
/* Enable the interrupts */
int_enable(cpsr);
/* Wait for the erase to complete */
while ((*dev.addr & 0x80) == 0); /* DQ7 will have 1 on completion of erase */ /* Data polling */
/* change the device state to default READ mode */
dev.state=DEV_READ;
}
//OMAPS62129 Create NEW pseudo SB erase function for AMD_NOR (Isample v1.x)
//This version allows the 3Mb of Flash not used by 1Mb FFS in Block C to
//be reused for other code/data.
void ffsdrv_amd_fg_erase_sector_pseudo_sb(void *dst)
{
volatile uint16 *flash = (volatile uint16*)dev.base;
uint32 cpsr;
uint32 unlockOffset;
dev.addr = (uint16 *) dst;
unlockOffset = ((uint32)(dev.addr)-(uint32)(dev.base) + 0x80) >> 1;
/* change the device status */
dev.state=DEV_ERASE;
ttw(ttr(TTrDrvErase, "e(%d){" NL, dst));
/* disable the interrupts */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -