diff options
| -rw-r--r-- | CHANGELOG | 18 | ||||
| -rw-r--r-- | README | 6 | ||||
| -rw-r--r-- | board/altera/common/sevenseg.c | 6 | ||||
| -rw-r--r-- | common/cmd_bootm.c | 8 | ||||
| -rw-r--r-- | common/miiphyutil.c | 4 | ||||
| -rw-r--r-- | cpu/ppc4xx/miiphy.c | 6 | ||||
| -rw-r--r-- | drivers/Makefile | 2 | ||||
| -rw-r--r-- | drivers/cfi_flash.c | 1018 | ||||
| -rw-r--r-- | drivers/pci_auto.c | 18 | ||||
| -rw-r--r-- | include/configs/DK1C20.h | 4 | ||||
| -rw-r--r-- | include/flash.h | 7 | 
11 files changed, 1083 insertions, 14 deletions
| @@ -2,6 +2,24 @@  Changes since U-Boot 1.0.1:  ====================================================================== +* Patch by Yuli Barcohen, 26 Jan 2004: +  Allow bzip2 compression for small memory footprint boards + +* Patch by Brad Kemp, 21 Jan 2004: +  Add support for CFI flash driver for both the Intel and the AMD +  command sets. + +* Patch by Travis Sawyer, 20 Jan 2004: +  Fix pci bridge auto enumeration of sibling p2p bridges. + +* Patch by Tolunay Orkun, 12 Jan 2004: +  Add some delays as needed for Intel LXT971A PHY support + +* Patches by Stephan Linz, 09 Jan 2004: +  - avoid warning: unused variable `piop' in board/altera/common/sevenseg.c +  - make DK1C20 board configuration related to ASMI conform to +    documentation +  * Patch by Anders Larsen, 09 Jan 2004:    ARM memory layout fixes: the abort-stack is now set up in the @@ -1643,7 +1643,11 @@ Configuration Settings:  - CFG_FLASH_CFI:  		Define if the flash driver uses extra elements in the -		common flash structure for storing flash geometry +		common flash structure for storing flash geometry. + +- CFG_FLASH_CFI_DRIVER +		This option also enables the building of the cfi_flash driver +		in the drivers directory  - CFG_RX_ETH_BUFFER:  		Defines the number of ethernet receive buffers. On some diff --git a/board/altera/common/sevenseg.c b/board/altera/common/sevenseg.c index fecfbd388..c53cec16e 100644 --- a/board/altera/common/sevenseg.c +++ b/board/altera/common/sevenseg.c @@ -44,7 +44,7 @@ static int sevenseg_init_done = 0;  static inline void __sevenseg_set_masked (unsigned int mask, int value)  { -	nios_pio_t *piop = (nios_pio_t*)SEVENSEG_BASE; +	nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE;  #ifdef	SEVENSEG_WRONLY	/* emulate read access */ @@ -97,7 +97,7 @@ static inline void __sevenseg_toggle_masked (unsigned int mask)  static inline void __sevenseg_set (unsigned int value)  { -	nios_pio_t *piop = (nios_pio_t*)SEVENSEG_BASE; +	nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE;  #ifdef	SEVENSEG_WRONLY	/* emulate read access */ @@ -126,7 +126,7 @@ static inline void __sevenseg_set (unsigned int value)  static inline void __sevenseg_init (void)  { -	nios_pio_t *piop = (nios_pio_t*)SEVENSEG_BASE; +	nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE;  	__sevenseg_set(0); diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 34a74ce2c..ac9c32e7b 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -333,8 +333,14 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  #ifdef CONFIG_BZIP2  	case IH_COMP_BZIP2:  		printf ("   Uncompressing %s ... ", name); +		/* +		 * If we've got less than 4 MB of malloc() space, +		 * use slower decompression algorithm which requires +		 * at most 2300 KB of memory. +		 */  		i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), -						&unc_len, (char *)data, len, 0, 0); +						&unc_len, (char *)data, len, +						CFG_MALLOC_LEN < (4096 * 1024), 0);  		if (i != BZ_OK) {  			printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i);  			SHOW_BOOT_PROGRESS (-6); diff --git a/common/miiphyutil.c b/common/miiphyutil.c index af8c7c7a3..03964da81 100644 --- a/common/miiphyutil.c +++ b/common/miiphyutil.c @@ -99,7 +99,9 @@ int miiphy_reset (unsigned char addr)  #endif  		return (-1);  	} - +#ifdef CONFIG_PHY_RESET_DELAY +	udelay (CONFIG_PHY_RESET_DELAY);	/* Intel LXT971A needs this */ +#endif  	/*  	 * Poll the control register for the reset bit to go to 0 (it is  	 * auto-clearing).  This should happen within 0.5 seconds per the diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c index 5ca66815c..3d343ee88 100644 --- a/cpu/ppc4xx/miiphy.c +++ b/cpu/ppc4xx/miiphy.c @@ -113,6 +113,9 @@ int miiphy_read (unsigned char addr, unsigned char reg,  	printf ("a2: write: EMAC_STACR=0x%0x\n", sta_reg);	/* test-only */  #endif +#ifdef CONFIG_PHY_CMD_DELAY +	udelay (CONFIG_PHY_CMD_DELAY);		/* Intel LXT971A needs this */ +#endif  	sta_reg = in32 (EMAC_STACR);  	i = 0;  	while ((sta_reg & EMAC_STACR_OC) == 0) { @@ -173,6 +176,9 @@ int miiphy_write (unsigned char addr, unsigned char reg,  	out32 (EMAC_STACR, sta_reg); +#ifdef CONFIG_PHY_CMD_DELAY +	udelay (CONFIG_PHY_CMD_DELAY);		/* Intel LXT971A needs this */ +#endif  	/* wait for completion */  	i = 0;  	sta_reg = in32 (EMAC_STACR); diff --git a/drivers/Makefile b/drivers/Makefile index 2bdabae8e..2999eb465 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk  LIB	= libdrivers.a  OBJS	= 3c589.o 5701rls.o ali512x.o \ -	  bcm570x.o bcm570x_autoneg.o cfb_console.o \ +	  bcm570x.o bcm570x_autoneg.o cfb_console.o cfi_flash.o \  	  cs8900.o ct69000.o dataflash.o dc2114x.o          \  	  e1000.o eepro100.o \  	  i8042.o i82365.o inca-ip_sw.o \ diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c new file mode 100644 index 000000000..fb769253d --- /dev/null +++ b/drivers/cfi_flash.c @@ -0,0 +1,1018 @@ +/* + * (C) Copyright 2002 + * Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.com + * + * Copyright (C) 2003 Arabella Software Ltd. + * Yuli Barcohen <yuli@arabellasw.com> + * Modified to work with AMD flashes + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * History + * 01/20/2004 - combined variants of original driver. + * + * Tested Architectures + * Port Width  Chip Width    # of banks    Flash Chip  Board + * 32          16            1             23F128J3    seranoa/eagle + *  + */ + +/* The DEBUG define must be before common to enable debugging */ +#undef  DEBUG  +#include <common.h> +#include <asm/processor.h> +#ifdef  CFG_FLASH_CFI_DRIVER +/* + * This file implements a Common Flash Interface (CFI) driver for U-Boot. + * The width of the port and the width of the chips are determined at initialization. + * These widths are used to calculate the address for access CFI data structures. + * It has been tested on an Intel Strataflash implementation and AMD 29F016D. + * + * References + * JEDEC Standard JESD68 - Common Flash Interface (CFI) + * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes + * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets + * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet + * + * TODO + * + * Use Primary Extended Query table (PRI) and Alternate Algorithm Query + * Table (ALT) to determine if protection is available + * + * Add support for other command sets Use the PRI and ALT to determine command set + * Verify erase and program timeouts. + */ + +#define FLASH_CMD_CFI			0x98 +#define FLASH_CMD_READ_ID		0x90 +#define FLASH_CMD_RESET			0xff +#define FLASH_CMD_BLOCK_ERASE		0x20 +#define FLASH_CMD_ERASE_CONFIRM		0xD0 +#define FLASH_CMD_WRITE			0x40 +#define FLASH_CMD_PROTECT		0x60 +#define FLASH_CMD_PROTECT_SET		0x01 +#define FLASH_CMD_PROTECT_CLEAR		0xD0 +#define FLASH_CMD_CLEAR_STATUS		0x50 +#define FLASH_CMD_WRITE_TO_BUFFER       0xE8 +#define FLASH_CMD_WRITE_BUFFER_CONFIRM  0xD0 + +#define FLASH_STATUS_DONE		0x80 +#define FLASH_STATUS_ESS		0x40 +#define FLASH_STATUS_ECLBS		0x20 +#define FLASH_STATUS_PSLBS		0x10 +#define FLASH_STATUS_VPENS		0x08 +#define FLASH_STATUS_PSS		0x04 +#define FLASH_STATUS_DPS		0x02 +#define FLASH_STATUS_R			0x01 +#define FLASH_STATUS_PROTECT		0x01 + +#define AMD_CMD_RESET			0xF0 +#define AMD_CMD_WRITE			0xA0 +#define AMD_CMD_ERASE_START		0x80 +#define AMD_CMD_ERASE_SECTOR		0x30 + +#define AMD_STATUS_TOGGLE		0x40 +#define AMD_STATUS_ERROR		0x20 + +#define FLASH_OFFSET_CFI		0x55 +#define FLASH_OFFSET_CFI_RESP		0x10 +#define FLASH_OFFSET_PRIMARY_VENDOR     0x13 +#define FLASH_OFFSET_WTOUT		0x1F +#define FLASH_OFFSET_WBTOUT             0x20 +#define FLASH_OFFSET_ETOUT		0x21 +#define FLASH_OFFSET_CETOUT             0x22 +#define FLASH_OFFSET_WMAX_TOUT		0x23 +#define FLASH_OFFSET_WBMAX_TOUT         0x24 +#define FLASH_OFFSET_EMAX_TOUT		0x25 +#define FLASH_OFFSET_CEMAX_TOUT         0x26 +#define FLASH_OFFSET_SIZE		0x27 +#define FLASH_OFFSET_INTERFACE          0x28 +#define FLASH_OFFSET_BUFFER_SIZE        0x2A +#define FLASH_OFFSET_NUM_ERASE_REGIONS	0x2C +#define FLASH_OFFSET_ERASE_REGIONS	0x2D +#define FLASH_OFFSET_PROTECT		0x02 +#define FLASH_OFFSET_USER_PROTECTION    0x85 +#define FLASH_OFFSET_INTEL_PROTECTION   0x81 + + +#define FLASH_MAN_CFI			0x01000000 + +#define CFI_CMDSET_NONE             0 +#define CFI_CMDSET_INTEL_EXTENDED   1 +#define CFI_CMDSET_AMD_STANDARD     2 +#define CFI_CMDSET_INTEL_STANDARD   3 +#define CFI_CMDSET_AMD_EXTENDED     4 +#define CFI_CMDSET_MITSU_STANDARD   256 +#define CFI_CMDSET_MITSU_EXTENDED   257 +#define CFI_CMDSET_SST              258 + + +typedef union { +	unsigned char c; +	unsigned short w; +	unsigned long l; +	unsigned long long ll; +} cfiword_t; + +typedef union { +	volatile unsigned char  *cp; +	volatile unsigned short *wp; +	volatile unsigned long  *lp; +	volatile unsigned long long *llp; +} cfiptr_t; + +#define NUM_ERASE_REGIONS 4 + +static ulong bank_base[CFG_MAX_FLASH_BANKS] = CFG_FLASH_BANKS_LIST; + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/ + +/*----------------------------------------------------------------------- + * Functions + */ + +typedef unsigned long flash_sect_t; + +static void flash_add_byte(flash_info_t *info, cfiword_t * cword, uchar c); +static void flash_make_cmd(flash_info_t * info, uchar cmd, void * cmdbuf); +static void flash_write_cmd(flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd); +static void flash_unlock_seq(flash_info_t *info); +static int flash_isequal(flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd); +static int flash_isset(flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd); +static int flash_toggle(flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd); +static int flash_detect_cfi(flash_info_t * info); +static ulong flash_get_size (ulong base, int banknum); +static int flash_write_cfiword (flash_info_t *info, ulong dest, cfiword_t cword); +static int flash_full_status_check(flash_info_t * info, flash_sect_t sector, ulong tout, char * prompt); +#ifdef CFG_FLASH_USE_BUFFER_WRITE +static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp, int len); +#endif + +#ifdef DEBUG +void print_longlong(char * str, unsigned long long data) +{ +	int i; +	char *cp; +	cp = (unsigned char *)&data; +	for(i=0;i<8; i++)  +		sprintf(&str[i*2], "%2.2x", *cp++);   +} +#endif + + +/*----------------------------------------------------------------------- + * create an address based on the offset and the port width + */ +inline uchar * flash_make_addr(flash_info_t * info, flash_sect_t sect, uint offset) +{ +	return ((uchar *)(info->start[sect] + (offset * info->portwidth))); +} +/*----------------------------------------------------------------------- + * read a character at a port width address + */ +inline uchar flash_read_uchar(flash_info_t * info, uint offset) +{ +	uchar *cp; +	cp = flash_make_addr(info, 0, offset); +	return (cp[info->portwidth - 1]); +} + +/*----------------------------------------------------------------------- + * read a short word by swapping for ppc format. + */ +ushort flash_read_ushort(flash_info_t * info, flash_sect_t sect,  uint offset) +{ +    uchar * addr; + +    addr = flash_make_addr(info, sect, offset); +    return ((addr[(2*info->portwidth) - 1] << 8) | addr[info->portwidth - 1]); + +} + +/*----------------------------------------------------------------------- + * read a long word by picking the least significant byte of each maiximum + * port size word. Swap for ppc format. + */ +ulong flash_read_long(flash_info_t * info, flash_sect_t sect,  uint offset) +{ +    uchar * addr; + +    addr = flash_make_addr(info, sect, offset); +    return ( (addr[(2*info->portwidth) - 1] << 24 ) | (addr[(info->portwidth) -1] << 16) | +	    (addr[(4*info->portwidth) - 1] << 8) | addr[(3*info->portwidth) - 1]); + +} + +/*----------------------------------------------------------------------- + */ +unsigned long flash_init (void) +{ +	unsigned long size = 0; +	int i; + +	/* Init: no FLASHes known */ +	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { +		flash_info[i].flash_id = FLASH_UNKNOWN; +		size += flash_info[i].size = flash_get_size(bank_base[i], i); +		if (flash_info[i].flash_id == FLASH_UNKNOWN) { +			printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", +				i, flash_info[i].size, flash_info[i].size << 20); +		} +	} + +	/* Monitor protection ON by default */ +#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE) +	flash_protect(FLAG_PROTECT_SET, +		      CFG_MONITOR_BASE, +		      CFG_MONITOR_BASE + monitor_flash_len - 1, +		      &flash_info[0]); +#endif + +	return (size); +} + +/*----------------------------------------------------------------------- + */ +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ +	int rcode = 0; +	int prot; +	flash_sect_t sect; + +	if( info->flash_id != FLASH_MAN_CFI) { +		printf ("Can't erase unknown flash type - aborted\n"); +		return 1; +	} +	if ((s_first < 0) || (s_first > s_last)) { +		printf ("- no sectors to erase\n"); +		return 1; +	} + +	prot = 0; +	for (sect=s_first; sect<=s_last; ++sect) { +		if (info->protect[sect]) { +			prot++; +		} +	} +	if (prot) { +		printf ("- Warning: %d protected sectors will not be erased!\n", +			prot); +	} else { +		printf ("\n"); +	} + + +	for (sect = s_first; sect<=s_last; sect++) { +		if (info->protect[sect] == 0) { /* not protected */ +			switch(info->vendor) { +			case CFI_CMDSET_INTEL_STANDARD: +			case CFI_CMDSET_INTEL_EXTENDED: +				flash_write_cmd(info, sect, 0, FLASH_CMD_CLEAR_STATUS); +				flash_write_cmd(info, sect, 0, FLASH_CMD_BLOCK_ERASE); +				flash_write_cmd(info, sect, 0, FLASH_CMD_ERASE_CONFIRM); +				break; +			case CFI_CMDSET_AMD_STANDARD: +			case CFI_CMDSET_AMD_EXTENDED: +				flash_unlock_seq(info); +				flash_write_cmd(info, sect, 0x555, AMD_CMD_ERASE_START); +				flash_unlock_seq(info); +				flash_write_cmd(info, sect, 0, AMD_CMD_ERASE_SECTOR); +				break; +			default: +				debug("Unkown flash vendor %d\n", info->vendor); +				break; +			} + +			if(flash_full_status_check(info, sect, info->erase_blk_tout, "erase")) { +				rcode = 1; +			} else +				printf("."); +		} +	} +	printf (" done\n"); +	return rcode; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info  (flash_info_t *info) +{ +	int i; + +	if (info->flash_id != FLASH_MAN_CFI) { +		printf ("missing or unknown FLASH type\n"); +		return; +	} + +	printf("CFI conformant FLASH (%d x %d)", +	       (info->portwidth	 << 3 ), (info->chipwidth  << 3 )); +	printf ("  Size: %ld MB in %d Sectors\n", +		info->size >> 20, info->sector_count); +	printf(" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n", +	       info->erase_blk_tout, info->write_tout, info->buffer_write_tout, info->buffer_size); + +	printf ("  Sector Start Addresses:"); +	for (i=0; i<info->sector_count; ++i) { +#ifdef CFG_FLASH_EMPTY_INFO +		int k; +		int size; +		int erased; +		volatile unsigned long *flash; + +		/* +		 * Check if whole sector is erased +		 */ +		if (i != (info->sector_count-1)) +		  size = info->start[i+1] - info->start[i]; +		else +		  size = info->start[0] + info->size - info->start[i]; +		erased = 1; +		flash = (volatile unsigned long *)info->start[i]; +		size = size >> 2;        /* divide by 4 for longword access */ +		for (k=0; k<size; k++) +		  { +		    if (*flash++ != 0xffffffff) +		      { +			erased = 0; +			break; +		      } +		  } + +		if ((i % 5) == 0) +			printf ("\n"); +		/* print empty and read-only info */ +		printf (" %08lX%s%s", +			info->start[i], +			erased ? " E" : "  ", +			info->protect[i] ? "RO " : "   "); +#else +		if ((i % 5) == 0) +			printf ("\n   "); +		printf (" %08lX%s", +			info->start[i], +			info->protect[i] ? " (RO)" : "     "); +#endif +	} +	printf ("\n"); +	return; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ +	ulong wp; +	ulong cp; +	int aln; +	cfiword_t cword; +	int i, rc; + +	/* get lower aligned address */ +	wp = (addr & ~(info->portwidth - 1)); + +	/* handle unaligned start */ +	if((aln = addr - wp) != 0) { +		cword.l = 0; +		cp = wp; +		for(i=0;i<aln; ++i, ++cp) +			flash_add_byte(info, &cword, (*(uchar *)cp)); + +		for(; (i< info->portwidth) && (cnt > 0) ; i++) { +			flash_add_byte(info, &cword, *src++); +			cnt--; +			cp++; +		} +		for(; (cnt == 0) && (i < info->portwidth); ++i, ++cp) +			flash_add_byte(info, &cword, (*(uchar *)cp)); +		if((rc = flash_write_cfiword(info, wp, cword)) != 0) +			return rc; +		wp = cp; +	} + +#ifdef CFG_FLASH_USE_BUFFER_WRITE +	while(cnt >= info->portwidth) { +		i = info->buffer_size > cnt? cnt: info->buffer_size; +		if((rc = flash_write_cfibuffer(info, wp, src,i)) != ERR_OK) +			return rc; +		wp += i; +		src += i; +		cnt -=i; +	} +#else +	/* handle the aligned part */ +	while(cnt >= info->portwidth) { +		cword.l = 0; +		for(i = 0; i < info->portwidth; i++) { +			flash_add_byte(info, &cword, *src++); +		} +		if((rc = flash_write_cfiword(info, wp, cword)) != 0) +			return rc; +		wp += info->portwidth; +		cnt -= info->portwidth; +	} +#endif /* CFG_FLASH_USE_BUFFER_WRITE */ +	if (cnt == 0) { +		return (0); +	} + +	/* +	 * handle unaligned tail bytes +	 */ +	cword.l = 0; +	for (i=0, cp=wp; (i<info->portwidth) && (cnt>0); ++i, ++cp) { +		flash_add_byte(info, &cword, *src++); +		--cnt; +	} +	for (; i<info->portwidth; ++i, ++cp) { +		flash_add_byte(info, & cword, (*(uchar *)cp)); +	} + +	return flash_write_cfiword(info, wp, cword); +} + +/*----------------------------------------------------------------------- + */ +#ifdef CFG_FLASH_PROTECTION + +int flash_real_protect(flash_info_t *info, long sector, int prot) +{ +	int retcode = 0; + +	flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); +	flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT); +	if(prot) +		flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_SET); +	else +		flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_CLEAR); + +	if((retcode = flash_full_status_check(info, sector, info->erase_blk_tout, +					 prot?"protect":"unprotect")) == 0) { + +		info->protect[sector] = prot; +		/* Intel's unprotect unprotects all locking */ +		if(prot == 0) { +			flash_sect_t i; +			for(i = 0 ; i<info->sector_count; i++) { +				if(info->protect[i]) +					flash_real_protect(info, i, 1); +			} +		} +	} + +	return retcode; + } +/*----------------------------------------------------------------------- + * flash_read_user_serial - read the OneTimeProgramming cells + */ +void flash_read_user_serial(flash_info_t * info, void * buffer, int offset, int len) +{ +	uchar * src; +	uchar * dst; + +	dst = buffer; +	src = flash_make_addr(info, 0, FLASH_OFFSET_USER_PROTECTION); +	flash_write_cmd(info,0, 0, FLASH_CMD_READ_ID); +	memcpy(dst,src + offset,len); +	flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); +} +/* + * flash_read_factory_serial - read the device Id from the protection area + */ +void flash_read_factory_serial(flash_info_t * info, void * buffer, int offset, int len) +{ +	uchar * src; +	 +	src = flash_make_addr(info, 0, FLASH_OFFSET_INTEL_PROTECTION); +	flash_write_cmd(info,0, 0, FLASH_CMD_READ_ID); +	memcpy(buffer,src + offset,len); +	flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); +} + +#endif /* CFG_FLASH_PROTECTION */ + +static int flash_poll_status(flash_info_t * info, flash_sect_t sect)  +{ +	int retval; +	switch(info->vendor) { +	case CFI_CMDSET_INTEL_STANDARD: +	case CFI_CMDSET_INTEL_EXTENDED: +		retval = !flash_isset(info, sect, 0, FLASH_STATUS_DONE); +		break; +	case CFI_CMDSET_AMD_STANDARD: +	case CFI_CMDSET_AMD_EXTENDED: +		retval =  flash_toggle(info, sect, 0, AMD_STATUS_TOGGLE); +		break; +	default: +		retval = 0; +	} +	return retval; +} +/*----------------------------------------------------------------------- + *  wait for XSR.7 to be set. Time out with an error if it does not. + *  This routine does not set the flash to read-array mode. + */ +static int flash_status_check(flash_info_t * info, flash_sect_t sector, ulong tout, char * prompt) +{ +	ulong start; + +	/* Wait for command completion */ +	start = get_timer (0); +	while (flash_poll_status(info, sector)) { +		if (get_timer(start) > info->erase_blk_tout) { +			printf("Flash %s timeout at address %lx\n", prompt, info->start[sector]); +			flash_write_cmd(info, sector, 0, info->cmd_reset); +			return ERR_TIMOUT; +		} +	} +	return ERR_OK; +} +/*----------------------------------------------------------------------- + * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check. + * This routine sets the flash to read-array mode. + */ +static int flash_full_status_check(flash_info_t * info, flash_sect_t sector, ulong tout, char * prompt) +{ +	int retcode; +	retcode = flash_status_check(info, sector, tout, prompt); +	switch(info->vendor) { +	case CFI_CMDSET_INTEL_EXTENDED: +	case CFI_CMDSET_INTEL_STANDARD: +		if((retcode == ERR_OK) && !flash_isequal(info,sector, 0, FLASH_STATUS_DONE)) { +			retcode = ERR_INVAL; +			printf("Flash %s error at address %lx\n", prompt,info->start[sector]); +			if(flash_isset(info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)){ +				printf("Command Sequence Error.\n"); +			} else if(flash_isset(info, sector, 0, FLASH_STATUS_ECLBS)){ +				printf("Block Erase Error.\n"); +				retcode = ERR_NOT_ERASED; +			} else if (flash_isset(info, sector, 0, FLASH_STATUS_PSLBS)) { +				printf("Locking Error\n"); +			} +		if(flash_isset(info, sector, 0, FLASH_STATUS_DPS)){ +			printf("Block locked.\n"); +			retcode = ERR_PROTECTED; +		} +		if(flash_isset(info, sector, 0, FLASH_STATUS_VPENS)) +			printf("Vpp Low Error.\n"); +		} +		flash_write_cmd(info, sector, 0, FLASH_CMD_RESET); +		break; +	default: +		break; +	} +	return retcode; +} +/*----------------------------------------------------------------------- + */ +static void flash_add_byte(flash_info_t *info, cfiword_t * cword, uchar c) +{ +	switch(info->portwidth) { +	case FLASH_CFI_8BIT: +		cword->c = c; +		break; +	case FLASH_CFI_16BIT: +		cword->w = (cword->w << 8) | c; +		break; +	case FLASH_CFI_32BIT: +		cword->l = (cword->l << 8) | c; +		break; +	case FLASH_CFI_64BIT: +		cword->ll = (cword->ll << 8) | c; +		break; +	} +} + + +/*----------------------------------------------------------------------- + * make a proper sized command based on the port and chip widths + */ +static void flash_make_cmd(flash_info_t * info, uchar cmd, void * cmdbuf) +{ +	int i; +	uchar *cp = (uchar *)cmdbuf; +	for(i=0; i< info->portwidth; i++) +		*cp++ = ((i+1) % info->chipwidth) ? '\0':cmd; +} + +/* + * Write a proper sized command to the correct address + */ +static void flash_write_cmd(flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd) +{ + +	volatile cfiptr_t addr; +	cfiword_t cword; +	addr.cp = flash_make_addr(info, sect, offset); +	flash_make_cmd(info, cmd, &cword); +	switch(info->portwidth) { +	case FLASH_CFI_8BIT: +		debug("fwc addr %p cmd %x %x 8bit x %d bit\n",addr.cp, cmd, cword.c,  +		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH); +		*addr.cp = cword.c; +		break; +	case FLASH_CFI_16BIT: +		debug("fwc addr %p cmd %x %4.4x 16bit x %d bit\n",addr.wp, cmd, cword.w,  +		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH); +		*addr.wp = cword.w; +		break; +	case FLASH_CFI_32BIT: +		debug("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n",addr.lp, cmd, cword.l,  +		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH); +		*addr.lp = cword.l; +		break; +	case FLASH_CFI_64BIT: +#ifdef DEBUG +	        {  +			char str[20]; +			print_longlong(str, cword.ll); +	 +			printf("fwc addr %p cmd %x %s 64 bit x %d bit\n",addr.llp, cmd, str,  +			       info->chipwidth << CFI_FLASH_SHIFT_WIDTH); +		} +#endif +		*addr.llp = cword.ll; +		break; +	} +} + +static void flash_unlock_seq(flash_info_t *info) +{ +	flash_write_cmd(info, 0, 0x555, 0xAA); +	flash_write_cmd(info, 0, 0x2AA, 0x55); +} +/*----------------------------------------------------------------------- + */ +static int flash_isequal(flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd) +{ +	cfiptr_t cptr; +	cfiword_t cword; +	int retval; +	cptr.cp = flash_make_addr(info, sect, offset); +	flash_make_cmd(info, cmd, &cword); + +	debug("is= cmd %x(%c) addr %p ", cmd,cmd, cptr.cp); +	switch(info->portwidth) { +	case FLASH_CFI_8BIT: +		debug("is= %x %x\n", cptr.cp[0], cword.c); +		retval = (cptr.cp[0] == cword.c); +		break; +	case FLASH_CFI_16BIT: +		debug("is= %4.4x %4.4x\n", cptr.wp[0], cword.w); +		retval = (cptr.wp[0] == cword.w); +		break; +	case FLASH_CFI_32BIT: +		debug("is= %8.8lx %8.8lx\n", cptr.lp[0], cword.l); +		retval = (cptr.lp[0] == cword.l); +		break; +	case FLASH_CFI_64BIT: +#ifdef DEBUG		 +	        { +			char str1[20]; +			char str2[20]; +			print_longlong(str1, cptr.llp[0]); +			print_longlong(str2, cword.ll); +			printf("is= %s %s\n", str1, str2); +		} +#endif +		retval = (cptr.llp[0] == cword.ll); +		break; +	default: +		retval = 0; +		break; +	} +	return retval; +} +/*----------------------------------------------------------------------- + */ +static int flash_isset(flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd) +{ +	cfiptr_t cptr; +	cfiword_t cword; +	int retval; +	cptr.cp = flash_make_addr(info, sect, offset); +	flash_make_cmd(info, cmd, &cword); +	switch(info->portwidth) { +	case FLASH_CFI_8BIT: +		retval = ((cptr.cp[0] & cword.c) == cword.c); +		break; +	case FLASH_CFI_16BIT: +		retval = ((cptr.wp[0] & cword.w) == cword.w); +		break; +	case FLASH_CFI_32BIT: +		retval = ((cptr.lp[0] & cword.l) == cword.l); +		break; +	case FLASH_CFI_64BIT: +		retval = ((cptr.llp[0] & cword.ll) == cword.ll); +	default: +		retval = 0; +		break; +	} +	return retval; +} + +/*----------------------------------------------------------------------- + */ +static int flash_toggle(flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd) +{ +	cfiptr_t cptr; +	cfiword_t cword; +	int retval; +	cptr.cp = flash_make_addr(info, sect, offset); +	flash_make_cmd(info, cmd, &cword); +	switch(info->portwidth) { +	case FLASH_CFI_8BIT: +		retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c)); +		break; +	case FLASH_CFI_16BIT: +		retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w)); +		break; +	case FLASH_CFI_32BIT: +		retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l)); +		break; +	case FLASH_CFI_64BIT: +		retval = ((cptr.llp[0] & cword.ll) != (cptr.llp[0] & cword.ll)); +		break; +	default: +		retval = 0; +		break; +	} +	return retval; +} + +/*----------------------------------------------------------------------- + * detect if flash is compatible with the Common Flash Interface (CFI) + * http://www.jedec.org/download/search/jesd68.pdf + * +*/ +static int flash_detect_cfi(flash_info_t * info) +{ + +    puts("flash detect cfi\n"); + +	for(info->portwidth=FLASH_CFI_8BIT; info->portwidth <= FLASH_CFI_64BIT; +	    info->portwidth <<= 1) { +	  /*		for(info->chipwidth = info->portwidth; +			info->chipwidth > 0; +			info->chipwidth >>= 1) { */ +		for(info->chipwidth =FLASH_CFI_BY8; +		    info->chipwidth <= info->portwidth; +		    info->chipwidth <<= 1) {  +			flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); +			flash_write_cmd(info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI); +			if(flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP,'Q') && +			   flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') && +			   flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) { +				debug("found port %d chip %d ", info->portwidth, info->chipwidth); +				debug("port %d bits chip %d bits\n", info->portwidth << CFI_FLASH_SHIFT_WIDTH,  +				       info->chipwidth << CFI_FLASH_SHIFT_WIDTH); +				return 1; +			} +		} +	} +	puts("not found\n"); +	return 0; +} +/* + * The following code cannot be run from FLASH! + * + */ +static ulong flash_get_size (ulong base, int banknum) +{ +	flash_info_t * info = &flash_info[banknum]; +	int i, j; +	flash_sect_t sect_cnt; +	unsigned long sector; +	unsigned long tmp; +	int size_ratio; +	uchar num_erase_regions; +	int  erase_region_size; +	int  erase_region_count; + +	info->start[0] = base; + +	if(flash_detect_cfi(info)){ +		info->vendor = flash_read_ushort(info, 0, FLASH_OFFSET_PRIMARY_VENDOR); +		switch(info->vendor) { +		case CFI_CMDSET_INTEL_STANDARD: +		case CFI_CMDSET_INTEL_EXTENDED: +		default: +			info->cmd_reset = FLASH_CMD_RESET; +			break; +		case CFI_CMDSET_AMD_STANDARD: +		case CFI_CMDSET_AMD_EXTENDED: +			info->cmd_reset = AMD_CMD_RESET; +			break; +		} +			 +		debug("manufacturer is %d\n", info->vendor); +		size_ratio = info->portwidth / info->chipwidth; +		num_erase_regions = flash_read_uchar(info, FLASH_OFFSET_NUM_ERASE_REGIONS); +		debug("size_ration %d port %d bits chip %d bits\n", size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,  +			       info->chipwidth << CFI_FLASH_SHIFT_WIDTH); +		debug("found %d erase regions\n", num_erase_regions); +		sect_cnt = 0; +		sector = base; +		for(i = 0 ; i < num_erase_regions; i++) { +			if(i > NUM_ERASE_REGIONS) { +				printf("%d erase regions found, only %d used\n", +				       num_erase_regions, NUM_ERASE_REGIONS); +				break; +			} +			tmp = flash_read_long(info, 0, FLASH_OFFSET_ERASE_REGIONS + i*4); +			erase_region_size = (tmp & 0xffff)? ((tmp & 0xffff) * 256): 128; +			tmp >>= 16; +			erase_region_count = (tmp & 0xffff) +1; +			for(j = 0; j< erase_region_count; j++) { +				info->start[sect_cnt] = sector; +				sector += (erase_region_size * size_ratio); +				info->protect[sect_cnt] = flash_isset(info, sect_cnt, FLASH_OFFSET_PROTECT, FLASH_STATUS_PROTECT); +				sect_cnt++; +			} +		} + +		info->sector_count = sect_cnt; +		/* multiply the size by the number of chips */ +		info->size = (1 << flash_read_uchar(info, FLASH_OFFSET_SIZE)) * size_ratio; +		info->buffer_size = (1 << flash_read_ushort(info, 0, FLASH_OFFSET_BUFFER_SIZE)); +		tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_ETOUT); +		info->erase_blk_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_EMAX_TOUT))); +		tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WBTOUT); +		info->buffer_write_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_WBMAX_TOUT))); +		tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WTOUT); +		info->write_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_WMAX_TOUT)))/ 1000; +		info->flash_id = FLASH_MAN_CFI; +	} + +	flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); +	return(info->size); +} + + +/*----------------------------------------------------------------------- + */ +static int flash_write_cfiword (flash_info_t *info, ulong dest, cfiword_t cword) +{ + +	cfiptr_t ctladdr; +	cfiptr_t cptr; +	int flag; + +	ctladdr.cp = flash_make_addr(info, 0, 0); +	cptr.cp = (uchar *)dest; + + +	/* Check if Flash is (sufficiently) erased */ +	switch(info->portwidth) { +	case FLASH_CFI_8BIT: +		flag = ((cptr.cp[0] & cword.c) == cword.c); +		break; +	case FLASH_CFI_16BIT: +		flag = ((cptr.wp[0] & cword.w) == cword.w); +		break; +	case FLASH_CFI_32BIT: +		flag = ((cptr.lp[0] & cword.l)	== cword.l); +		break; +	case FLASH_CFI_64BIT: +		flag = ((cptr.lp[0] & cword.ll) == cword.ll); +		break; +	default: +		return 2; +	} +	if(!flag) +		return 2; + +	/* Disable interrupts which might cause a timeout here */ +	flag = disable_interrupts(); + +	switch(info->vendor) { +	case CFI_CMDSET_INTEL_EXTENDED: +	case CFI_CMDSET_INTEL_STANDARD: +		flash_write_cmd(info, 0, 0, FLASH_CMD_CLEAR_STATUS); +		flash_write_cmd(info, 0, 0, FLASH_CMD_WRITE); +		break; +	case CFI_CMDSET_AMD_EXTENDED: +	case CFI_CMDSET_AMD_STANDARD: +		flash_unlock_seq(info); +		flash_write_cmd(info, 0, 0x555, AMD_CMD_WRITE); +		break; +	} + +	switch(info->portwidth) { +	case FLASH_CFI_8BIT: +		cptr.cp[0] = cword.c; +		break; +	case FLASH_CFI_16BIT: +		cptr.wp[0] = cword.w; +		break; +	case FLASH_CFI_32BIT: +		cptr.lp[0] = cword.l; +		break; +	case FLASH_CFI_64BIT: +		cptr.llp[0] = cword.ll; +		break; +	} + +	/* re-enable interrupts if necessary */ +	if(flag) +		enable_interrupts(); + +	return flash_full_status_check(info, 0, info->write_tout, "write"); +} + +#ifdef CFG_FLASH_USE_BUFFER_WRITE + +/* loop through the sectors from the highest address + * when the passed address is greater or equal to the sector address + * we have a match + */ +static flash_sect_t find_sector(flash_info_t *info, ulong addr) +{ +	flash_sect_t sector; +	for(sector = info->sector_count - 1; sector >= 0; sector--) { +		if(addr >= info->start[sector]) +			break; +	} +	return sector; +} + +static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp, int len) +{ +	flash_sect_t sector; +	int cnt; +	int retcode; +	volatile cfiptr_t src; +	volatile cfiptr_t dst; + +	src.cp = cp; +	dst.cp = (uchar *)dest; +	sector = find_sector(info, dest); +	flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); +	flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER); +	if((retcode = flash_status_check(info, sector, info->buffer_write_tout, +					 "write to buffer")) == ERR_OK) { +		switch(info->portwidth) { +		case FLASH_CFI_8BIT: +			cnt = len; +			break; +		case FLASH_CFI_16BIT: +			cnt = len >> 1; +			break; +		case FLASH_CFI_32BIT: +			cnt = len >> 2; +			break; +		case FLASH_CFI_64BIT: +			cnt = len >> 3; +			break; +		default: +			return ERR_INVAL; +			break; +		} +		flash_write_cmd(info, sector, 0, (uchar)cnt-1); +		while(cnt-- > 0) { +			switch(info->portwidth) { +			case FLASH_CFI_8BIT: +				*dst.cp++ = *src.cp++; +				break; +			case FLASH_CFI_16BIT: +				*dst.wp++ = *src.wp++; +				break; +			case FLASH_CFI_32BIT: +				*dst.lp++ = *src.lp++; +				break; +			case FLASH_CFI_64BIT: +				*dst.llp++ = *src.llp++; +				break; +			default: +				return ERR_INVAL; +				break; +			} +		} +		flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_BUFFER_CONFIRM); +		retcode = flash_full_status_check(info, sector, info->buffer_write_tout, +					     "buffer write"); +	} +	flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); +	return retcode; +} +#endif /* CFG_USE_FLASH_BUFFER_WRITE */ +#endif /* CFG_FLASH_CFI */ diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c index 20acc0713..39b7e8e33 100644 --- a/drivers/pci_auto.c +++ b/drivers/pci_auto.c @@ -163,7 +163,8 @@ static void pciauto_prescan_setup_bridge(struct pci_controller *hose,  	/* Configure bus number registers */  	pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, PCI_BUS(dev)); -	pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus + 1); +	/* TBS: passed in sub_bus is correct, removed the +1 */ +	pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus);  	pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff);  	if (pci_mem) @@ -284,6 +285,7 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)  	unsigned int sub_bus = PCI_BUS(dev);  	unsigned short class;  	unsigned char prg_iface; +	int n;  	pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class); @@ -294,11 +296,19 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)  		pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_io);  		DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev)); -		pciauto_prescan_setup_bridge(hose, dev, sub_bus); - -		pci_hose_scan_bus(hose, hose->current_busno); +		 +		/* TBS: Passing in current_busno allows for sibling P2P bridges */ +		pciauto_prescan_setup_bridge(hose, dev, hose->current_busno); +		/*  +		 * TBS: need to figure out if this is a subordinate bridge on the bus  +		 * to be able to properly set the pri/sec/sub bridge registers. +		 */ +		n = pci_hose_scan_bus(hose, hose->current_busno); +		/* TBS: figure out the deepest we've gone for this leg */ +		sub_bus = max(n, sub_bus);  		pciauto_postscan_setup_bridge(hose, dev, sub_bus); +  		sub_bus = hose->current_busno;  		break; diff --git a/include/configs/DK1C20.h b/include/configs/DK1C20.h index 92c8e517e..f3570512e 100644 --- a/include/configs/DK1C20.h +++ b/include/configs/DK1C20.h @@ -647,8 +647,8 @@   * ASMI is for Cyclone devices only and only works when the configuration   * is loaded via JTAG or ASMI. Please see doc/README.dk1c20 for details.   *----------------------------------------------------------------------*/ -#define CONFIG_NIOS_ASMI			/* Enable ASMI		*/ -#define CFG_NIOS_ASMIBASE	0x00920b00	/* ASMI base address	*/ +#define CONFIG_NIOS_ASMI			   /* Enable ASMI	*/ +#define CFG_NIOS_ASMIBASE	CFG_NIOS_CPU_ASMI0 /* ASMI base address	*/  /*------------------------------------------------------------------------   * COMMANDS diff --git a/include/flash.h b/include/flash.h index 8f20887e4..0cfc76d32 100644 --- a/include/flash.h +++ b/include/flash.h @@ -42,7 +42,8 @@ typedef struct {  	ulong	erase_blk_tout;		/* maximum block erase timeout		*/  	ulong	write_tout;		/* maximum write timeout		*/  	ulong	buffer_write_tout;	/* maximum buffer write timeout		*/ - +	ushort  vendor;                 /* the primary vendor id                */ +	ushort  cmd_reset;              /* Vendor specific reset command        */  #endif  } flash_info_t; @@ -61,6 +62,8 @@ typedef struct {  #define FLASH_CFI_BY32		0x04  #define FLASH_CFI_BY64		0x08 +/* convert between bit value and numeric value */ +#define CFI_FLASH_SHIFT_WIDTH      3  /* Prototypes */  extern unsigned long flash_init (void); @@ -78,6 +81,8 @@ extern int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt);  /* board/?/flash.c */  #if defined(CFG_FLASH_PROTECTION)  extern int flash_real_protect(flash_info_t *info, long sector, int prot); +extern void flash_read_user_serial(flash_info_t * info, void * buffer, int offset, int len); +extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int offset, int len);  #endif	/* CFG_FLASH_PROTECTION */  /*----------------------------------------------------------------------- |