diff options
| author | wdenk <wdenk> | 2003-07-14 22:13:32 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2003-07-14 22:13:32 +0000 | 
| commit | 8564acf936726c5568d71e4fa93a0ae9814e0d07 (patch) | |
| tree | 05fa981555adf1d333970f3d52d0683008fe3cfb /board/mpc8260ads/flash.c | |
| parent | 5702923e23238df6c6f62d53f73863462ae62f4e (diff) | |
| download | olio-uboot-2014.01-8564acf936726c5568d71e4fa93a0ae9814e0d07.tar.xz olio-uboot-2014.01-8564acf936726c5568d71e4fa93a0ae9814e0d07.zip | |
* Patches by Yuli Barcohen, 13 Jul 2003:
  - Correct flash and JFFS2 support for MPC8260ADS
  - fix PVR values and clock generation for PowerQUICC II family
    (8270/8275/8280)
* Patch by Bernhard Kuhn, 08 Jul 2003:
  - add support for M68K targets
* Patch by Ken Chou, 3 Jul:
  - Fix PCI config table for A3000
  - Fix iobase for natsemi.c
    (PCI_BASE_ADDRESS_0 is the IO base register for DP83815)
* Allow to enable "slow" POST routines by key press on power-on
* Fix temperature dependend switching of LCD backlight on LWMON
* Tweak output format for LWMON
Diffstat (limited to 'board/mpc8260ads/flash.c')
| -rw-r--r-- | board/mpc8260ads/flash.c | 494 | 
1 files changed, 267 insertions, 227 deletions
| diff --git a/board/mpc8260ads/flash.c b/board/mpc8260ads/flash.c index d61bfc646..b2e9df243 100644 --- a/board/mpc8260ads/flash.c +++ b/board/mpc8260ads/flash.c @@ -7,6 +7,11 @@   * I started with board/ip860/flash.c and made changes I found in   * the MTD project by David Schleef.   * + * (C) Copyright 2003 Arabella Software Ltd. + * Yuli Barcohen <yuli@arabellasw.com> + * Re-written to support multi-bank flash SIMMs. + * Added support for real protection and JFFS2. + *   * See file CREDITS for list of people who contributed to this   * project.   * @@ -28,73 +33,119 @@  #include <common.h> +/* Intel-compatible flash ID */ +#define INTEL_COMPAT  0x89898989 +#define INTEL_ALT     0xB0B0B0B0 -flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/ +/* Intel-compatible flash commands */ +#define INTEL_PROGRAM 0x10101010 +#define INTEL_ERASE   0x20202020 +#define INTEL_CLEAR   0x50505050 +#define INTEL_LOCKBIT 0x60606060 +#define INTEL_PROTECT 0x01010101 +#define INTEL_STATUS  0x70707070 +#define INTEL_READID  0x90909090 +#define INTEL_CONFIRM 0xD0D0D0D0 +#define INTEL_RESET   0xFFFFFFFF -#if defined(CFG_ENV_IS_IN_FLASH) -# ifndef  CFG_ENV_ADDR -#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET) -# endif -# ifndef  CFG_ENV_SIZE -#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE -# endif -# ifndef  CFG_ENV_SECT_SIZE -#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE -# endif -#endif +/* Intel-compatible flash status bits */ +#define INTEL_FINISHED 0x80808080 +#define INTEL_OK       0x80808080 -/*----------------------------------------------------------------------- - * 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 int clear_block_lock_bit(vu_long * addr); +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */  /*----------------------------------------------------------------------- + * This board supports 32-bit wide flash SIMMs (4x8-bit configuration.) + * Up to 32MB of flash supported (up to 4 banks.) + * BCSR is used for flash presence detect (page 4-65 of the User's Manual) + * + * The following code can not run from flash!   */ -  unsigned long flash_init (void)  { -#ifndef CONFIG_MPC8260ADS -	volatile immap_t	*immap  = (immap_t *)CFG_IMMR; -	volatile memctl8xx_t	*memctl = &immap->im_memctl; -	volatile ip860_bcsr_t	*bcsr   = (ip860_bcsr_t *)BCSR_BASE; -#endif -	unsigned long size; -	int i; - -	/* Init: enable write, -	 * or we cannot even write flash commands -	 */ -#ifndef CONFIG_MPC8260ADS -	bcsr->bd_ctrl |= BD_CTRL_FLWE; -#endif +	ulong size = 0, sect_start, sect_size = 0, bank_size; +	ushort sect_count = 0; +	int i, j, nbanks; +	vu_long *addr = (vu_long *)CFG_FLASH_BASE; +	vu_long *bcsr = (vu_long *)CFG_BCSR; -	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { -		flash_info[i].flash_id = FLASH_UNKNOWN; - -		/* set the default sector offset */ +	switch (bcsr[2] & 0xF) { +	case 0: +		nbanks = 4; +		break; +	case 1: +		nbanks = 2; +		break; +	case 2: +		nbanks = 1; +		break; +	default:		/* Unsupported configurations */ +		nbanks = CFG_MAX_FLASH_BANKS;  	} -	/* Static FLASH Bank configuration here - FIXME XXX */ - -	size = flash_get_size((vu_long *)FLASH_BASE, &flash_info[0]); +	if (nbanks > CFG_MAX_FLASH_BANKS) +		nbanks = CFG_MAX_FLASH_BANKS; -	if (flash_info[0].flash_id == FLASH_UNKNOWN) { -		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", -			size, size<<20); +	for (i = 0; i < nbanks; i++) { +		*addr = INTEL_READID;	/* Read Intelligent Identifier */ +		if ((addr[0] == INTEL_COMPAT) || (addr[0] == INTEL_ALT)) { +			switch (addr[1]) { +			case SHARP_ID_28F016SCL: +			case SHARP_ID_28F016SCZ: +				flash_info[i].flash_id = FLASH_MAN_SHARP | FLASH_LH28F016SCT; +				sect_count = 32; +				sect_size = 0x40000; +				break; +			default: +				flash_info[i].flash_id = FLASH_UNKNOWN; +				sect_count = CFG_MAX_FLASH_SECT; +				sect_size = +				   CFG_FLASH_SIZE / CFG_MAX_FLASH_BANKS / CFG_MAX_FLASH_SECT; +			} +		} +		else +			flash_info[i].flash_id = FLASH_UNKNOWN; +		if (flash_info[i].flash_id == FLASH_UNKNOWN) { +			printf("### Unknown flash ID %08lX %08lX at address %08lX ###\n", +			       addr[0], addr[1], (ulong)addr); +			size = 0; +			*addr = INTEL_RESET; /* Reset bank to Read Array mode */ +			break; +		} +		flash_info[i].sector_count = sect_count; +		flash_info[i].size = bank_size = sect_size * sect_count; +		size += bank_size; +		sect_start = (ulong)addr; +		for (j = 0; j < sect_count; j++) { +			addr = (vu_long *)sect_start; +			flash_info[i].start[j]   = sect_start; +			flash_info[i].protect[j] = (addr[2] == 0x01010101); +			sect_start += sect_size; +		} +		*addr = INTEL_RESET; /* Reset bank to Read Array mode */ +		addr = (vu_long *)sect_start;  	} -#ifndef CONFIG_MPC8260ADS -	/* Remap FLASH according to real size */ -	memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size & 0xFFFF8000); -	memctl->memc_br1 = (CFG_FLASH_BASE & BR_BA_MSK) | -				(memctl->memc_br1 & ~(BR_BA_MSK)); -#endif - -	/* Re-do sizing to get full correct info */ -	size = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]); -	flash_info[0].size = size; +	if (size == 0) {	/* Unknown flash, fill with hard-coded values */ +		sect_start = CFG_FLASH_BASE; +		for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { +			flash_info[i].flash_id = FLASH_UNKNOWN; +			flash_info[i].size = CFG_FLASH_SIZE / CFG_MAX_FLASH_BANKS; +			flash_info[i].sector_count = sect_count; +			for (j = 0; j < sect_count; j++) { +				flash_info[i].start[j]   = sect_start; +				flash_info[i].protect[j] = 0; +				sect_start += sect_size; +			} +		} +		size = CFG_FLASH_SIZE; +	} +	else +		for (i = nbanks; i < CFG_MAX_FLASH_BANKS; i++) { +			flash_info[i].flash_id = FLASH_UNKNOWN; +			flash_info[i].size = 0; +			flash_info[i].sector_count = 0; +		}  #if CFG_MONITOR_BASE >= CFG_FLASH_BASE  	/* monitor protection ON by default */ @@ -161,102 +212,6 @@ void flash_print_info  (flash_info_t *info)  /*-----------------------------------------------------------------------   */ - - -/*----------------------------------------------------------------------- - */ - -/* - * The following code cannot be run from FLASH! - */ - -static ulong flash_get_size (vu_long *addr, flash_info_t *info) -{ -	short i; -	ulong value; -	ulong base = (ulong)addr; -	ulong sector_offset; - -	/* Write "Intelligent Identifier" command: read Manufacturer ID */ -	*addr = 0x90909090; - -	value = addr[0] & 0x00FF00FF; -	switch (value) { -	case MT_MANUFACT:	/* SHARP, MT or => Intel */ -	case INTEL_ALT_MANU: -		info->flash_id = FLASH_MAN_INTEL; -		break; -	default: -		printf("unknown manufacturer: %x\n", (unsigned int)value); -		info->flash_id = FLASH_UNKNOWN; -		info->sector_count = 0; -		info->size = 0; -		return (0);			/* no or unknown flash	*/ -	} - -	value = addr[1];			/* device ID		*/ - -	switch (value) { -	case (INTEL_ID_28F016S): -		info->flash_id += FLASH_28F016SV; -		info->sector_count = 32; -		info->size = 0x00400000; -		sector_offset = 0x20000; -		break;				/* => 2x2 MB		*/ - -	case (INTEL_ID_28F160S3): -		info->flash_id += FLASH_28F160S3; -		info->sector_count = 32; -		info->size = 0x00400000; -		sector_offset = 0x20000; -		break;				/* => 2x2 MB		*/ - -	case (INTEL_ID_28F320S3): -		info->flash_id += FLASH_28F320S3; -		info->sector_count = 64; -		info->size = 0x00800000; -		sector_offset = 0x20000; -		break;				/* => 2x4 MB		*/ - -	case SHARP_ID_28F016SCL: -	case SHARP_ID_28F016SCZ: -		info->flash_id      = FLASH_MAN_SHARP | FLASH_LH28F016SCT; -		info->sector_count  = 32; -		info->size          = 0x00800000; -		sector_offset = 0x40000; -		break;				/* => 4x2 MB		*/ - - -	default: -		info->flash_id = FLASH_UNKNOWN; -		return (0);			/* => no or unknown flash */ - -	} - -	/* set up sector start address table */ -	for (i = 0; i < info->sector_count; i++) { -		info->start[i] = base; -		base += sector_offset; -		/* don't know how to check sector protection */ -		info->protect[i] = 0; -	} - -	/* -	 * Prevent writes to uninitialized FLASH. -	 */ -	if (info->flash_id != FLASH_UNKNOWN) { -		addr = (vu_long *)info->start[0]; - -		*addr = 0xFFFFFF;	/* reset bank to read array mode */ -	} - -	return (info->size); -} - - -/*----------------------------------------------------------------------- - */ -  int	flash_erase (flash_info_t *info, int s_first, int s_last)  {  	int flag, prot, sect; @@ -292,12 +247,6 @@ int	flash_erase (flash_info_t *info, int s_first, int s_last)  		printf ("\n");  	} -	/* Make Sure Block Lock Bit is not set. */ -	if(clear_block_lock_bit((vu_long *)(info->start[s_first]))){ -		return 1; -	} - -  	/* Start erase on unprotected sectors */  	for (sect = s_first; sect<=s_last; sect++) {  		if (info->protect[sect] == 0) {	/* not protected */ @@ -308,36 +257,26 @@ int	flash_erase (flash_info_t *info, int s_first, int s_last)  			/* Disable interrupts which might cause a timeout here */  			flag = disable_interrupts(); -			/* Reset Array */ -			*addr = 0xffffffff;  			/* Clear Status Register */ -			*addr = 0x50505050; +			*addr = INTEL_CLEAR;  			/* Single Block Erase Command */ -			*addr = 0x20202020; +			*addr = INTEL_ERASE;  			/* Confirm */ -			*addr = 0xD0D0D0D0; +			*addr = INTEL_CONFIRM;  			if((info->flash_id & FLASH_TYPEMASK) != FLASH_LH28F016SCT) {  			    /* Resume Command, as per errata update */ -			    *addr = 0xD0D0D0D0; +			    *addr = INTEL_CONFIRM;  			}  			/* re-enable interrupts if necessary */  			if (flag)  				enable_interrupts(); -			/* wait at least 80us - let's wait 1 ms */ -			udelay (1000); -			while ((*addr & 0x80808080) != 0x80808080) { -				if(*addr & 0x20202020){ -					printf("Error in Block Erase - Lock Bit may be set!\n"); -					printf("Status Register = 0x%X\n", (uint)*addr); -					*addr = 0xFFFFFFFF;	/* reset bank */ -					return 1; -				} +			while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) {  				if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {  					printf ("Timeout\n"); -					*addr = 0xFFFFFFFF;	/* reset bank */ +					*addr = INTEL_RESET;	/* reset bank */  					return 1;  				}  				/* show that we're waiting */ @@ -347,8 +286,15 @@ int	flash_erase (flash_info_t *info, int s_first, int s_last)  				}  			} +			if (*addr != INTEL_OK) { +				printf("Block erase failed at %08X, CSR=%08X\n", +				       (uint)addr, (uint)*addr); +				*addr = INTEL_RESET;	/* reset bank */ +				return 1; +			} +  			/* reset to read mode */ -			*addr = 0xFFFFFFFF; +			*addr = INTEL_RESET;  		}  	} @@ -357,6 +303,58 @@ int	flash_erase (flash_info_t *info, int s_first, int s_last)  }  /*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ +	ulong start; +	int rc = 0; +	int flag; +	vu_long *addr = (vu_long *)dest; + +	/* Check if Flash is (sufficiently) erased */ +	if ((*addr & data) != data) { +		return (2); +	} + +	*addr = INTEL_CLEAR; /* Clear status register */ + +	/* Disable interrupts which might cause a timeout here */ +	flag = disable_interrupts(); + +	/* Write Command */ +	*addr = INTEL_PROGRAM; + +	/* Write Data */ +	*addr = data; + +	/* re-enable interrupts if necessary */ +	if (flag) +		enable_interrupts(); + +	/* data polling for D7 */ +	start = get_timer (0); +	while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) { +		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { +			printf("Write timed out\n"); +			rc = 1; +			break; +		} +	} +	if (*addr != INTEL_OK) { +		printf ("Write failed at %08X, CSR=%08X\n", (uint)addr, (uint)*addr); +		rc = 1; +	} + +	*addr = INTEL_RESET; /* Reset to read array mode */ + +	return rc; +} + +/*-----------------------------------------------------------------------   * Copy memory to flash, returns:   * 0 - OK   * 1 - write timeout @@ -370,6 +368,8 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)  	wp = (addr & ~3);	/* get lower word aligned address */ +	*(vu_long *)wp = INTEL_RESET; /* Reset to read array mode */ +  	/*  	 * handle unaligned start bytes  	 */ @@ -424,85 +424,125 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)  		data = (data << 8) | (*(uchar *)cp);  	} -	return (write_word(info, wp, data)); +	rc = write_word(info, wp, data); + +	return rc;  }  /*----------------------------------------------------------------------- - * Write a word to Flash, returns: + * Set/Clear sector's lock bit, returns:   * 0 - OK - * 1 - write timeout - * 2 - Flash not erased + * 1 - Error (timeout, voltage problems, etc.)   */ -static int write_word (flash_info_t *info, ulong dest, ulong data) +int flash_real_protect(flash_info_t *info, long sector, int prot)  { -	vu_long *addr = (vu_long *)dest; -	ulong start, csr; -	int flag; +	ulong start; +	int i; +	int rc = 0; +	vu_long *addr = (vu_long *)(info->start[sector]); +	int flag = disable_interrupts(); -	/* Check if Flash is (sufficiently) erased */ -	if ((*addr & data) != data) { -		return (2); +	*addr = INTEL_CLEAR;	/* Clear status register */ +	if (prot) {			/* Set sector lock bit */ +		*addr = INTEL_LOCKBIT;	/* Sector lock bit */ +		*addr = INTEL_PROTECT;	/* set */ +	} +	else {				/* Clear sector lock bit */ +		*addr = INTEL_LOCKBIT;	/* All sectors lock bits */ +		*addr = INTEL_CONFIRM;	/* clear */  	} -	/* Disable interrupts which might cause a timeout here */ -	flag = disable_interrupts(); - -	/* Write Command */ -	*addr = 0x10101010; - -	/* Write Data */ -	*addr = data; - -	/* re-enable interrupts if necessary */ -	if (flag) -		enable_interrupts(); -	/* data polling for D7 */ -	start = get_timer (0); -	flag  = 0; -	while (((csr = *addr) & 0x80808080) != 0x80808080) { -		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { -			flag = 1; +	start = get_timer(0); +	while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) { +		if (get_timer(start) > CFG_FLASH_UNLOCK_TOUT) { +			printf("Flash lock bit operation timed out\n"); +			rc = 1;  			break;  		}  	} -	if (csr & 0x40404040) { -		printf ("CSR indicates write error (%08lx) at %08lx\n", csr, (ulong)addr); -		flag = 1; + +	if (*addr != INTEL_OK) { +		printf("Flash lock bit operation failed at %08X, CSR=%08X\n", +		       (uint)addr, (uint)*addr); +		rc = 1;  	} -	/* Clear Status Registers Command */ -	*addr = 0x50505050; -	/* Reset to read array mode */ -	*addr = 0xFFFFFFFF; +	if (!rc) +		info->protect[sector] = prot; + +	/* +	 * Clear lock bit command clears all sectors lock bits, so +	 * we have to restore lock bits of protected sectors. +	 */ +	if (!prot) +		for (i = 0; i < info->sector_count; i++) +			if (info->protect[i]) { +				addr = (vu_long *)(info->start[i]); +				*addr = INTEL_LOCKBIT;	/* Sector lock bit */ +				*addr = INTEL_PROTECT;	/* set */ +				udelay(CFG_FLASH_LOCK_TOUT * 1000); +			} + +	if (flag) +		enable_interrupts(); + +	*addr = INTEL_RESET;		/* Reset to read array mode */ -	return (flag); +	return rc;  }  /*----------------------------------------------------------------------- - * Clear Block Lock Bit, returns: - * 0 - OK - * 1 - Timeout + * Support for flash file system (JFFS2) + * + * We use custom partition info function because we have to fit the + * file system image between first sector (containing hard reset + * configuration word) and the sector containing U-Boot image. Standard + * partition info function does not allow for last sector specification + * and assumes that the file system occupies flash bank up to and + * including bank's last sector.   */ +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CFG_JFFS_CUSTOM_PART) -static int clear_block_lock_bit(vu_long  * addr) -{ -	ulong start, now; +#ifndef CFG_JFFS2_FIRST_SECTOR +#define CFG_JFFS2_FIRST_SECTOR 0 +#endif +#ifndef CFG_JFFS2_FIRST_BANK +#define CFG_JFFS2_FIRST_BANK 0 +#endif +#ifndef CFG_JFFS2_NUM_BANKS +#define CFG_JFFS2_NUM_BANKS 1 +#endif +#define CFG_JFFS2_LAST_BANK (CFG_JFFS2_FIRST_BANK + CFG_JFFS2_NUM_BANKS - 1) -	/* Reset Array */ -	*addr = 0xffffffff; -	/* Clear Status Register */ -	*addr = 0x50505050; +#include <jffs2/jffs2.h> -	*addr = 0x60606060; -	*addr = 0xd0d0d0d0; +static struct part_info partition; -	start = get_timer (0); -	while(*addr != 0x80808080){ -		if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) { -			printf ("Timeout on clearing Block Lock Bit\n"); -			*addr = 0xFFFFFFFF;	/* reset bank */ -			return 1; +struct part_info *jffs2_part_info(int part_num) +{ +	int i; + +	if (part_num == 0) { +		if (partition.usr_priv == 0) { +			partition.offset = +				(unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR]; +			for (i = CFG_JFFS2_FIRST_BANK; i <= CFG_JFFS2_LAST_BANK; i++) +				partition.size += flash_info[i].size; +			partition.size -= +				flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR] - +				flash_info[CFG_JFFS2_FIRST_BANK].start[0]; +#ifdef CFG_JFFS2_LAST_SECTOR +			i = flash_info[CFG_JFFS2_LAST_BANK].sector_count - 1; +			partition.size -= +				flash_info[CFG_JFFS2_LAST_BANK].start[i] - +				flash_info[CFG_JFFS2_LAST_BANK].start[CFG_JFFS2_LAST_SECTOR]; +#endif + +			partition.usr_priv = (void *)1;  		} +		return &partition;  	}  	return 0;  } + +#endif /* JFFS2 */ |