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

📄 uboot_driver_flash.c

📁 uclinux下 intel mx flash驱动源码!
💻 C
字号:
/*
 * (C) Copyright 2001 - Analog Devices, Inc.  All rights reserved.
 *	BF533EzFlash.c
 *	Analog Devices, Inc. - 2001
 *
 *
 *	Change Log
 *	1.00.1
 *	- made changes so that the driver will work with
 *		  the revised GUI
 *	1.00.0
 *	- initial release
 *
 * VisualDSP++ "Flash Programmer" flash driver for use with the
 * ADSP-BF533 EZ-KIT Lite containing the STMicroelectronics PSD4256G
 * flash device.  \hhbf
 */

 #include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/moduleparam.h>
#include <asm/page.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <linux/delay.h>

#include "uboot_common.h"


unsigned long uboot_flash_get_size(vu_long *addr, uboot_flash_info_t * info)
{
	short i;
	FLASH_WORD_SIZE manu_id, dev_id;
	ulong base = (ulong) addr;
	volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) addr;

	/* Write Auto Select Command and read Manufacturer's ID and Dev ID */

	addr2[ADDR0] = (FLASH_WORD_SIZE) 0xAAAAAAAA; asm("ssync;");
	addr2[ADDR1] = (FLASH_WORD_SIZE) 0x55555555; asm("ssync;");
	addr2[ADDR0] = (FLASH_WORD_SIZE) 0x90909090; asm("ssync;");
    	printk("");  //for delay ???   by beyond.cheng
	
	manu_id = addr2[0];

	switch (manu_id) 
	{
	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;

	default:
		info->flash_id = FLASH_UNKNOWN;
		info->sector_count = 0;
		info->size = 0;
		break;
	}

	/* Read Device Id */
	dev_id = addr2[1];

	switch (dev_id)
	{
	case (FLASH_WORD_SIZE) AMD_ID_LV320B:
		info->flash_id += FLASH_AM320B;
		info->sector_count = 71;	/* 8 - boot sec + 63 normal */
		info->size = 0x400000;	/* 4MByte */
		break;
	 case (FLASH_WORD_SIZE) AMD_ID_LV160B:
                info->flash_id += FLASH_AM160B;
                info->sector_count = 35;        /* 8 - boot sec + 27 normal */
                info->size = 0x200000;  /* 2MByte */
                break;
	 case (FLASH_WORD_SIZE) MX_ID_LV320B:
                info->flash_id += FLASH_MXLV320B;
                info->sector_count = 71;        /* 8 - boot sec + 63 normal */
                info->size = 0x400000;  /* 4MByte */
                break;

	default:
		info->flash_id = FLASH_UNKNOWN;
		break;
	}

	/* Set up sector start Addresses */

	if (info->flash_id & FLASH_BTYPE) 
	{
		if(info->size==0x400000)
			{
				/* set sector offsets for bottom boot block
				 ** Eight 8 Kb Boot sectors
				 ** Sixty Three 64Kb sectors
				 */
				for (i = 0; i < 8; i++) 
				{
					info->start[i] = base + (i * 0x00002000);			
				info->protect[i] = 0;
				}
				
				for (i = 8; i < info->sector_count; i++) 
				{
					info->start[i] = base + (i * 0x00010000) - 0x00070000;
				info->protect[i] = 0;
				}
			}
		else if(info->size==0x200000)
			{
			/* set sector offsets for bottom boot block
				 ** one 16 Kb Boot sectors
				 ** two 8kb Boot Sectors
				 ** one 32kb Boot Sectors
				 ** twenty_nine 64Kb sectors
				 */
				 info->start[0]=base;
			info->protect[0] = 0;
				for (i = 1; i < 3; i++) 
				{
					info->start[i] = base +0x4000+ ((i-1) * 0x00002000);			
				info->protect[i] = 0;
				}
				info->start[3]=base+0x8000;
			info->protect[3] = 0;
				
				for (i = 4; i < info->sector_count; i++) 
				{
					info->start[i] = base +0x10000+ ((i-4) * 0x00010000);
				info->protect[i] = 0;
				}
			}
	}

	/* Reset To read mode */

	if (info->flash_id != FLASH_UNKNOWN) 
	{
		addr = (ulong *) info->start[0];
		*addr = 0xF0F0F0F0;
	}
	
	return (info->size);
}

unsigned long uboot_flash_init(void)
{
	unsigned long size_b0 = -1;
	int i;

	/* Set Flash to unknown */
	for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) 
	{
		uboot_flash_info[i].flash_id = FLASH_UNKNOWN;
	}

	/* Get the Flash Bank Size */

	size_b0 = uboot_flash_get_size ((vu_long *) (CFG_FLASH_BASE), &uboot_flash_info[0]);

	if (uboot_flash_info[0].flash_id == FLASH_UNKNOWN)
	{
		printk ("## UNKNOWN Flash on Bank 0 - Size = 0x%08lx = %ldMB\n",
			size_b0, size_b0 >> 20);
	}

	return size_b0;
}

int uboot_flash_erase(uboot_flash_info_t * info, int s_first, int s_last)
{
	volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
	volatile FLASH_WORD_SIZE *addr2;
	int prot, sect;
	int i;

	if ((s_first < 0) || (s_first > s_last))
	{
		if (info->flash_id == FLASH_UNKNOWN) 
		{
			printk ("- missing\n");
		}
		else 
		{
			printk ("- no sectors to erase\n");
		}
		
		return 1;
	}

     //printk("first sector=0x%x,  last sector = 0x%x\n", s_first, s_last);
	if (info->flash_id == FLASH_UNKNOWN) 
	{
		printk ("Can't erase unknown flash type - aborted\n");
		return 1;
	}

	prot = 0;
	for (sect = s_first; sect <= s_last; ++sect) 
	{
		if (info->protect[sect]) 
		{
		      //printk("protected sect = %x \n",sect);
			prot++;
		}
	}

	if (prot) 
	{
		printk ("Warning: %d protected sectors will not be erased!\n",
			prot);
	}
	else
	{
		//printk ("\n");
	}

	/* Disable interrupts which might cause a timeout here */
	/* Start erase on unprotected sectors */
	for (sect = s_first; sect <= s_last; sect++) 
	{

		if (info->protect[sect] == 0)
		{	/* not protected */
			addr2 = (FLASH_WORD_SIZE *) (info->start[sect]);

			//printf("info->flash_id = %x \n",info->flash_id);

			addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA; asm("ssync;");
			addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055; asm("ssync;");
			addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080; asm("ssync;");
			addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA; asm("ssync;");
			addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055; asm("ssync;");
			addr2[0] = (FLASH_WORD_SIZE) 0x00300030; 	 asm("ssync;");	/* sector erase */

			while ((addr2[0] & (FLASH_WORD_SIZE) 0x00800080) != (FLASH_WORD_SIZE) 0x00800080) 
			{
			    //int delay;
		            //for(delay=0; delay<0xff;delay++);	
         		    udelay(1);
			}
						
		}
	}
	
	//for(i=0;i<0xffff;i++);  //wait for reset
	udelay(100);
        //for(i=0;i<0xffffff;i++);  //wait for reset
       // i= i;

	/* wait at least 80us - let's wait 1 ms */
	addr[0] = (FLASH_WORD_SIZE) 0x00F000F0;	  asm("ssync;");/* reset bank */

        //for(i=0;i<0xffffff;i++);  //wait for reset
        //for(i=0;i<0xffffff;i++);  //wait for reset
	udelay(100);
       // i=i;
       // block erase should be complete

	//printk (" done\n");
	
	return 0;
}


static int uboot_write_word (uboot_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;
	ulong start;
	int i;
	
	/* Check if Flash is (sufficiently) erased */
	if ((*((volatile FLASH_WORD_SIZE *) dest) &
	     (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data)
	{
	    printk("Flash Erasing Error\n");
		return (2);
	}
	for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) 
	{
		int flag;

		addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA; asm("ssync;");
		addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055; asm("ssync;");
		addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0; asm("ssync;");

		dest2[i] = data2[i]; asm("ssync;");

	
		/* data polling for D7 */
		while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
		       (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) 
		{
		    //int delay;
                    //for(delay=0; delay<0xff;delay++);
                    udelay(1);
		}
		
	}
	return (0);
}

int uboot_write_buff(uboot_flash_info_t * info, uchar * src, ulong addr, ulong cnt)
{
	ulong cp, wp, data;
	int i, l, rc;

	/* get lower word aligned address */
	wp = (addr & ~3);

	/*
	 * handle unaligned start bytes
	 */
	if ((l = addr - wp) != 0) 
	{
	    //printk("write test\n");
		data = 0;
		
		for (i = 0, cp = wp; i < l; ++i, ++cp) 
		{
			data |= (*(uchar *) cp)<<(8*i);
		}
		
		for (; i < 4 && cnt > 0; ++i) 
		{
			data |= (*src++)<<(8*i);
			--cnt;
			++cp;
		}
		
		for (; cnt == 0 && i < 4; ++i, ++cp) 
		{
			data |= (*(uchar *) cp)<<(8*i);
		}

		if ((rc = uboot_write_word (info, wp, data)) != 0) 
		{
			return (rc);
		}
		
		wp += 4;
	}

	/*
	 * handle word aligned part
	 */

	while (cnt >= 4) 
	{
		data = 0;
		
		for (i = 0; i < 4; ++i) 
		{
			data |= (*src++)<<(8*i);
		}
		
		if ((rc = uboot_write_word (info, wp, data)) != 0) 
		{
		    printk("Error\n");
			return (rc);
		}
		
		wp += 4;
		cnt -= 4;
	}

	if (cnt == 0) 
	{
		return (0);
	}

	/*
	 * handle unaligned tail bytes
	 */
	data = 0;
	
	for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp)
	{
		data |= (*src++)<<(8*i);
		--cnt;
	}
	
	for (; i < 4; ++i, ++cp) 
	{
		data |= (*(uchar *) cp)<<(8*i);
	}

	return (uboot_write_word (info, wp, data));
	
}




⌨️ 快捷键说明

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