flash_amd.c

来自「ADS下的bios工程」· C语言 代码 · 共 712 行 · 第 1/2 页

C
712
字号
#include <bios/s3c2410x.h>#include <bios/stdio.h>#include <bios/flash_amd.h>struct flashinfo *meminfo; /* A pointer into a specific field defined in memdesc below */struct flashinfo memdesc[] = {	 /* DL800T */	{"Am29DL800T", 0L, 0, 22, 14, 0 ,{	{65536,     0x00000,    2},	{65536,     0x10000,    2},	{65536,     0x20000,    2},	{65536,     0x30000,    2},	{65536,     0x40000,    2},	{65536,     0x50000,    2},	{65536,     0x60000,    2},	{65536,     0x70000,    2},	{65536,     0x80000,    2},	{65536,     0x90000,    2},	{65536,     0xA0000,    2},	{65536,     0xB0000,    2},	{65536,     0xC0000,    2},	{65536,     0xD0000,    2},	{16384,     0xE0000,    1},	{32768,     0xE4000,    1},	{8192,      0xEC000,    1},	{8192,      0xEE000,    1},	{8192,      0xF0000,    1},	{8192,      0xF2000,    1},	{32768,     0xF4000,    1},	{16384,     0xFC000,    1}	}	 },	 /* DL800B */	{"Am29DL800B", 0L, 0, 22, 0, 8 ,{	{16384,     0x00000,    1},	{32768,     0x04000,    1},	{8192,      0x0C000,    1},	{8192,      0x0E000,    1},	{8192,      0x10000,    1},	{8192,      0x12000,    1},	{32768,     0x14000,    1},	{16384,     0x1C000,    1},	{65536,     0x20000,    2},	{65536,     0x30000,    2},	{65536,     0x40000,    2},	{65536,     0x50000,    2},	{65536,     0x60000,    2},	{65536,     0x70000,    2},	{65536,     0x80000,    2},	{65536,     0x90000,    2},	{65536,     0xA0000,    2},	{65536,     0xB0000,    2},	{65536,     0xC0000,    2},	{65536,     0xD0000,    2},	{65536,     0xE0000,    2},	{65536,     0xF0000,    2}	}	},	 /* LV800T */	{"Am29LV800T", 0L, 0, 19, 0, 4 ,{	{65536,     0x00000,    1},	{65536,     0x10000,    1},	{65536,     0x20000,    1},	{65536,     0x30000,    1},	{65536,     0x40000,    1},	{65536,     0x50000,    1},	{65536,     0x60000,    1},	{65536,     0x70000,    1},	{65536,     0x80000,    1},	{65536,     0x90000,    1},	{65536,     0xA0000,    1},	{65536,     0xB0000,    1},	{65536,     0xC0000,    1},	{65536,     0xD0000,    1},	{65536,     0xE0000,    1},	{32768,     0xF0000,    1},	{8192,      0xF8000,    1},	{8192,      0xFA000,    1},	{16384,     0xFC000,    1}	}	},	 /* LV800B */	{"Am29LV800B", 0L, 0, 19, 0, 4 ,{	{16384,     0x00000,    1},	{8192,      0x04000,    1},	{8192,      0x06000,    1},	{32768,     0x08000,    1},	{65536,     0x10000,    1},	{65536,     0x20000,    1},	{65536,     0x30000,    1},	{65536,     0x40000,    1},	{65536,     0x50000,    1},	{65536,     0x60000,    1},	{65536,     0x70000,    1},	{65536,     0x80000,    1},	{65536,     0x90000,    1},	{65536,     0xA0000,    1},	{65536,     0xB0000,    1},	{65536,     0xC0000,    1},	{65536,     0xD0000,    1},	{65536,     0xE0000,    1},	{65536,     0xF0000,    1}	}	},	/* LV160B - same as LV800B, but limited to 2MB addressing window*/	{"Am29LV160B", 0L, 0, 35, 0, 0 ,{	{16384,     0x00000,    1},	{8192,      0x04000,    1},	{8192,      0x06000,    1},	{32768,     0x08000,    1},	{65536,     0x10000,    1},	{65536,     0x20000,    1},	{65536,     0x30000,    1},	{65536,     0x40000,    1},	{65536,     0x50000,    1},	{65536,     0x60000,    1},	{65536,     0x70000,    1},	{65536,     0x80000,    1},	{65536,     0x90000,    1},	{65536,     0xA0000,    1},	{65536,     0xB0000,    1},	{65536,     0xC0000,    1},	{65536,     0xD0000,    1},	{65536,     0xE0000,    1},	{65536,     0xF0000,    1}	}	},	/* LV400B */	{"Am29LV400B", 0L, 0, 11, 0, 0 ,{	{16384,     0x00000,    1},	{8192,      0x04000,    1},	{8192,      0x06000,    1},	{32768,     0x08000,    1},	{65536,     0x10000,    1},	{65536,     0x20000,    1},	{65536,     0x30000,    1},	{65536,     0x40000,    1},	{65536,     0x50000,    1},	{65536,     0x60000,    1},	{65536,     0x70000,    1},	}	}};extern void dbgout(char *fmt, ...);volatile unsigned short *flashptr;  /* flash window (64K bytes) */volatile unsigned short *get_flash_memptr(int sector){	return (volatile unsigned short *)PHYS_ROM_BASE;	/* 0x00000000, non-cacheable */}/*********************************************************************//* init_flash() performs any initial memory allocation, setting of   *//* parameters, and also initializes the appropriate sector table     *//* defined above.                                                    *//* Memory mapping or allocation specifics will need to be provided   *//* by the programmer of the driver, and will be highly dependant on  *//* on the system being used.                                         *//*********************************************************************/unsigned int init_flash(unsigned int flashtype){	/* Insert any memory initialization or memory mapping here */	meminfo = &memdesc[flashtype];	return(1);}/*********************************************************************//* Flash_command() is the main driver function.  It performs         *//* every possible command available to AMD B revision                *//* flash parts. Note that this command is not used directly, but     *//* rather called through the API wrapper functions provided below.   *//* This function can be called directly if desired (see wrapper      *//* functions defined below.                                          *//*********************************************************************/void flash_command(int command, int sector, int offset, unsigned int data){	static int oldsector = -1;	int retry, stat;              	/**************************************************************/	/* IMPORTANT: Note that flashptr is defined as a WORD pointer */       	/* If BYTE pointers are used, the command tables will have to */       	/* be remapped						       */       	/* Note 1: flashptr is declared far - if system does not      */       	/*         support far pointers, this will have to be changed */       	/* Note 2: flashptr is declared static to avoid calling       */       	/*         get_flash_memptr() on successive sector accesses   */       	/**************************************************************/	/******************************************************************/	/* On systems where bus glitching is prevalent, some long command */  	/* strings may be interrupted and cause the command to fail (this */       	/* is most probable on six cycle commands such as chip erase). In */       	/* order to ensure that flash_command executes the command        */       	/* properly, it may be necessary to issue the command more than   */       	/* once in order for it to be accepted by the flash device.  In   */       	/* these cases it is recommended that the retry number be made    */       	/* positive (such as 1 or 2), so that flash_command will try      */       	/* to issue the command more than once.  Keep in mind that this   */       	/* will only be attempted if the command fails in the first       */       	/* attempt.                                                       */       	/******************************************************************/                	static int retrycount[] = {0,0,0,0,0,0,0,0,0,0};	retry = retrycount[command];	if(sector != oldsector) {		flashptr = (unsigned short *) get_flash_memptr(sector);	}	if (command == FLASH_SELECT) {		return;	} else if (command == FLASH_RESET || command > FLASH_LASTCMD) {		flashptr[0] = 0xF0;   /* assume reset device to read mode */	} else if (command == FLASH_ESUSPEND) {		flashptr[0] = 0xB0;   /* suspend sector erase */	} else if (command == FLASH_ERESUME) {		flashptr[0] = 0x30;   /* resume suspended sector erase */	} else if (command == FLASH_UBPROG) {		flashptr[0] = 0xA0;		flashptr[((meminfo->sec[sector].base)+offset)/2] = data;	} else if (command == FLASH_UBRESET) {		flashptr[0] = 0x90;		flashptr[0] = 0x00;	}	else {		flashptr[0x555] = 0xAA;       /* unlock 1 */		flashptr[0x2AA] = 0x55;       /* unlock 2 */		switch (command) {			case FLASH_AUTOSEL:				flashptr[0x555] = 0x90;				return;				break;			case FLASH_PROG:				flashptr[0x555] = 0xA0;				flashptr[((meminfo->sec[sector].base)+offset)/2] = data;				break;			case FLASH_CERASE:				flashptr[0x555] = 0x80;				flashptr[0x555] = 0xAA;				flashptr[0x2AA] = 0x55;				flashptr[0x555] = 0x10;				break;			case FLASH_SERASE:				flashptr[0x555]  = 0x80;				flashptr[0x555]  = 0xAA;				flashptr[0x2AA]  = 0x55;				flashptr[(meminfo->sec[sector].base)/2] = 0x30;				break;			case FLASH_UB:				flashptr[0x555] = 0x20;				break;		}	}	while ((stat = flash_status(get_flash_memptr(sector))) == STATUS_BUSY) { }	if (stat != STATUS_READY) {		dbgout("%s[%d] : status(%x)\n", __FUNCTION__, __LINE__, stat);	}}/*********************************************************************//* Flash_write extends the functionality of flash_program() by       *//* providing an faster way to program multiple data words, without   *//* needing the function overhead of looping algorithms which         *//* program word by word.  This function utilizes fast pointers       *//* to quickly loop through bulk data.                                *//*********************************************************************/int flash_write(int sector, unsigned short offset, unsigned char *buf, unsigned int nbytes, int ub){	unsigned short *src, *dst;	int stat = 0;	int retry = 2, retried = 0;	flashptr = (unsigned short *)get_flash_memptr(sector);	flashptr += (meminfo->sec[sector].base)/2;	dst = (unsigned short *)(flashptr + offset/2);		/* (byte offset) */	src = (unsigned short *)buf;	if ((nbytes | (unsigned int)offset) & 1) {		/* IS Odd ??? */		return -1;	}again:	/* Check to see if we're in unlock bypass mode */       	if (ub == FALSE)		flash_command(FLASH_RESET,sector,0,0);	while (nbytes > 0) {		if (ub == FALSE){			flashptr[0x555] = 0xAA;		/* unlock 1 */			flashptr[0x2AA] = 0x55;		/* unlock 2 */		}		flashptr[0x555] = 0xA0;		*dst++ = *src++;		while ((stat = flash_status(flashptr)) == STATUS_BUSY) { }		if (stat != STATUS_READY){			if(stat == STATUS_TIMEOUT){				dst--; src--;				if(*dst != *src){					dbgout("%s[%d] : DST(%x:%x), SRC(%x:%x)\n", __FUNCTION__, __LINE__, dst, *dst, src, *src);					continue;				}else{					dst++;					src++;				}			}else{				dbgout("%s[%d] : status(%x)\n", __FUNCTION__, __LINE__, stat);				break;			}		}		nbytes -= 2;	}	if (stat != STATUS_READY || nbytes != 0) {		if (retry-- > 0) {			++retried;			--dst, --src;   /* back up */			goto again;     /* and retry the last word */		}		if (ub == FALSE)       			flash_command(FLASH_RESET,sector,0,0);	}	return (unsigned short *)src - (unsigned short *)buf;}/*********************************************************************//* Flash_status utilizes the DQ6, DQ5, and DQ3 polling algorithms    *//* described in the flash data book.  It can quickly ascertain the   *//* operational status of the flash device, and return an             *//* appropriate status code (defined in flash.h)                      *//*********************************************************************/ int flash_status(volatile unsigned short *fp){	unsigned char d, t;	int retry = 1;again:	d = (unsigned char)*fp;		/* read data */	t = d ^ (unsigned char)*fp;	/* read it again and see what toggled */	if (t == 0) {			/* no toggles, nothing's happening */		return STATUS_READY;	}	else if (t == 0x04) {			/* erase-suspend */		if (retry--) goto again;	/* may have been write completion */		return STATUS_ERSUSP;	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?