⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash.c

📁 嵌入式LINUX中FLASH的驱动源码。可以用于ARM7、ARM9、AMD等系统中。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************      Include files************************************************************************/#include <linux/types.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/miscdevice.h>#include <linux/module.h>#include <linux/init.h>#include <linux/ctype.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/page.h>#include <asm/io.h>#include <linux/vmalloc.h>#include <linux/mm.h>#include <linux/wrapper.h>#include <linux/version.h>#include <linux/delay.h>#include "flash.h"#define MAJOR_NUM 222#define DRIVER_NAME  "flash"static int cnt_open=0;unsigned char *flash_mem;//define kernel size 1.25Mbyte#define KERNEL_SIZE 0x100000#define KERNEL_BASE 0x81000000#define FLASH_BASE 0xBF800000#define FLASH_END  0xBFBFFFFF#define ERASE_FLASH 0#define READ_FLASH 1#define WRITE_FLASH 2#define UUPDATE_FLASH 3#define FLASH_16BIT#define ADDR0           0x555#define ADDR1           0x2aa#define FLASH_WORD_SIZE unsigned shorttypedef unsigned char		UINT8;typedef signed char		INT8;typedef unsigned short		UINT16;typedef signed short		INT16;typedef unsigned int		UINT32;typedef signed int		INT32;#define KSEG_MSK		  0xE0000000#define KSEG1BASE		  0xA0000000#define iKSEG1(addr)              (((UINT32)(addr) & ~KSEG_MSK) | KSEG1BASE)struct ioctl {	unsigned int addr;	unsigned int data;}; flash_info_t flash_info[1];static void * rvmalloc(unsigned long size){	void * mem;	unsigned long adr;	size=PAGE_ALIGN(size);	mem=vmalloc_32(size);	if (mem) 	{		memset(mem, 0, size); 	        adr=(unsigned long) mem;		while (size > 0)                 {			mem_map_reserve(vmalloc_to_page((void *)adr));			adr+=PAGE_SIZE;			size-=PAGE_SIZE;		}	}	return mem;}static void rvfree(void * mem, unsigned long size){        unsigned long adr,siz=size;	if (mem) 	{	        adr=(unsigned long) mem;		while ( siz > 0)                 {			mem_map_unreserve(vmalloc_to_page((void *)adr));			adr+=PAGE_SIZE;			siz-=PAGE_SIZE;		}		vfree(mem);	}}static ulong flash_get_size (vu_long *addr, flash_info_t *info){	short i,n;	FLASH_WORD_SIZE value,value1;	ulong base = (ulong)addr;        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;	/* Write auto select command: read Manufacturer ID */	addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;	udelay(100);	addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;	udelay(100);	addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090;	udelay(100);	value = addr2[0];//	printk(KERN_INFO "########First ManuD : 0x%04x########\n", value);	switch (value) {	case (FLASH_WORD_SIZE)AMD_MANUFACT:		info->flash_id = FLASH_MAN_AMD;		break;	case (FLASH_WORD_SIZE)MX_MANUFACT:		info->flash_id = FLASH_MAN_MX;		break;	case (FLASH_WORD_SIZE)FUJ_MANUFACT:		info->flash_id = FLASH_MAN_FUJ;		break;	default:			/* Write auto select command: read Manufacturer ID */	             /*Detect for FUJ_FLASH*/		udelay(100);		addr2[0x5555] = (FLASH_WORD_SIZE)0x00AA00AA;		udelay(100);		addr2[0x2aaa] = (FLASH_WORD_SIZE)0x00550055;		udelay(100);		addr2[0x5555] = (FLASH_WORD_SIZE)0x00900090;		udelay(100);		value = addr2[0];//		printk("########Re-read ManuD : 0x%04x########\n", value);		if(value==(FLASH_WORD_SIZE)FUJ_MANUFACT)		{			info->flash_id = FLASH_MAN_FUJ;			break;					}		else		{			info->flash_id = FLASH_UNKNOWN;			info->sector_count = 0;			info->size = 0;			return (0);			/* no or unknown flash	*/		}		break;			}	udelay(100);	value = addr2[1];				/* device ID		*///printk(KERN_INFO "########DeviceID : 0x%08x########\n", value);	switch (value) {	case (FLASH_WORD_SIZE)FUJI_ID_29LV650UE:		info->flash_id += FLASH_FUJLV650;		info->sector_count = 128;		info->size = 0x00800000;		break;				/* => 8 MB		*/	case (FLASH_WORD_SIZE)MX_ID_LV640T:		info->flash_id += FLASH_MX29LV640T;		info->sector_count = 135;		info->size = 0x00800000;		break;		case (FLASH_WORD_SIZE)MX_ID_LV640B:		info->flash_id += FLASH_MX29LV640B;		info->sector_count = 135;		info->size = 0x00800000;		break;					case (FLASH_WORD_SIZE)AMD_ID_DL640:		udelay(100);		value1=addr2[0x0e];	//	printk(KERN_INFO "########DeviceID sub1: 0x%08x########\n", value1);				if(value1==0x2202)		{			info->flash_id += FLASH_AMDL640;			info->sector_count = 142;			info->size = 0x00800000;		}		else if(value1==0x2210)		{			info->flash_id += FLASH_S29GL064;			info->sector_count = 135;			info->size = 0x00800000;		}		else		{			info->flash_id = FLASH_UNKNOWN;			return (0);			/* => no or unknown flash */					}		break;				/* => 8 MB		*/			default:		info->flash_id = FLASH_UNKNOWN;		return (0);			/* => no or unknown flash */	}	/* set up sector start address table */        if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||	    (info->flash_id  == FLASH_AM040))	{	    for (i = 0; i < info->sector_count; i++)		info->start[i] = base + (i * 0x00010000);        }	else if((info->flash_id & FLASH_TYPEMASK) ==FLASH_AMDL640)	{			/* set sector offsets for dual boot block type		*///			printk(KERN_INFO "########AM29DL640 offset########\n");		for (i=0; i<8; ++i) 		{		/*  8 x 8k boot sectors	*/			info->start[i] = base;			base += 8 << 10;		}		n = info->sector_count - 8;		while (i < n) 		{			/* 64k regular sectors	*/			info->start[i] = base;			base += 64 << 10;			++i;		}		while (i < info->sector_count) 		{ /* 8 x 8k boot sectors	*/			info->start[i] = base;			base += 8 << 10;			++i;		}			}	else if(((info->flash_id & FLASH_TYPEMASK) ==FLASH_S29GL064)||((info->flash_id & FLASH_TYPEMASK) ==FLASH_MX29LV640T))	{			/* set sector offsets for top boot block type		*///			printk(KERN_INFO "########MX29lv640T S29GL064R3 offset########\n");		i=0;		n = info->sector_count - 8;		while (i < n) 		{			/* 64k regular sectors	*/			info->start[i] = base;			base += 64 << 10;			++i;		}		while (i < info->sector_count) 		{ /* 8 x 8k boot sectors	*/			info->start[i] = base;			base += 8 << 10;			++i;		}		}	else if((info->flash_id & FLASH_TYPEMASK) ==FLASH_MX29LV640B)	{			/* set sector offsets for bottom boot block type		*/	//		printk(KERN_INFO "########MX29lv640B offset########\n");		i=0;		for (i=0; i<8; ++i) 		{		/*  8 x 8k boot sectors	*/			info->start[i] = base;			base += 8 << 10;		}		while (i < info->sector_count) 		{			/* 64k regular sectors	*/			info->start[i] = base;			base += 64 << 10;			++i;		}		}			else 	{	    if (info->flash_id & FLASH_BTYPE) 	    {		/* set sector offsets for bottom boot block type	*/		info->start[0] = base + 0x00000000;		info->start[1] = base + 0x00004000;		info->start[2] = base + 0x00006000;		info->start[3] = base + 0x00008000;		for (i = 4; i < info->sector_count; i++) 		{			info->start[i] = base + (i * 0x00010000) - 0x00030000;		}	    } 	    else 	    {		/* set sector offsets for top boot block type		*/		i = info->sector_count - 1;		info->start[i--] = base + info->size - 0x00004000;		info->start[i--] = base + info->size - 0x00006000;		info->start[i--] = base + info->size - 0x00008000;			for (; i >= 0; i--) 		{			info->start[i] = base + i * 0x00010000;		}	    }	}	/* check for protected sectors */	for (i = 0; i < info->sector_count; i++) 	{		info->protect[i] =0;	}	/*	 * Prevent writes to uninitialized FLASH.	 */ 	addr2 = (FLASH_WORD_SIZE *)info->start[0];	*addr2 = (FLASH_WORD_SIZE)0x00F000F0;	/* reset bank */	return (info->size);}static void flash_get_offsets (ulong base, flash_info_t *info){	int i,n;	/* set up sector start address table */        if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||	    (info->flash_id  == FLASH_AM040)){	    for (i = 0; i < info->sector_count; i++)		info->start[i] = base + (i * 0x00010000);        }	else if((info->flash_id & FLASH_TYPEMASK) ==FLASH_AMDL640)	{		/* set sector offsets for dual boot block type		*/		for (i=0; i<8; ++i) 		{		/*  8 x 8k boot sectors	*/			info->start[i] = base;			base += 8 << 10;		}		n = info->sector_count - 8;		while (i < n) 		{			/* 64k regular sectors	*/			info->start[i] = base;			base += 64 << 10;			++i;		}		while (i < info->sector_count) 		{ /* 8 x 8k boot sectors	*/			info->start[i] = base;			base += 8 << 10;			++i;		}			}	else if(((info->flash_id & FLASH_TYPEMASK) ==FLASH_S29GL064)||((info->flash_id & FLASH_TYPEMASK) ==FLASH_MX29LV640T))	{			/* set sector offsets for top boot block type		*///			printk(KERN_INFO "########MX29lv640T S29GL064R3 offset########\n");		i=0;		n = info->sector_count - 8;		while (i < n) {			/* 64k regular sectors	*/			info->start[i] = base;			base += 64 << 10;			++i;		}		while (i < info->sector_count) { /* 8 x 8k boot sectors	*/			info->start[i] = base;			base += 8 << 10;			++i;		}		}	else if((info->flash_id & FLASH_TYPEMASK) ==FLASH_MX29LV640B)	{			/* set sector offsets for bottom boot block type		*///			printk(KERN_INFO "########MX29lv640B offset########\n");		i=0;		for (i=0; i<8; ++i) 		{		/*  8 x 8k boot sectors	*/			info->start[i] = base;			base += 8 << 10;		}		while (i < info->sector_count) 		{			/* 64k regular sectors	*/			info->start[i] = base;			base += 64 << 10;			++i;		}		}			else 	{	    if (info->flash_id & FLASH_BTYPE) 	    {		/* set sector offsets for bottom boot block type	*/		info->start[0] = base + 0x00000000;		info->start[1] = base + 0x00004000;		info->start[2] = base + 0x00006000;		info->start[3] = base + 0x00008000;		for (i = 4; i < info->sector_count; i++) 		{			info->start[i] = base + (i * 0x00010000) - 0x00030000;		}	    } 	    else 	    {		/* set sector offsets for top boot block type		*/		i = info->sector_count - 1;		for (; i >= 0; i--) 		{			info->start[i] = base + i * 0x00010000;		}

⌨️ 快捷键说明

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