📄 flash_nand.c
字号:
#include <define.h>#include <board_config.h>//#ifdef FLASH_TYPE_NAND#include <sl2312.h>#include "flash_drv.h"#include "flash_nand_parts.h"//#include <flash_nand_parts.h>// Low level debugging// 1 - command level - prints messages about read/write/erase commands// 2 - hardware level - shows all NAND device I/O dataUINT32 chip0_en=0,nwidth=0,ndirect=0x4000,def_width=0;UINT32 ADD,ADD2,ADD3,ADD4,ADD5;UINT32 opcode=0,nmode=1,ecc_cmp=0;UINT32 info_flash[12];UINT8 ck_buf[512];UINT8 ecc_buf[4];extern int nand_present;extern void FLASH_CTRL_WRITE_REG(unsigned int addr,unsigned int data);extern unsigned int FLASH_CTRL_READ_REG(unsigned int addr);//----------------------------------------------------------------------------// Now that device properties are defined, include magic for defining// accessor type and constants.//----------------------------------------------------------------------------// Information about supported devicesstatic const flash_dev_info_t* flash_dev_info;#define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))#define FLASH_BASE BOARD_FLASH_BASE_ADDR//----------------------------------------------------------------------------// Functions that put the flash device into non-read mode must reside// in RAM.void flash_query(void* data) ;static int flash_erase_block(void* block, unsigned int size);int flash_program_buf(void* addr, void* data, int len);//----------------------------------------------------------------------------/*unsigned int FLASH_CTRL_READ_REG(unsigned int addr){ unsigned int *base; unsigned int data; base = (unsigned int *)(SL2312_FLASH_CTRL_BASE + addr); data = *base; return (data);}void FLASH_CTRL_WRITE_REG(unsigned int addr,unsigned int data){ unsigned int *base; base = (unsigned int *)(SL2312_FLASH_CTRL_BASE + addr); *base = data; return;}*/unsigned int FLASH_READ_DMA_REG(unsigned int addr){ unsigned int *base; unsigned int data; base = (unsigned int *)(0x67000000 + addr); data = *base; return (data);}void FLASH_WRITE_DMA_REG(unsigned int addr,unsigned int data){ unsigned int *base; base = (unsigned int *)(0x67000000 + addr); *base = data; return;}unsigned int StatusCheck(UINT32 chip_en, UINT32 nwidth) //status check{ UINT8 status; RD_STATUS: FLASH_CTRL_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0 FLASH_CTRL_WRITE_REG(NFLASH_COUNT, 0x7f000070); //set only command no address and two data FLASH_CTRL_WRITE_REG(NFLASH_COMMAND_ADDRESS, 0x00000070); //write read status command opcode = 0x80002000|chip0_en|nwidth|ndirect; //set start bit & 8bits read command FLASH_CTRL_WRITE_REG(NFLASH_ACCESS, opcode); while(opcode&0x80000000) //polling flash access 31b { opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS); flash_delay(); } status=FLASH_CTRL_READ_REG(NFLASH_DATA); if(status==0) goto RD_STATUS; //printf("\n<--- StatusCheck : %x \n ",status); if(info_flash[5] < 528) { if(status!= 0xC0) goto RD_STATUS; if (status == 0xc0) return PASS; else return FAIL; } else { if(status!= 0xE0) goto RD_STATUS; if (status == 0xe0) return PASS; else return FAIL; }}/*void flash_delay(){ int i,j; for(i=0;i<0x100;i++) j=i*3+5;}*/// Initialize driver detailsintflash_hwr_init(FLASH_INFO_T *info){ UINT8 id[4]; int i; flash_query(id); // Check that flash_id data is matching the one the driver was // configured for. // Check manufacturer if ((id[0] != CYGNUM_FLASH_VENDOR_TOSHIBA)&&(id[0] != CYGNUM_FLASH_VENDOR_SAMSUNG)) { printf("Can't identify FLASH - manufacturer is: %x\n", id[0]); return FLASH_ERR_DRV_WRONG_PART; } // Look through table for device data flash_dev_info = supported_devices; for (i = 0; i < NUM_DEVICES; i++) { if (flash_dev_info->device_id == id[1]) break; flash_dev_info++; } // Did we find the device? If not, return error. if (NUM_DEVICES == i) { printf("Can't identify FLASH - device is: %x, supported: ", id[1]); for (i = 0; i < NUM_DEVICES; i++) { printf("%x ", supported_devices[i].device_id); } printf("\n"); return FLASH_ERR_DRV_WRONG_PART; } info_flash[1] = flash_dev_info->device_size >> 20; info_flash[2] = flash_dev_info->block_count ; info_flash[3] = flash_dev_info->block_size / flash_dev_info->page_size; //info_flash[4] = flash_dev_info->page_size+ (flash_dev_info->page_size>0x200)?64:16; info_flash[5] = flash_dev_info->page_size; info_flash[4] = info_flash[5] + (info_flash[5]>0x200?64:16); info_flash[6] = (flash_dev_info->page_size>0x200)?64:16; nand_present = 1; // Fill in device details //flash_info.block_size = flash_dev_info->block_size; //flash_info.blocks = flash_dev_info->block_count; //flash_info.start = (void *)BOARD_FLASH_BASE_ADDR; //flash_info.end = (void *)(BOARD_FLASH_BASE_ADDR+ flash_dev_info->device_size ); // Hard wired for now info->erase_block = (void *)flash_erase_block; info->program = (void *)flash_program_buf; info->block_size = flash_dev_info->block_size; info->blocks = flash_dev_info->block_count; info->start = (void *)FLASH_BASE; info->end = (void *)(FLASH_BASE+ (flash_dev_info->device_size)); info->vendor = id[0]; info->chip_id = id[1]; info->sub_id1 = 0; info->sub_id2 = 0; return FLASH_ERR_OK;}//----------------------------------------------------------------------------// Map a hardware status to a package errorstatic intflash_hwr_map_error(int e){ return e;}//----------------------------------------------------------------------------// See if a range of FLASH addresses overlaps currently running codestatic boolflash_code_overlaps(void *start, void *end){ extern unsigned char _stext[], _etext[]; return ((((unsigned long)&_stext >= (unsigned long)start) && ((unsigned long)&_stext < (unsigned long)end)) || (((unsigned long)&_etext >= (unsigned long)start) && ((unsigned long)&_etext < (unsigned long)end)));}static voidput_NAND(volatile UINT8 *ROM, UINT8 val){ *ROM = val;#if FLASH_DEBUG > 1 printf("%02x ", val);#endif}//----------------------------------------------------------------------------// Flash Query//// Only reads the manufacturer and part number codes for the first// device(s) in series. It is assumed that any devices in series// will be of the same type.voidflash_query(void* data){ UINT8* id = (UINT8*) data; UINT32 i, dent_bit; UINT8 m_code,d_code; dent_bit=FLASH_CTRL_READ_REG(FLASH_TYPE); if((dent_bit&0x800)==0x800) info_flash[11]=16; else info_flash[11]=8; FLASH_CTRL_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0 if((dent_bit&0x00000700)<=0x00000300) FLASH_CTRL_WRITE_REG(NFLASH_COUNT, 0x7f000100); //set only command & address and two data else FLASH_CTRL_WRITE_REG(NFLASH_COUNT, 0x7f000300); //set only command & address and 4 data FLASH_CTRL_WRITE_REG(NFLASH_COMMAND_ADDRESS, 0x00000090); //write read id command FLASH_CTRL_WRITE_REG(NFLASH_ADDRESS, 0x00000000); //write address 0x00 /* read maker code */ opcode = 0x80002000|chip0_en|nwidth|ndirect; //set start bit & 8bits read command FLASH_CTRL_WRITE_REG(NFLASH_ACCESS, opcode); opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS); while(opcode&0x80000000) //polling flash access 31b { opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS); flash_delay(); } if(nwidth == NFLASH_WiDTH8) { m_code=FLASH_CTRL_READ_REG(NFLASH_DATA); //FLASH_CTRL_WRITE_REG(NFLASH_DATA, 0x00000000); /* read device code */ opcode = 0x80002000|chip0_en|nwidth|ndirect; //set start bit & 8bits read command FLASH_CTRL_WRITE_REG(NFLASH_ACCESS, opcode); opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS); while(opcode&0x80000000) //polling flash access 31b { opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS); flash_delay(); } d_code = (FLASH_CTRL_READ_REG(NFLASH_DATA)>>8); dent_bit=FLASH_CTRL_READ_REG(FLASH_TYPE); if((dent_bit&0x700)>0x300) { for(i=0;i<2;i++) { //data cycle 3 & 4 ->not use opcode = 0x80002000|chip0_en|nwidth|ndirect; //set start bit & 8bits read command FLASH_CTRL_WRITE_REG(NFLASH_ACCESS, opcode); opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS); while(opcode&0x80000000) //polling flash access 31b { opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS); flash_delay(); } dent_bit=FLASH_CTRL_READ_REG(NFLASH_DATA); } } } else // 16-bit { dent_bit = FLASH_CTRL_READ_REG(NFLASH_DATA); m_code = dent_bit; d_code = dent_bit>>8; //data cycle 3 & 4 ->not use dent_bit=FLASH_CTRL_READ_REG(FLASH_TYPE); if(((dent_bit&0x700)>0x300)&&(nwidth == NFLASH_WiDTH16)) { opcode = 0x80002000|chip0_en|nwidth|ndirect; //set start bit & 8bits read command FLASH_CTRL_WRITE_REG(NFLASH_ACCESS, opcode); opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS); while(opcode&0x80000000) //polling flash access 31b { opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS); flash_delay(); } dent_bit=FLASH_CTRL_READ_REG(NFLASH_DATA); } } printf("\rManufacturer's code is %x\n", m_code); printf("Device code is %x\n", d_code); id[0] = m_code; // vendor ID id[1] = d_code; // device ID opcode = 0x4000; FLASH_CTRL_WRITE_REG(NFLASH_ACCESS,opcode);}//----------------------------------------------------------------------------// Erase Blockstatic intflash_erase_block(void* block, unsigned int size){ UINT32 page_add = (UINT32)block; page_add -=0x30000000; page_add = page_add / info_flash[5]; FLASH_CTRL_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0 if(info_flash[1]>=64) FLASH_CTRL_WRITE_REG(NFLASH_COUNT, 0x7f0fff21); //3 address & 2 command else FLASH_CTRL_WRITE_REG(NFLASH_COUNT, 0x7f0fff11); //2 address & 2 command FLASH_CTRL_WRITE_REG(NFLASH_COMMAND_ADDRESS, 0x0000d060); //write read id command FLASH_CTRL_WRITE_REG(NFLASH_ADDRESS, page_add); //write address 0x00 /* read maker code */ opcode = 0x80003000|chip0_en|nwidth|ndirect; //set start bit & 8bits write command FLASH_CTRL_WRITE_REG(NFLASH_ACCESS, opcode); while(opcode&0x80000000) //polling flash access 31b { opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS); flash_delay(); } //printf("\n--->BlockErase: \n"); if(StatusCheck(chip0_en, def_width)!=FAIL) return FLASH_ERR_OK; else return FLASH_ERR_ERASE; }//// ECC support - adapted from Linux://// drivers/mtd/nand_ecc.c//// Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)// Toshiba America Electronics Components, Inc.//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -