📄 nand.c
字号:
unsigned long pages_in_bank[4]; /* 44 */
unsigned long pages_in_vram; /* 60 */
unsigned long initrd_start; /* 64 */
unsigned long initrd_size; /* 68 */
unsigned long rd_start; /* 72 */
unsigned long system_rev; /* 76 */
unsigned long system_serial_low; /* 80 */
unsigned long system_serial_high; /* 84 */
unsigned long mem_fclk_21285; /* 88 */
} s;
char unused[256];
} u1;
union
{
char paths[8][128];
struct
{
unsigned long magic;
char n[1024 - sizeof( unsigned long )];
} s;
} u2;
char commandline[COMMAND_LINE_SIZE];
};
extern void call_linux( U32 a0 , U32 a1 , U32 a2 );
/*************************************************************/
static __inline void cpu_arm920_cache_clean_invalidate_all( void )
{
__asm
{
mov r1, #0
mov r1, #7 << 5 /* 8 segments */
cache_clean_loop1:
orr r3, r1, #63UL << 26 /* 64 entries */
cache_clean_loop2:
mcr p15, 0, r3, c7, c14, 2 /* clean & invalidate D index */
subs r3, r3, #1 << 26
bcs cache_clean_loop2 /* entries 64 to 0 */
subs r1, r1, #1 << 5
bcs cache_clean_loop1 /* segments 7 to 0 */
mcr p15, 0, r1, c7, c5, 0 /* invalidate I cache */
mcr p15, 0, r1, c7, c10, 4 /* drain WB */
}
}
void cache_clean_invalidate( void )
{
cpu_arm920_cache_clean_invalidate_all();
}
static __inline void cpu_arm920_tlb_invalidate_all( void )
{
__asm
{
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 /* drain WB */
mcr p15, 0, r0, c8, c7, 0 /* invalidate I & D TLBs */
}
}
void tlb_invalidate( void )
{
cpu_arm920_tlb_invalidate_all();
}
void disable_irq( void );
void call_linux( U32 a0 , U32 a1 , U32 a2 )
{
void ( *goto_start ) ( U32 , U32 );
cache_clean_invalidate();
tlb_invalidate();
__asm
{
// mov r0, a0//%0
// mov r1, a1//%1
// mov r2, a2//%2
mov ip, #0
mcr p15, 0, ip, c13, c0, 0 /* zero PID */
mcr p15, 0, ip, c7, c7, 0 /* invalidate I,D caches */
mcr p15, 0, ip, c7, c10, 4 /* drain write buffer */
mcr p15, 0, ip, c8, c7, 0 /* invalidate I,D TLBs */
mrc p15, 0, ip, c1, c0, 0 /* get control register */
bic ip, ip, #0x0001 /* disable MMU */
mcr p15, 0, ip, c1, c0, 0 /* write control register */
//mov pc, r2
//nop
//nop
/* no outpus */
//: "r" (a0), "r" (a1), "r" (a2)
}
// SetClockDivider(1, 1);
// SetSysFclk(FCLK_200M); //start kernel, use 200M
SET_IF();
goto_start = ( void ( * ) ( U32 , U32 ) ) a2;
( *goto_start ) ( a0 , a1 );
}
static void LoadRun( void )
{
U32 i, ram_addr, buf = boot_params.run_addr.val;
struct param_struct* params = ( struct param_struct* ) 0x30000100;
int size;
memset( params , 0 , sizeof( struct param_struct ) );
/*{
U32 *pD = (U32 *)0x30000100;
for(i=0; i<0x1000; i++)
pD[i] = 0;
}*/
if ( boot_params.start.val )
{
char parameters[512];
char* rootfs;
char initrd[32];
char* tty_sel;
char* devfs_sel;
switch ( boot_params.root_sel.val )
{
case 0:
rootfs = "/dev/ram";
break;
case 1:
rootfs = "nfs";
break;
case 2:
rootfs = "/dev/mtdblock2";
break;
case 3:
rootfs = "/dev/mtdblock3";
break;
case 4:
rootfs = "/dev/hda1";
default:
rootfs = ""; //user define
break;
}
if ( boot_params.root_sel.val )
Uart_Printf( initrd , "load_ramdisk=0" );
else
Uart_Printf( initrd , "initrd=0x%08x,0x%08x" , boot_params.initrd_addr.val , boot_params.initrd_len.val );
switch ( boot_params.tty_sel.val )
{
case 0:
tty_sel = "ttyS0";
break;
case 1:
tty_sel = "ttyS1";
break;
case 2:
tty_sel = "tty1";
break;
default:
tty_sel = ""; //user define
break;
}
if ( boot_params.devfs_sel.val )
devfs_sel = "devfs=mount";
else
devfs_sel = "";
memset( parameters , 0 , sizeof( parameters ) );
Uart_Printf( parameters , "root=%s init=/linuxrc %s console=%s,%d mem=%dK %s %s" , rootfs , initrd , tty_sel ,
boot_params.serial_baud.val , boot_params.mem_cfg.val >> 10 , devfs_sel , boot_params.string );
params->u1.s.page_size = LINUX_PAGE_SIZE;
params->u1.s.nr_pages = ( boot_params.mem_cfg.val >> LINUX_PAGE_SHIFT );
memcpy( params->commandline , parameters , strlen( parameters ) );
Uart_Printf( "Set boot params = %s\n" , params->commandline );
}
StartPage = NandPart[1].offset >> 9;
size = NandPart[1].size;
ram_addr = buf;
Uart_Printf( "Load Kernel...\n" );
for ( i = 0; size > 0; )
{
if ( !( i & 0x1f ) )
{
if ( CheckBadBlk( i + StartPage ) )
{
Uart_Printf( "Skipped bad block at 0x%x\n" , i + StartPage );
i += 32;
size -= 32 << 9;
continue;
}
}
ReadPage( ( i + StartPage ) , ( U8 * ) ram_addr );
i++;
size -= 512;
ram_addr += 512;
}
if ( !boot_params.root_sel.val )
{
int ramdisk_sz;
Uart_Printf( "Load Ramdisk...\n" );
StartPage = NandPart[2].offset >> 9;
size = NandPart[1].size;
ram_addr = boot_params.initrd_addr.val;
ramdisk_sz = boot_params.initrd_len.val;
for ( i = 0; size > 0 && ramdisk_sz > 0; )
{
if ( !( i & 0x1f ) )
{
if ( CheckBadBlk( i + StartPage ) )
{
Uart_Printf( "Skipped bad block at 0x%x\n" , i + StartPage );
i += 32;
size -= 32 << 9;
continue;
}
}
ReadPage( ( i + StartPage ) , ( U8 * ) ram_addr );
i++;
size -= 512;
ram_addr += 512;
ramdisk_sz -= 512;
}
}
DsNandFlash();
//ChangeClockDivider(13,12);
//ChangeMPllValue(67,1,1); //300MHz,2440A!
//rCLKCON = 0x7fff0;
call_linux( 0 , boot_params.machine.val , buf );
}
/************************************************************/
static void InitNandFlash( int info )
{
U32 i;
InitNandCfg();
i = ReadChipId();
if ( info )
Uart_Printf( "Read chip id = %x\n" , i );
if ( ( i == 0x9873 ) || ( i == 0xec75 ) )
NandAddr = 0;
else if ( i == 0xec76 )
NandAddr = 1;
else
{
Uart_Printf( "Chip id error!!!\n" );
return;
}
if ( info )
Uart_Printf( "Nand flash status = %x\n" , ReadStatus() );
}
void NandErase( void )
{
int i, err = 0;
InitNandFlash( 1 );
i = NandSelPart( "erase" );
if ( i < 0 )
return;
Uart_Printf( "Are you sure to erase nand flash from page 0x%x, block count 0x%x ? [y/n]\n" , StartPage , BlockCnt );
while ( 1 )
{
char c;
c = Uart_Getch();
if ( ( c == 'y' ) || ( c == 'Y' ) )
break;
if ( ( c == 'n' ) || ( c == 'N' ) )
return;
}
for ( i = 0; BlockCnt; BlockCnt--, i += 32 )
{
if ( EraseBlock( i + StartPage ) )
{
err ++;
Uart_Printf( "Press any key to continue...\n" );
Uart_Getch();
}
}
DsNandFlash(); //disable nand flash interface
Uart_Printf( "Erase Nand partition completed " );
if ( err )
Uart_Printf( "with %d bad block(s)\n" , err );
else
Uart_Printf( "success\n" );
}
void NandWrite( void )
{
InitNandFlash( 1 );
WrFileToNF();
DsNandFlash(); //disable nand flash interface
}
void NandLoadRun( void )
{
InitNandFlash( 1 );
LoadRun();
}
/*
void TestNandFlash(void)
{
InitNandFlash();
while(1)
{
U8 key = '2';
Uart_Printf("\nNand flash operations, press ESC to exit\n");
Uart_Printf("1.Write nand flash with download file\n");
Uart_Printf("2.Load progam from nand flash and run\n");
Uart_Printf("3.Erase nand flash partition\n");
Uart_Printf("4.Test nand flash erase, write, read\n");
key = Uart_Getch();
if(key==0x1b)
goto TestNandExit;
else if(key=='1')
WrFileToNF();
else if(key=='2')
LoadRun();
else if(key=='3')
NandErase();
else if(key=='4')
TestFunc();
}
TestNandExit:
DsNandFlash(); //disable nand flash interface
}*/
int search_params( void )
{
U32 page, page_cnt;
U8 dat[528];
BootParams* pBP = ( BootParams* ) dat;
int ret = -1;
InitNandFlash( 0 ); //don't show info in InitNandFlash!
page = NandPart[0].offset >> 9;
page_cnt = NandPart[0].size >> 9;
//search from the last page
while ( page_cnt-- )
{
ReadPage( page + page_cnt , dat );
if ( !strncmp( boot_params.start.flags , pBP->start.flags , 10 ) )
{
ret = 0;
break;
}
}
if ( !ret )
{
ParamItem* pPIS = &pBP-> start, * pPID = &boot_params.start;
for ( ; pPID <= &boot_params.user_params; pPIS++, pPID++ )
if ( !strncmp( pPID->flags , pPIS->flags , sizeof( pPID->flags ) ) )
pPID->val = pPIS->val;
strncpy( boot_params.string , pPIS->flags , boot_params.user_params.val + 1 );
if ( boot_params.user_params.val != strlen( pPID->flags ) )
{
memset( boot_params.string , 0 , sizeof( boot_params.string ) );
boot_params.user_params.val = 0;
}
}
else
{
//Uart_Printf("Fail to find boot params! Use Default parameters.\n");
//don't Uart_Printf anything before serial initialized!
}
DsNandFlash();
return ret;
}
//保存在最后两个block,应确保程序(包括出现坏块时)不会覆盖到最后两块
int save_params( void )
{
U32 page, page_cnt;
U8 dat[528];
InitNandFlash( 1 );
memset( dat , 0 , sizeof( dat ) );
memcpy( dat , &boot_params , sizeof( boot_params ) );
page = ( NandPart[1].offset >> 9 ) - 64;
for ( page_cnt = 0; page_cnt < 64; page_cnt++ )
{
if ( !( page_cnt % 32 ) )
EraseBlock( page );
if ( !WritePage( page + page_cnt , dat ) )
break;
}
DsNandFlash();
Uart_Printf( "Save boot params %s.\n" , ( page_cnt >= 64 ) ? "fail" : "success" );
return page_cnt >= 64;
}
int set_params( void )
{
int i, key, chg = 0;
ParamItem* pPID;
Uart_Printf( "\nConfig parameters\n" );
do
{
pPID = &boot_params.start;
for ( i = 0; pPID <= &boot_params.user_params; pPID++, i++ )
Uart_Printf( "[%d] : %s%-8s is 0x%08x (%d)\n" , i , ( i > 9 ) ? "" : " ", pPID->flags, pPID->val, pPID->val );
Uart_Printf( "[%d] : Exit\n" , i );
if ( boot_params.user_params.val )
Uart_Printf( "User parameters is : \"%s\"\n" , boot_params.string );
Uart_Printf( "\nplease select item:" );
key = Uart_GetIntNum();
if ( key >= 0 && key < i )
{
chg = 1;
Uart_Printf( "please enter value:" );
i = key;
if ( ( &boot_params.start + i ) == &boot_params.user_params )
{
//确保输入的字节数不超过127!
char cmd[128];
memset( cmd , 0 , sizeof( cmd ) );
Uart_GetString( cmd );
strncpy( boot_params.string , cmd , strlen( cmd ) + 1 );
boot_params.user_params.val = strlen( cmd );
}
else
{
key = Uart_GetIntNum();
( &boot_params.start + i )->val = key;
}
}
else
break;
}
while ( 1 );
if ( chg )
{
Uart_Printf( "Do you want to save parameters? press y or Y for save.\n" );
key = Uart_Getch();
if ( key == 'y' || key == 'Y' )
save_params();
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -