diff options
| author | wdenk <wdenk> | 2004-06-09 21:54:22 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2004-06-09 21:54:22 +0000 | 
| commit | 99edcfb29ef8c4865bd26dddf938af0bf5959482 (patch) | |
| tree | cbe509d69cb6096313ff6c1177139217e73a85a5 /board/fads/flash.c | |
| parent | 2d24a3a787c2376c2c2c86a511eee78ef170923f (diff) | |
| download | olio-uboot-2014.01-99edcfb29ef8c4865bd26dddf938af0bf5959482.tar.xz olio-uboot-2014.01-99edcfb29ef8c4865bd26dddf938af0bf5959482.zip | |
Patch by Yuli Barcohen, 09 Jun 2004:
Add support for 8MB flash SIMM and JFFS2 file system on
Motorola FADS board and its derivatives (MPC86xADS, MPC885ADS).
Diffstat (limited to 'board/fads/flash.c')
| -rw-r--r-- | board/fads/flash.c | 241 | 
1 files changed, 78 insertions, 163 deletions
| diff --git a/board/fads/flash.c b/board/fads/flash.c index d2a46b227..f0fb62127 100644 --- a/board/fads/flash.c +++ b/board/fads/flash.c @@ -24,7 +24,7 @@  #include <common.h>  #include <mpc8xx.h> -flash_info_t flash_info[CFG_MAX_FLASH_BANKS];	/* info for FLASH chips        */ +flash_info_t flash_info[CFG_MAX_FLASH_BANKS];	/* info for FLASH chips */  #if defined(CFG_ENV_IS_IN_FLASH)  # ifndef  CFG_ENV_ADDR @@ -38,124 +38,103 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS];	/* info for FLASH chips        */  # endif  #endif +#define QUAD_ID(id)	((((ulong)(id) & 0xFF) << 24) | \ +			 (((ulong)(id) & 0xFF) << 16) | \ +			 (((ulong)(id) & 0xFF) << 8)  | \ +			 (((ulong)(id) & 0xFF) << 0)    \ +			) +  /*-----------------------------------------------------------------------   * Functions   */  static ulong flash_get_size (vu_long * addr, flash_info_t * info);  static int write_word (flash_info_t * info, ulong dest, ulong data); -static void flash_get_offsets (ulong base, flash_info_t * info);  /*-----------------------------------------------------------------------   */ -  unsigned long flash_init (void)  {  	volatile immap_t *immap = (immap_t *) CFG_IMMR;  	volatile memctl8xx_t *memctl = &immap->im_memctl; -	unsigned long total_size; -	unsigned long size_b0, size_b1; +	vu_long *bcsr = (vu_long *)BCSR_ADDR; +	unsigned long pd_size, total_size, bsize, or_am;  	int i;  	/* Init: no FLASHes known */  	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {  		flash_info[i].flash_id = FLASH_UNKNOWN; +		flash_info[i].size = 0; +		flash_info[i].sector_count = 0; +		flash_info[i].start[0] = 0xFFFFFFFF; /* For TFTP */  	} -	total_size = 0; -	size_b0 = 0xffffffff; +	switch ((bcsr[2] & BCSR2_FLASH_PD_MASK) >> BCSR2_FLASH_PD_SHIFT) { +	case 2: +	case 4: +	case 6: +		pd_size = 0x800000; +		or_am = 0xFF800000; +		break; -	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { -		size_b1 = -			flash_get_size ((vu_long *) (CFG_FLASH_BASE + -						     total_size), -					&flash_info[i]); +	case 5: +	case 7: +		pd_size = 0x400000; +		or_am = 0xFFC00000; +		break; -		if (flash_info[i].flash_id == FLASH_UNKNOWN) { -			printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", i, size_b1, size_b1 >> 20); -		} +	case 8: +		pd_size = 0x200000; +		or_am = 0xFFE00000; +		break; -		/* Is this really needed ? - LP */ -		if (size_b1 > size_b0) { -			printf ("## ERROR: Bank %d (0x%08lx = %ld MB) > Bank %d (0x%08lx = %ld MB)\n", i, size_b1, size_b1 >> 20, i - 1, size_b0, size_b0 >> 20); -			goto out_error; -		} -		size_b0 = size_b1; -		total_size += size_b1; +	default: +		pd_size = 0; +		or_am = 0xFFE00000; +		printf("## Unsupported flash detected by BCSR: 0x%08X\n", bcsr[2]);  	} -	/* Compute the Address Mask */ -	for (i = 0; (total_size >> i) != 0; ++i) { +	total_size = 0; +	for (i = 0; i < CFG_MAX_FLASH_BANKS && total_size < pd_size; ++i) { +		bsize = flash_get_size((vu_long *)(CFG_FLASH_BASE + total_size), +				       &flash_info[i]); + +		if (flash_info[i].flash_id == FLASH_UNKNOWN) { +			printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", +				i, bsize, bsize >> 20); +		} + +		total_size += bsize;  	} -	i--; -	if (total_size != (1 << i)) { -		printf ("## WARNING: Total FLASH size (0x%08lx = %ld MB) is not a power of 2\n", total_size, total_size >> 20); +	if (total_size != pd_size) { +		printf("## Detected flash size %lu conflicts with PD data %lu\n", +		       total_size, pd_size);  	}  	/* Remap FLASH according to real size */ -	memctl->memc_or0 = -		((((unsigned long) ~0) << i) & OR_AM_MSK) | -		CFG_OR_TIMING_FLASH; -	memctl->memc_br0 = CFG_BR0_PRELIM; - -	total_size = 0; +	memctl->memc_or0 = or_am | CFG_OR_TIMING_FLASH;  	for (i = 0; i < CFG_MAX_FLASH_BANKS && flash_info[i].size != 0; ++i) { -		/* Re-do sizing to get full correct info */ -		/* Why ? - LP */ -		size_b1 = -			flash_get_size ((vu_long *) (CFG_FLASH_BASE + -						     total_size), -					&flash_info[i]); - -		/* This is done by flash_get_size - LP */ -		/* flash_get_offsets (CFG_FLASH_BASE + total_size, &flash_info[i]); */ -  #if CFG_MONITOR_BASE >= CFG_FLASH_BASE  		/* monitor protection ON by default */ -		flash_protect (FLAG_PROTECT_SET, -			       CFG_MONITOR_BASE, -			       CFG_MONITOR_BASE + monitor_flash_len - 1, -			       &flash_info[i]); +		if (CFG_MONITOR_BASE >= flash_info[i].start[0]) +			flash_protect (FLAG_PROTECT_SET, +				       CFG_MONITOR_BASE, +				       CFG_MONITOR_BASE + monitor_flash_len - 1, +				       &flash_info[i]);  #endif  #ifdef	CFG_ENV_IS_IN_FLASH  		/* ENV protection ON by default */ -		flash_protect (FLAG_PROTECT_SET, -			       CFG_ENV_ADDR, -			       CFG_ENV_ADDR + CFG_ENV_SIZE - 1, -			       &flash_info[i]); +		if (CFG_ENV_ADDR >= flash_info[i].start[0]) +			flash_protect (FLAG_PROTECT_SET, +				       CFG_ENV_ADDR, +				       CFG_ENV_ADDR + CFG_ENV_SIZE - 1, +				       &flash_info[i]);  #endif - -		total_size += size_b1;  	} -	return (total_size); - -      out_error: -	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { -		flash_info[i].flash_id = FLASH_UNKNOWN; -		flash_info[i].sector_count = -1; -		flash_info[i].size = 0; -	} - -	return (0); -} - -/*----------------------------------------------------------------------- - */ -static void flash_get_offsets (ulong base, flash_info_t * info) -{ -	int i; - -	/* set up sector start address table */ -	if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040 -	    || (info->flash_id & FLASH_TYPEMASK) == FLASH_AM080) { -		/* set sector offsets for uniform sector type   */ -		for (i = 0; i < info->sector_count; i++) { -			info->start[i] = base + (i * 0x00040000); -		} -	} +	return total_size;  }  /*----------------------------------------------------------------------- @@ -235,48 +214,26 @@ void flash_print_info (flash_info_t * info)  	}  	printf ("\n"); -	return;  }  /*----------------------------------------------------------------------- + * The following code can not run from flash!   */ - - -/*----------------------------------------------------------------------- - */ - -/* - * The following code cannot be run from FLASH! - */ -  static ulong flash_get_size (vu_long * addr, flash_info_t * info)  {  	short i; -#if 0 -	ulong base = (ulong) addr; -#endif -	uchar value; -  	/* Write auto select command: read Manufacturer ID */ -#if 0 -	addr[0x0555] = 0x00AA00AA; -	addr[0x02AA] = 0x00550055; -	addr[0x0555] = 0x00900090; -#else  	addr[0x0555] = 0xAAAAAAAA;  	addr[0x02AA] = 0x55555555;  	addr[0x0555] = 0x90909090; -#endif - -	value = addr[0]; -	switch (value + (value << 16)) { -	case AMD_MANUFACT: +	switch (addr[0]) { +	case QUAD_ID(AMD_MANUFACT):  		info->flash_id = FLASH_MAN_AMD;  		break; -	case FUJ_MANUFACT: +	case QUAD_ID(FUJ_MANUFACT):  		info->flash_id = FLASH_MAN_FUJ;  		break; @@ -287,21 +244,20 @@ static ulong flash_get_size (vu_long * addr, flash_info_t * info)  		break;  	} -	value = addr[1];	/* device ID            */ - -	switch (value) { -	case AMD_ID_F040B: +	switch (addr[1]) {	/* device ID            */ +	case QUAD_ID(AMD_ID_F040B): +	case QUAD_ID(AMD_ID_LV040B):  		info->flash_id += FLASH_AM040;  		info->sector_count = 8;  		info->size = 0x00200000;  		break;		/* => 2 MB              */ -	case AMD_ID_F080B: +	case QUAD_ID(AMD_ID_F080B):  		info->flash_id += FLASH_AM080;  		info->sector_count = 16;  		info->size = 0x00400000;  		break;		/* => 4 MB              */ - +#if 0  	case AMD_ID_LV400T:  		info->flash_id += FLASH_AM400T;  		info->sector_count = 11; @@ -337,7 +293,7 @@ static ulong flash_get_size (vu_long * addr, flash_info_t * info)  		info->sector_count = 35;  		info->size = 0x00400000;  		break;		/* => 4 MB              */ -#if 0				/* enable when device IDs are available */ +  	case AMD_ID_LV320T:  		info->flash_id += FLASH_AM320T;  		info->sector_count = 67; @@ -349,11 +305,10 @@ static ulong flash_get_size (vu_long * addr, flash_info_t * info)  		info->sector_count = 67;  		info->size = 0x00800000;  		break;		/* => 8 MB              */ -#endif +#endif /* 0 */  	default:  		info->flash_id = FLASH_UNKNOWN;  		return (0);	/* => no or unknown flash */ -  	}  #if 0 @@ -378,7 +333,9 @@ static ulong flash_get_size (vu_long * addr, flash_info_t * info)  		}  	}  #else -	flash_get_offsets ((ulong) addr, info); +	/* set sector offsets for uniform sector type */ +	for (i = 0; i < info->sector_count; i++) +		info->start[i] = (ulong)addr + (i * 0x00040000);  #endif  	/* check for protected sectors */ @@ -389,25 +346,16 @@ static ulong flash_get_size (vu_long * addr, flash_info_t * info)  		info->protect[i] = addr[2] & 1;  	} -	/* -	 * Prevent writes to uninitialized FLASH. -	 */  	if (info->flash_id != FLASH_UNKNOWN) {  		addr = (volatile unsigned long *) info->start[0]; -#if 0 -		*addr = 0x00F000F0;	/* reset bank */ -#else  		*addr = 0xF0F0F0F0;	/* reset bank */ -#endif  	}  	return (info->size);  } -  /*-----------------------------------------------------------------------   */ -  int flash_erase (flash_info_t * info, int s_first, int s_last)  {  	vu_long *addr = (vu_long *) (info->start[0]); @@ -420,13 +368,13 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)  		} else {  			printf ("- no sectors to erase\n");  		} -		return 1; +		return ERR_INVAL;  	}  	if ((info->flash_id == FLASH_UNKNOWN) ||  	    (info->flash_id > FLASH_AMD_COMP)) {  		printf ("Can't erase unknown flash type - aborted\n"); -		return 1; +		return ERR_UNKNOWN_FLASH_TYPE;  	}  	prot = 0; @@ -447,29 +395,17 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)  	/* Disable interrupts which might cause a timeout here */  	flag = disable_interrupts (); -#if 0 -	addr[0x0555] = 0x00AA00AA; -	addr[0x02AA] = 0x00550055; -	addr[0x0555] = 0x00800080; -	addr[0x0555] = 0x00AA00AA; -	addr[0x02AA] = 0x00550055; -#else  	addr[0x0555] = 0xAAAAAAAA;  	addr[0x02AA] = 0x55555555;  	addr[0x0555] = 0x80808080;  	addr[0x0555] = 0xAAAAAAAA;  	addr[0x02AA] = 0x55555555; -#endif  	/* Start erase on unprotected sectors */  	for (sect = s_first; sect <= s_last; sect++) {  		if (info->protect[sect] == 0) {	/* not protected */  			addr = (vu_long *) (info->start[sect]); -#if 0 -			addr[0] = 0x00300030; -#else  			addr[0] = 0x30303030; -#endif  			l_sect = sect;  		}  	} @@ -490,15 +426,11 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)  	start = get_timer (0);  	last = start;  	addr = (vu_long *) (info->start[l_sect]); -#if 0 -	while ((addr[0] & 0x00800080) != 0x00800080) -#else  	while ((addr[0] & 0xFFFFFFFF) != 0xFFFFFFFF) -#endif  	{  		if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {  			printf ("Timeout\n"); -			return 1; +			return ERR_TIMOUT;  		}  		/* show that we're waiting */  		if ((now - last) > 1000) {	/* every second */ @@ -510,13 +442,10 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)        DONE:  	/* reset to read mode */  	addr = (volatile unsigned long *) info->start[0]; -#if 0 -	addr[0] = 0x00F000F0;	/* reset bank */ -#else  	addr[0] = 0xF0F0F0F0;	/* reset bank */ -#endif  	printf (" done\n"); +  	return 0;  } @@ -526,7 +455,6 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)   * 1 - write timeout   * 2 - Flash not erased   */ -  int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)  {  	ulong cp, wp, data; @@ -605,20 +533,14 @@ static int write_word (flash_info_t * info, ulong dest, ulong data)  	/* Check if Flash is (sufficiently) erased */  	if ((*((vu_long *) dest) & data) != data) { -		return (2); +		return ERR_NOT_ERASED;  	}  	/* Disable interrupts which might cause a timeout here */  	flag = disable_interrupts (); -#if 0 -	addr[0x0555] = 0x00AA00AA; -	addr[0x02AA] = 0x00550055; -	addr[0x0555] = 0x00A000A0; -#else  	addr[0x0555] = 0xAAAAAAAA;  	addr[0x02AA] = 0x55555555;  	addr[0x0555] = 0xA0A0A0A0; -#endif  	*((vu_long *) dest) = data; @@ -628,18 +550,11 @@ static int write_word (flash_info_t * info, ulong dest, ulong data)  	/* data polling for D7 */  	start = get_timer (0); -#if 0 -	while ((*((vu_long *) dest) & 0x00800080) != (data & 0x00800080)) -#else  	while ((*((vu_long *) dest) & 0x80808080) != (data & 0x80808080)) -#endif  	{  		if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { -			return (1); +			return ERR_TIMOUT;  		}  	}  	return (0);  } - -/*----------------------------------------------------------------------- - */ |