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

📄 flash.c

📁 嵌入式LINUX中FLASH的驱动源码。可以用于ARM7、ARM9、AMD等系统中。
💻 C
📖 第 1 页 / 共 2 页
字号:
	    }	}}unsigned long flash_get_info (void){	unsigned long size_b0, size_b1;	int i;	/* Init: no FLASHes known */	for (i=0; i<1; ++i) {		flash_info[i].flash_id = FLASH_UNKNOWN;	}	/* Static FLASH Bank configuration here - FIXME XXX */	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);	if (flash_info[0].flash_id == FLASH_UNKNOWN) 	{		printk(KERN_INFO "## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",			size_b0, size_b0<<20);	}	/* Only one bank */	if (1)	  {	    flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);	    size_b1 = 0 ;	    flash_info[0].size = size_b0;	  }	return (size_b0 + size_b1);}int flash_erase_(struct file *file,unsigned int startaddr, unsigned int endaddr){	int i;	unsigned int *addr;	//printk(KERN_INFO "erase startadr:0x%X\tendaddr:0x%X\n", startaddr, endaddr);	endaddr = iKSEG1(endaddr);	addr = (unsigned int *)iKSEG1(startaddr);	while((unsigned int)addr < endaddr) 	{		addr[0x555] = (unsigned short)0x00AA00AA;		addr[0x2AA] = (unsigned short)0x00550055;		addr[0x555] = (unsigned short)0x00800080;		addr[0x555] = (unsigned short)0x00AA00AA;		addr[0x2AA] = (unsigned short)0x00550055;		addr[0] = (unsigned short)0x00300030;  		for(i=0; i<50; i++)			udelay(1000);		addr += 0x10000;			}	udelay (1000);	//printk(KERN_INFO "erase flash device succes\n");		return 0;}int flash_write(struct file *file,unsigned int addr, unsigned int data){	//printk(KERN_INFO "write flash device\n");	volatile unsigned short *dest2 = (unsigned short *) addr;	volatile unsigned short *data2 = (unsigned short *) &data;	dest2[0] = data2[0];	dest2[1] = data2[1];	//printk(KERN_INFO "addr:0x%X\tdata:%d\n",addr, data);		return 0;}int flash_read(struct file *file, unsigned int addr, unsigned int data) {	//printk(KERN_INFO "read flash device\n");	volatile unsigned short *dest2 = (unsigned short *) addr;	volatile unsigned short *data2 = (unsigned short *) &data;	data2[0] = dest2[0];	data2[1] = dest2[1];	//printk(KERN_INFO "addr:0x%X\tdata:%d\n",addr, data);		return 0;}INT32 program_flash(unsigned short *src,unsigned long dst,int length){    int             	i, len;    volatile short 	*psrc;    volatile short 	*pdst;    volatile short	*flash;    psrc = src;    pdst = (short*)iKSEG1(dst);    len  = length;    flash = (short *)((long)pdst & 0xffc00000);		// command base address    if (len <= 0)    {        printk("len <= 0\n");        return  0;    }    if( ((UINT32)psrc & 0x00000001) || ((UINT32)pdst & 0x00000001))    {	printk("alignment error,src=0x%08x,dst=0x%08x",(UINT32)psrc,(UINT32)pdst);	return(-2);    }    for ( i = 0; i < len; i += 2)    {        flash[0x555] = 0x00AA;        flash[0x2AA] = 0x0055;        flash[0x555] = 0x00A0;        *pdst = *psrc;	udelay(1000);        if ( *pdst != *psrc )        {//	    printk("Data check read:(0x%08x)=0x%08x,Data written:0x%08x\n",(UINT32)pdst,*pdst,*psrc);            return -2;        }        ++pdst;        ++psrc;    }    return 0;}int wait_for_DQ7(flash_info_t *info, int sect){	volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);	while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080)     	{       			udelay(10);    	}	return 0;}int	flash_erase (flash_info_t *info, ulong a_first, ulong a_last){	volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);	volatile FLASH_WORD_SIZE *addr2;	ulong  prot, sect, l_sect,s_first,s_last;	int i;		if(a_first < info->start[0] || a_first > a_last)	{		printk(KERN_INFO "input addr error\n");		return 1;	}/*	for(i=0;i<info->sector_count - 1; i++)	{	   printk(KERN_INFO "sector %ld,start=%X\n",i,info->start[i]);	}*/		for(i = 0; i < info->sector_count - 1; i++)	{		if(a_first < info->start[i])		{			s_first = i - 1;			break;		}	}	if(a_first >= info->start[info->sector_count - 1])		s_first = info->sector_count - 1;			for(i = 0; i < info->sector_count - 1; i++)	{		if(a_last <= info->start[i])		{			s_last = i-1;			break;		}	}		if(a_last >= info->start[info->sector_count - 1])		s_last = info->sector_count - 1;        printk(KERN_INFO "s_first=%ld,slast=%ld\n",s_first,s_last);			if ((s_first < 0) || (s_first > s_last)) 	{		if (info->flash_id == FLASH_UNKNOWN) 		{			printk (KERN_INFO "- missing\n");		} 		else 		{			printk (KERN_INFO "- no sectors to erase\n");		}		return 1;	}		//printk(KERN_INFO "start erase flash,s_first = %d\ts_last=%d\n",s_first,s_last);	if (info->flash_id == FLASH_UNKNOWN) 	{		printk (KERN_INFO "Can't erase unknown flash type - aborted\n");		return 1;	}	prot = 0;	l_sect = -1;	for (sect = s_first; sect<=s_last; sect++) 	{		    addr2 = (FLASH_WORD_SIZE *)(info->start[sect]);		    printk (KERN_INFO "Erasing sector %p\n", addr2);	// CLH		    if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) 		    {			addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;			addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;			addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;			addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;			addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;			addr2[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */			for (i=0; i<50; i++)				udelay(1000);  /* wait 1 ms */		    }		   else if((info->flash_id & FLASH_TYPEMASK) == FLASH_FUJLV650)		   {			addr[0x5555] = (FLASH_WORD_SIZE)0x00AA00AA;			addr[0x2aaa] = (FLASH_WORD_SIZE)0x00550055;			addr[0x5555] = (FLASH_WORD_SIZE)0x00800080;			addr[0x5555] = (FLASH_WORD_SIZE)0x00AA00AA;			addr[0x2aaa] = (FLASH_WORD_SIZE)0x00550055;			addr2[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */		   			   }		   else 		   {			addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;			addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;			addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;			addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;			addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;			addr2[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */		    }		    l_sect = sect;		    wait_for_DQ7(info, sect);	}	udelay (1000);	addr = (FLASH_WORD_SIZE *)info->start[0];	addr[0] = (FLASH_WORD_SIZE)0x00F000F0;	/* reset bank */	return 0;}int write_word (flash_info_t * info, ulong dest, ulong data){	volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) (info->start[0]);	volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;	volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;	int i;	/* Check if Flash is (sufficiently) erased */	if ((*((volatile FLASH_WORD_SIZE *) dest) &	    (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) 	{		return (2);	}	for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) 	{		if((info->flash_id & FLASH_TYPEMASK) == FLASH_FUJLV650)		{			addr2[0x5555] = (FLASH_WORD_SIZE) 0x00AA00AA;			addr2[0x2aaa] = (FLASH_WORD_SIZE) 0x00550055;			addr2[0x5555] = (FLASH_WORD_SIZE) 0x00A000A0;		}		else		{			addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;			addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;			addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0;		}		dest2[i] = data2[i];		while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=		       (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) 	        {				udelay(1);				}	}     // printk(KERN_INFO "write word finished!\n");	return (0);}static int flash_ioctl(struct inode *inode,struct file *_file,unsigned int cmd,unsigned long arg){	struct ioctl a;	int i;	volatile unsigned short *dest2;	volatile unsigned short *data2;	unsigned int baseaddr;			switch(cmd){		case ERASE_FLASH:			//printk(KERN_INFO "erase flash device\n");			copy_from_user(&a, (unsigned short *)arg, sizeof(struct ioctl));			flash_erase(flash_info, a.addr, a.data);			break;		case READ_FLASH:			//printk(KERN_INFO "read flash device\n");			copy_from_user(&a, (unsigned short *)arg, sizeof(struct ioctl));			//flash_read(_file, a.addr, a.data);			(unsigned short *)dest2 = (unsigned short *)a.addr;			(unsigned short *)data2 = (unsigned short *)&(a.data);			data2[0] = dest2[0];			data2[1] = dest2[1];			copy_to_user((unsigned short *)arg, &a, sizeof(struct ioctl));			break;				case WRITE_FLASH:			//printk(KERN_INFO "wite flash device\n");			copy_from_user(&a, (unsigned short *)arg, sizeof(struct ioctl));			//flash_write(_file, a.addr, a.data);			write_word(flash_info, a.addr, a.data);					break;		case UUPDATE_FLASH:			//printk(KERN_INFO "update flash device\n");			copy_from_user(&a, (unsigned short *)arg, sizeof(struct ioctl));					//擦除整个FLASH地址空间			//ret = flash_erase(flash_info, FLASH_BASE, FLASH_END);						for(i=0; i<50; i++)				udelay(1000);						baseaddr = KERNEL_BASE;			program_flash((unsigned short*)flash_mem,(unsigned int)FLASH_BASE,KERNEL_SIZE);			break;		default:			return -EINVAL;	}	return -EINVAL;}static inline unsigned long kvirt_to_pa(unsigned long adr) {        unsigned long kva, ret;	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));	kva |= adr & (PAGE_SIZE-1);	ret = __pa(kva);        return ret;}static int flash_mmap(struct file *file,struct vm_area_struct *vma){	unsigned long start=vma->vm_start;	unsigned long offset,pos;	unsigned long size=vma->vm_end-vma->vm_start;	pos=(unsigned long)flash_mem;	while(size>0)	{			offset=kvirt_to_pa(pos);		if(remap_page_range(start,offset,PAGE_SIZE,PAGE_SHARED))			return -EAGAIN;		size-=PAGE_SIZE;		start+=PAGE_SIZE;		pos+=PAGE_SIZE;	}	return 0;	}static int flash_open(struct inode *inode,struct file *file){	if(cnt_open>0)		return -EBUSY;	cnt_open++;	flash_mem=rvmalloc(KERNEL_SIZE);		flash_get_info();//	printk(KERN_INFO "open flash device\n");	return 0;}static int flash_close(struct inode *inode,struct file *file){	if(cnt_open>0)		cnt_open--;	if(flash_mem)		rvfree(flash_mem,KERNEL_SIZE);//	printk(KERN_INFO "close flash device\n");	return 0;}
	static struct file_operations flash_ops = {	open:	flash_open,	release:flash_close, 	ioctl:	flash_ioctl,	mmap:   flash_mmap,};static int __init flash_init(void){	if(register_chrdev(MAJOR_NUM, DRIVER_NAME, &flash_ops))	{		printk("can't register flash_amd update kernel driver\n");		return -1;	}	//printk(KERN_INFO "register flash module\n");	return 0;}static void __exit flash_exit(void){	unregister_chrdev(MAJOR_NUM, DRIVER_NAME);	printk(KERN_INFO "deregister flash module\n");}module_init(flash_init);module_exit(flash_exit);		

⌨️ 快捷键说明

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