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 + -
显示快捷键?