mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-30 18:05:48 +01:00 
			
		
		
		
	board/mpl/common: remove the old legacy flash
Signed-off-by: David Mueller <d.mueller@elsoft.ch> Signed-off-by: Stefan Roese <sr@denx.de>
This commit is contained in:
		
				
					committed by
					
						 Stefan Roese
						Stefan Roese
					
				
			
			
				
	
			
			
			
						parent
						
							06b174124e
						
					
				
				
					commit
					4b11dba975
				
			| @@ -53,13 +53,156 @@ extern int mem_test(ulong start, ulong ramsize, int quiet); | |||||||
| #define I2C_BACKUP_ADDR 0x7C00		/* 0x200 bytes for backup */ | #define I2C_BACKUP_ADDR 0x7C00		/* 0x200 bytes for backup */ | ||||||
| #define IMAGE_SIZE CONFIG_SYS_MONITOR_LEN	/* ugly, but it works for now */ | #define IMAGE_SIZE CONFIG_SYS_MONITOR_LEN	/* ugly, but it works for now */ | ||||||
|  |  | ||||||
| extern flash_info_t flash_info[];	/* info for FLASH chips */ | #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) | ||||||
|  | /*----------------------------------------------------------------------- | ||||||
|  |  * On PIP/MIP405 we have 3 (4) possible boot mode | ||||||
|  |  * | ||||||
|  |  * - Boot from Flash (Flash CS = CS0, MPS CS = CS1) | ||||||
|  |  * - Boot from MPS   (Flash CS = CS1, MPS CS = CS0) | ||||||
|  |  * - Boot from PCI with Flash map (Flash CS = CS0, MPS CS = CS1) | ||||||
|  |  * - Boot from PCI with MPS map   (Flash CS = CS1, MPS CS = CS0) | ||||||
|  |  * The flash init is the first board specific routine which is called | ||||||
|  |  * after code relocation (running from SDRAM) | ||||||
|  |  * The first thing we do is to map the Flash CS to the Flash area and | ||||||
|  |  * the MPS CS to the MPS area. Since the flash size is unknown at this | ||||||
|  |  * point, we use the max flash size and the lowest flash address as base. | ||||||
|  |  * | ||||||
|  |  * After flash detection we adjust the size of the CS area accordingly. | ||||||
|  |  * update_flash_size() will fix in wrong values in the flash_info structure, | ||||||
|  |  * misc_init_r() will fix the values in the board info structure | ||||||
|  |  */ | ||||||
|  | int get_boot_mode(void) | ||||||
|  | { | ||||||
|  | 	unsigned long pbcr; | ||||||
|  | 	int res = 0; | ||||||
|  | 	pbcr = mfdcr(CPC0_PSR); | ||||||
|  | 	if ((pbcr & PSR_ROM_WIDTH_MASK) == 0) | ||||||
|  | 		/* boot via MPS or MPS mapping */ | ||||||
|  | 		res = BOOT_MPS; | ||||||
|  | 	if (pbcr & PSR_ROM_LOC) | ||||||
|  | 		/* boot via PCI.. */ | ||||||
|  | 		res |= BOOT_PCI; | ||||||
|  | 	 return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Map the flash high (in boot area) | ||||||
|  |    This code can only be executed from SDRAM (after relocation). | ||||||
|  | */ | ||||||
|  | void setup_cs_reloc(void) | ||||||
|  | { | ||||||
|  | 	int mode; | ||||||
|  | 	/* | ||||||
|  | 	 * since we are relocated, we can set-up the CS finaly | ||||||
|  | 	 * but first of all, switch off PCI mapping (in case it | ||||||
|  | 	 * was a PCI boot) | ||||||
|  | 	 */ | ||||||
|  | 	out32r(PMM0MA, 0L); | ||||||
|  | 	/* get boot mode */ | ||||||
|  | 	mode = get_boot_mode(); | ||||||
|  | 	/* | ||||||
|  | 	 * we map the flash high in every case | ||||||
|  | 	 * first find out to which CS the flash is attached to | ||||||
|  | 	 */ | ||||||
|  | 	if (mode & BOOT_MPS) { | ||||||
|  | 		/* map flash high on CS1 and MPS on CS0 */ | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB0AP); | ||||||
|  | 		mtdcr(EBC0_CFGDATA, MPS_AP); | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB0CR); | ||||||
|  | 		mtdcr(EBC0_CFGDATA, MPS_CR); | ||||||
|  | 		/* | ||||||
|  | 		 * we use the default values (max values) for the flash | ||||||
|  | 		 * because its real size is not yet known | ||||||
|  | 		 */ | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB1AP); | ||||||
|  | 		mtdcr(EBC0_CFGDATA, FLASH_AP); | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB1CR); | ||||||
|  | 		mtdcr(EBC0_CFGDATA, FLASH_CR_B); | ||||||
|  | 	} else { | ||||||
|  | 		/* map flash high on CS0 and MPS on CS1 */ | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB1AP); | ||||||
|  | 		mtdcr(EBC0_CFGDATA, MPS_AP); | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB1CR); | ||||||
|  | 		mtdcr(EBC0_CFGDATA, MPS_CR); | ||||||
|  | 		/* | ||||||
|  | 		 * we use the default values (max values) for the flash | ||||||
|  | 		 * because its real size is not yet known | ||||||
|  | 		 */ | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB0AP); | ||||||
|  | 		mtdcr(EBC0_CFGDATA, FLASH_AP); | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB0CR); | ||||||
|  | 		mtdcr(EBC0_CFGDATA, FLASH_CR_B); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | #endif /* #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) */ | ||||||
|  |  | ||||||
|  | #ifdef CONFIG_SYS_UPDATE_FLASH_SIZE | ||||||
|  | /* adjust flash start and protection info */ | ||||||
|  | int update_flash_size(int flash_size) | ||||||
|  | { | ||||||
|  | 	int i = 0, mode; | ||||||
|  | 	flash_info_t *info = &flash_info[0]; | ||||||
|  | 	unsigned long flashcr; | ||||||
|  | 	unsigned long flash_base = (0 - flash_size) & 0xFFF00000; | ||||||
|  |  | ||||||
|  | 	if (flash_size > 128*1024*1024) { | ||||||
|  | 		printf("\n ### ERROR, wrong flash size: %X, reset board ###\n", | ||||||
|  | 		       flash_size); | ||||||
|  | 		hang(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if ((flash_size >> 20) != 0) | ||||||
|  | 		i = __ilog2(flash_size >> 20); | ||||||
|  |  | ||||||
|  | 	/* set up flash CS according to the size */ | ||||||
|  | 	mode = get_boot_mode(); | ||||||
|  | 	if (mode & BOOT_MPS) { | ||||||
|  | 		/* flash is on CS1 */ | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB1CR); | ||||||
|  | 		flashcr = mfdcr(EBC0_CFGDATA); | ||||||
|  | 		/* we map the flash high in every case */ | ||||||
|  | 		flashcr &= 0x0001FFFF; /* mask out address bits */ | ||||||
|  | 		flashcr |= flash_base; /* start addr */ | ||||||
|  | 		flashcr |= (i << 17); /* size addr */ | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB1CR); | ||||||
|  | 		mtdcr(EBC0_CFGDATA, flashcr); | ||||||
|  | 	} else { | ||||||
|  | 		/* flash is on CS0 */ | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB0CR); | ||||||
|  | 		flashcr = mfdcr(EBC0_CFGDATA); | ||||||
|  | 		/* we map the flash high in every case */ | ||||||
|  | 		flashcr &= 0x0001FFFF; /* mask out address bits */ | ||||||
|  | 		flashcr |= flash_base; /* start addr */ | ||||||
|  | 		flashcr |= (i << 17); /* size addr */ | ||||||
|  | 		mtdcr(EBC0_CFGADDR, PB0CR); | ||||||
|  | 		mtdcr(EBC0_CFGDATA, flashcr); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < info->sector_count; i++) | ||||||
|  | 		/* adjust sector start address */ | ||||||
|  | 		info->start[i] = flash_base + | ||||||
|  | 				(info->start[i] - CONFIG_SYS_FLASH_BASE); | ||||||
|  |  | ||||||
|  | 	/* unprotect all sectors */ | ||||||
|  | 	flash_protect(FLAG_PROTECT_CLEAR, | ||||||
|  | 		      info->start[0], | ||||||
|  | 		      0xFFFFFFFF, | ||||||
|  | 		      info); | ||||||
|  | 	flash_protect_default(); | ||||||
|  | 	/* protect reset vector too*/ | ||||||
|  | 	flash_protect(FLAG_PROTECT_SET, | ||||||
|  | 		      info->start[info->sector_count-1], | ||||||
|  | 		      0xFFFFFFFF, | ||||||
|  | 		      info); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| static int | static int | ||||||
| mpl_prg(uchar *src, ulong size) | mpl_prg(uchar *src, ulong size) | ||||||
| { | { | ||||||
| 	ulong start; | 	ulong start; | ||||||
| 	flash_info_t *info; | 	flash_info_t *info = &flash_info[0]; | ||||||
| 	int i, rc; | 	int i, rc; | ||||||
| #if defined(CONFIG_PATI) | #if defined(CONFIG_PATI) | ||||||
| 	int start_sect; | 	int start_sect; | ||||||
| @@ -69,8 +212,6 @@ mpl_prg(uchar *src, ulong size) | |||||||
| 	ulong *magic = (ulong *)src; | 	ulong *magic = (ulong *)src; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	info = &flash_info[0]; |  | ||||||
|  |  | ||||||
| #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) || defined(CONFIG_PATI) | #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) || defined(CONFIG_PATI) | ||||||
| 	if (uimage_to_cpu (magic[0]) != IH_MAGIC) { | 	if (uimage_to_cpu (magic[0]) != IH_MAGIC) { | ||||||
| 		puts("Bad Magic number\n"); | 		puts("Bad Magic number\n"); | ||||||
| @@ -96,12 +237,18 @@ mpl_prg(uchar *src, ulong size) | |||||||
| 	} | 	} | ||||||
| #if !defined(CONFIG_PATI) | #if !defined(CONFIG_PATI) | ||||||
| 	start = 0 - size; | 	start = 0 - size; | ||||||
| 	for (i = info->sector_count-1; i > 0; i--) { |  | ||||||
| 		info->protect[i] = 0; /* unprotect this sector */ | 	/* unprotect sectors used by u-boot */ | ||||||
|  | 	flash_protect(FLAG_PROTECT_CLEAR, | ||||||
|  | 		      start, | ||||||
|  | 		      0xFFFFFFFF, | ||||||
|  | 		      info); | ||||||
|  |  | ||||||
|  | 	/* search start sector */ | ||||||
|  | 	for (i = info->sector_count-1; i > 0; i--) | ||||||
| 		if (start >= info->start[i]) | 		if (start >= info->start[i]) | ||||||
| 			break; | 			break; | ||||||
| 	} |  | ||||||
| 	/* set-up flash location */ |  | ||||||
| 	/* now erase flash */ | 	/* now erase flash */ | ||||||
| 	printf("Erasing at %lx (sector %d) (start %lx)\n", | 	printf("Erasing at %lx (sector %d) (start %lx)\n", | ||||||
| 				start,i,info->start[i]); | 				start,i,info->start[i]); | ||||||
| @@ -114,22 +261,24 @@ mpl_prg(uchar *src, ulong size) | |||||||
| #else /* #if !defined(CONFIG_PATI */ | #else /* #if !defined(CONFIG_PATI */ | ||||||
| 	start = FIRM_START; | 	start = FIRM_START; | ||||||
| 	start_sect = -1; | 	start_sect = -1; | ||||||
| 	for (i = 0; i < info->sector_count; i++) { |  | ||||||
| 		if (start < info->start[i]) { |  | ||||||
| 			start_sect = i - 1; |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	info->protect[i - 1] = 0;	/* unprotect this sector */ | 	/* search start sector */ | ||||||
| 	for (; i < info->sector_count; i++) { | 	for (i = info->sector_count-1; i > 0; i--) | ||||||
| 		if ((start + size) < info->start[i]) | 		if (start >= info->start[i]) | ||||||
| 			break; | 			break; | ||||||
| 		info->protect[i] = 0;	/* unprotect this sector */ |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	i--; | 	start_sect = i; | ||||||
| 	/* set-up flash location */ |  | ||||||
|  | 	for (i = info->sector_count-1; i > 0; i--) | ||||||
|  | 		if ((start + size) >= info->start[i]) | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 	/* unprotect sectors used by u-boot */ | ||||||
|  | 	flash_protect(FLAG_PROTECT_CLEAR, | ||||||
|  | 		      start, | ||||||
|  | 		      start + size, | ||||||
|  | 		      info); | ||||||
|  |  | ||||||
| 	/* now erase flash */ | 	/* now erase flash */ | ||||||
| 	printf ("Erasing at %lx to %lx (sector %d to %d) (%lx to %lx)\n", | 	printf ("Erasing at %lx to %lx (sector %d to %d) (%lx to %lx)\n", | ||||||
| 		start, start + size, start_sect, i, | 		start, start + size, start_sect, i, | ||||||
| @@ -143,12 +292,17 @@ mpl_prg(uchar *src, ulong size) | |||||||
|  |  | ||||||
| #elif defined(CONFIG_VCMA9) | #elif defined(CONFIG_VCMA9) | ||||||
| 	start = 0; | 	start = 0; | ||||||
| 	for (i = 0; i <info->sector_count; i++) { |  | ||||||
| 		info->protect[i] = 0; /* unprotect this sector */ | 	/* search end sector */ | ||||||
|  | 	for (i = 0; i < info->sector_count; i++) | ||||||
| 		if (size < info->start[i]) | 		if (size < info->start[i]) | ||||||
| 		    break; | 		    break; | ||||||
| 	} |  | ||||||
| 	/* set-up flash location */ | 	flash_protect(FLAG_PROTECT_CLEAR, | ||||||
|  | 		      start, | ||||||
|  | 		      size, | ||||||
|  | 		      info); | ||||||
|  |  | ||||||
| 	/* now erase flash */ | 	/* now erase flash */ | ||||||
| 	printf("Erasing at %lx (sector %d) (start %lx)\n", | 	printf("Erasing at %lx (sector %d) (start %lx)\n", | ||||||
| 				start,0,info->start[0]); | 				start,0,info->start[0]); | ||||||
|   | |||||||
| @@ -30,11 +30,15 @@ typedef struct { | |||||||
| 	char eth_addr[21];	/* "00:60:C2:0a:00:00" */ | 	char eth_addr[21];	/* "00:60:C2:0a:00:00" */ | ||||||
| } backup_t; | } backup_t; | ||||||
|  |  | ||||||
|  | extern flash_info_t flash_info[];	/* info for FLASH chips */ | ||||||
|  |  | ||||||
| void get_backup_values(backup_t *buf); | void get_backup_values(backup_t *buf); | ||||||
|  |  | ||||||
| #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) | #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) | ||||||
| #define BOOT_MPS	0x01 | #define BOOT_MPS	0x01 | ||||||
| #define BOOT_PCI	0x02 | #define BOOT_PCI	0x02 | ||||||
|  | int get_boot_mode(void); | ||||||
|  | void setup_cs_reloc(void); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| void check_env(void); | void check_env(void); | ||||||
|   | |||||||
| @@ -1,872 +0,0 @@ | |||||||
| /* |  | ||||||
|  * (C) Copyright 2000, 2001 |  | ||||||
|  * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |  | ||||||
|  * |  | ||||||
|  * 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 |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Modified 4/5/2001 |  | ||||||
|  * Wait for completion of each sector erase command issued |  | ||||||
|  * 4/5/2001 |  | ||||||
|  * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Modified 3/7/2001 |  | ||||||
|  * - adapted for pip405, Denis Peter, MPL AG Switzerland |  | ||||||
|  * TODO: |  | ||||||
|  * clean-up |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include <common.h> |  | ||||||
|  |  | ||||||
| #if !defined(CONFIG_PATI) |  | ||||||
| #include <asm/ppc4xx.h> |  | ||||||
| #include <asm/processor.h> |  | ||||||
| #include "common_util.h" |  | ||||||
| #if defined(CONFIG_MIP405) |  | ||||||
| #include "../mip405/mip405.h" |  | ||||||
| #endif |  | ||||||
| #if defined(CONFIG_PIP405) |  | ||||||
| #include "../pip405/pip405.h" |  | ||||||
| #endif |  | ||||||
| #include <asm/4xx_pci.h> |  | ||||||
| #else /* defined(CONFIG_PATI) */ |  | ||||||
| #include <mpc5xx.h> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| flash_info_t	flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips	*/ |  | ||||||
| /*----------------------------------------------------------------------- |  | ||||||
|  * 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); |  | ||||||
|  |  | ||||||
| void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt); |  | ||||||
|  |  | ||||||
| #define ADDR0           0x5555 |  | ||||||
| #define ADDR1           0x2aaa |  | ||||||
| #define FLASH_WORD_SIZE unsigned short |  | ||||||
|  |  | ||||||
| #define FALSE           0 |  | ||||||
| #define TRUE            1 |  | ||||||
|  |  | ||||||
| #if !defined(CONFIG_PATI) |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------- |  | ||||||
|  * Some CS switching routines: |  | ||||||
|  * |  | ||||||
|  * On PIP/MIP405 we have 3 (4) possible boot mode |  | ||||||
|  * |  | ||||||
|  * - Boot from Flash (Flash CS = CS0, MPS CS = CS1) |  | ||||||
|  * - Boot from MPS   (Flash CS = CS1, MPS CS = CS0) |  | ||||||
|  * - Boot from PCI with Flash map (Flash CS = CS0, MPS CS = CS1) |  | ||||||
|  * - Boot from PCI with MPS map   (Flash CS = CS1, MPS CS = CS0) |  | ||||||
|  * The flash init is the first board specific routine which is called |  | ||||||
|  * after code relocation (running from SDRAM) |  | ||||||
|  * The first thing we do is to map the Flash CS to the Flash area and |  | ||||||
|  * the MPS CS to the MPS area. Since the flash size is unknown at this |  | ||||||
|  * point, we use the max flash size and the lowest flash address as base. |  | ||||||
|  * |  | ||||||
|  * After flash detection we adjust the size of the CS area accordingly. |  | ||||||
|  * The board_init_r will fill in wrong values in the board init structure, |  | ||||||
|  * but this will be fixed in the misc_init_r routine: |  | ||||||
|  * bd->bi_flashstart=0-flash_info[0].size |  | ||||||
|  * bd->bi_flashsize=flash_info[0].size-CONFIG_SYS_MONITOR_LEN |  | ||||||
|  * bd->bi_flashoffset=0 |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| int get_boot_mode(void) |  | ||||||
| { |  | ||||||
| 	unsigned long pbcr; |  | ||||||
| 	int res = 0; |  | ||||||
| 	pbcr = mfdcr (CPC0_PSR); |  | ||||||
| 	if ((pbcr & PSR_ROM_WIDTH_MASK) == 0) |  | ||||||
| 		/* boot via MPS or MPS mapping */ |  | ||||||
| 		res = BOOT_MPS; |  | ||||||
| 	if(pbcr & PSR_ROM_LOC) |  | ||||||
| 		/* boot via PCI.. */ |  | ||||||
| 		res |= BOOT_PCI; |  | ||||||
| 	 return res; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Map the flash high (in boot area) |  | ||||||
|    This code can only be executed from SDRAM (after relocation). |  | ||||||
| */ |  | ||||||
| void setup_cs_reloc(void) |  | ||||||
| { |  | ||||||
| 	int mode; |  | ||||||
| 	/* Since we are relocated, we can set-up the CS finaly |  | ||||||
| 	 * but first of all, switch off PCI mapping (in case it was a PCI boot) */ |  | ||||||
| 	out32r(PMM0MA,0L); |  | ||||||
| 	icache_enable (); /* we are relocated */ |  | ||||||
| 	/* get boot mode */ |  | ||||||
| 	mode=get_boot_mode(); |  | ||||||
| 	/* we map the flash high in every case */ |  | ||||||
| 	/* first findout on which cs the flash is */ |  | ||||||
| 	if(mode & BOOT_MPS) { |  | ||||||
| 		/* map flash high on CS1 and MPS on CS0 */ |  | ||||||
| 		mtdcr (EBC0_CFGADDR, PB0AP); |  | ||||||
| 		mtdcr (EBC0_CFGDATA, MPS_AP); |  | ||||||
| 		mtdcr (EBC0_CFGADDR, PB0CR); |  | ||||||
| 		mtdcr (EBC0_CFGDATA, MPS_CR); |  | ||||||
| 		/* we use the default values (max values) for the flash |  | ||||||
| 		 * because its real size is not yet known */ |  | ||||||
| 		mtdcr (EBC0_CFGADDR, PB1AP); |  | ||||||
| 		mtdcr (EBC0_CFGDATA, FLASH_AP); |  | ||||||
| 		mtdcr (EBC0_CFGADDR, PB1CR); |  | ||||||
| 		mtdcr (EBC0_CFGDATA, FLASH_CR_B); |  | ||||||
| 	} |  | ||||||
| 	else { |  | ||||||
| 		/* map flash high on CS0 and MPS on CS1 */ |  | ||||||
| 		mtdcr (EBC0_CFGADDR, PB1AP); |  | ||||||
| 		mtdcr (EBC0_CFGDATA, MPS_AP); |  | ||||||
| 		mtdcr (EBC0_CFGADDR, PB1CR); |  | ||||||
| 		mtdcr (EBC0_CFGDATA, MPS_CR); |  | ||||||
| 		/* we use the default values (max values) for the flash |  | ||||||
| 		 * because its real size is not yet known */ |  | ||||||
| 		mtdcr (EBC0_CFGADDR, PB0AP); |  | ||||||
| 		mtdcr (EBC0_CFGDATA, FLASH_AP); |  | ||||||
| 		mtdcr (EBC0_CFGADDR, PB0CR); |  | ||||||
| 		mtdcr (EBC0_CFGDATA, FLASH_CR_B); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif /* #if !defined(CONFIG_PATI) */ |  | ||||||
|  |  | ||||||
| unsigned long flash_init (void) |  | ||||||
| { |  | ||||||
| 	unsigned long size_b0; |  | ||||||
| 	int i; |  | ||||||
|  |  | ||||||
| #if !defined(CONFIG_PATI) |  | ||||||
| 	unsigned long flashcr,size_reg; |  | ||||||
| 	int mode; |  | ||||||
| 	extern char version_string; |  | ||||||
| 	char *p = &version_string; |  | ||||||
|  |  | ||||||
| 	/* Since we are relocated, we can set-up the CS finally */ |  | ||||||
| 	setup_cs_reloc(); |  | ||||||
| 	/* get and display boot mode */ |  | ||||||
| 	mode=get_boot_mode(); |  | ||||||
| 	if(mode & BOOT_PCI) |  | ||||||
| 		printf("(PCI Boot %s Map) ",(mode & BOOT_MPS) ? |  | ||||||
| 			"MPS" : "Flash"); |  | ||||||
| 	else |  | ||||||
| 		printf("(%s Boot) ",(mode & BOOT_MPS) ? |  | ||||||
| 			"MPS" : "Flash"); |  | ||||||
| #endif /* #if !defined(CONFIG_PATI) */ |  | ||||||
| 	/* Init: no FLASHes known */ |  | ||||||
| 	for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) { |  | ||||||
| 		flash_info[i].flash_id = FLASH_UNKNOWN; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* Static FLASH Bank configuration here - FIXME XXX */ |  | ||||||
|  |  | ||||||
| 	size_b0 = flash_get_size((vu_long *)CONFIG_SYS_MONITOR_BASE, &flash_info[0]); |  | ||||||
|  |  | ||||||
| 	if (flash_info[0].flash_id == FLASH_UNKNOWN) { |  | ||||||
| 		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", |  | ||||||
| 			size_b0, size_b0<<20); |  | ||||||
| 	} |  | ||||||
| 	/* protect the bootloader */ |  | ||||||
| 	/* Monitor protection ON by default */ |  | ||||||
| #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE |  | ||||||
| 	flash_protect(FLAG_PROTECT_SET, |  | ||||||
| 			CONFIG_SYS_MONITOR_BASE, |  | ||||||
| 			CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1, |  | ||||||
| 			&flash_info[0]); |  | ||||||
| #endif |  | ||||||
| #if !defined(CONFIG_PATI) |  | ||||||
| 	/* protect reset vector */ |  | ||||||
| 	flash_info[0].protect[flash_info[0].sector_count-1] = 1; |  | ||||||
| 	flash_info[0].size = size_b0; |  | ||||||
| 	/* set up flash cs according to the size */ |  | ||||||
| 	size_reg=(flash_info[0].size >>20); |  | ||||||
| 	switch (size_reg) { |  | ||||||
| 		case 0: |  | ||||||
| 		case 1: i=0; break; /* <= 1MB */ |  | ||||||
| 		case 2: i=1; break; /* = 2MB */ |  | ||||||
| 		case 4: i=2; break; /* = 4MB */ |  | ||||||
| 		case 8: i=3; break; /* = 8MB */ |  | ||||||
| 		case 16: i=4; break; /* = 16MB */ |  | ||||||
| 		case 32: i=5; break; /* = 32MB */ |  | ||||||
| 		case 64: i=6; break; /* = 64MB */ |  | ||||||
| 		case 128: i=7; break; /*= 128MB */ |  | ||||||
| 		default: |  | ||||||
| 			printf("\n #### ERROR, wrong size %ld MByte reset board #####\n",size_reg); |  | ||||||
| 			while(1); |  | ||||||
| 	} |  | ||||||
| 	if(mode & BOOT_MPS) { |  | ||||||
| 		/* flash is on CS1 */ |  | ||||||
| 		mtdcr(EBC0_CFGADDR, PB1CR); |  | ||||||
| 		flashcr = mfdcr (EBC0_CFGDATA); |  | ||||||
| 		/* we map the flash high in every case */ |  | ||||||
| 		flashcr&=0x0001FFFF; /* mask out address bits */ |  | ||||||
| 		flashcr|= ((0-flash_info[0].size) & 0xFFF00000); /* start addr */ |  | ||||||
| 		flashcr|= (i << 17); /* size addr */ |  | ||||||
| 		mtdcr(EBC0_CFGADDR, PB1CR); |  | ||||||
| 		mtdcr(EBC0_CFGDATA, flashcr); |  | ||||||
| 	} |  | ||||||
| 	else { |  | ||||||
| 		/* flash is on CS0 */ |  | ||||||
| 		mtdcr(EBC0_CFGADDR, PB0CR); |  | ||||||
| 		flashcr = mfdcr (EBC0_CFGDATA); |  | ||||||
| 		/* we map the flash high in every case */ |  | ||||||
| 		flashcr&=0x0001FFFF; /* mask out address bits */ |  | ||||||
| 		flashcr|= ((0-flash_info[0].size) & 0xFFF00000); /* start addr */ |  | ||||||
| 		flashcr|= (i << 17); /* size addr */ |  | ||||||
| 		mtdcr(EBC0_CFGADDR, PB0CR); |  | ||||||
| 		mtdcr(EBC0_CFGDATA, flashcr); |  | ||||||
| 	} |  | ||||||
| #if 0 |  | ||||||
| 	/* enable this (PIP405/MIP405 only) if you want to test if |  | ||||||
| 	   the relocation has be done ok. |  | ||||||
| 	   This will disable both Chipselects */ |  | ||||||
| 	mtdcr (EBC0_CFGADDR, PB0CR); |  | ||||||
| 	mtdcr (EBC0_CFGDATA, 0L); |  | ||||||
| 	mtdcr (EBC0_CFGADDR, PB1CR); |  | ||||||
| 	mtdcr (EBC0_CFGDATA, 0L); |  | ||||||
| 	printf("CS0 & CS1 switched off for test\n"); |  | ||||||
| #endif |  | ||||||
| 	/* patch version_string */ |  | ||||||
| 	for(i=0;i<0x100;i++) { |  | ||||||
| 		if(*p=='\n') { |  | ||||||
| 			*p=0; |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		p++; |  | ||||||
| 	} |  | ||||||
| #else /* #if !defined(CONFIG_PATI) */ |  | ||||||
| #ifdef	CONFIG_ENV_IS_IN_FLASH |  | ||||||
| 	/* ENV protection ON by default */ |  | ||||||
| 	flash_protect(FLAG_PROTECT_SET, |  | ||||||
| 		      CONFIG_ENV_ADDR, |  | ||||||
| 		      CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1, |  | ||||||
| 		      &flash_info[0]); |  | ||||||
| #endif |  | ||||||
| #endif /* #if !defined(CONFIG_PATI) */ |  | ||||||
| 	return (size_b0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------- |  | ||||||
|  */ |  | ||||||
| void flash_print_info  (flash_info_t *info) |  | ||||||
| { |  | ||||||
| 	int i; |  | ||||||
| 	int k; |  | ||||||
| 	int size; |  | ||||||
| 	int erased; |  | ||||||
| 	volatile unsigned long *flash; |  | ||||||
|  |  | ||||||
| 	if (info->flash_id == FLASH_UNKNOWN) { |  | ||||||
| 		printf ("missing or unknown FLASH type\n"); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	switch (info->flash_id & FLASH_VENDMASK) { |  | ||||||
| 	case FLASH_MAN_AMD:	printf ("AMD ");		break; |  | ||||||
| 	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break; |  | ||||||
| 	case FLASH_MAN_SST:	printf ("SST ");		break; |  | ||||||
| 	case FLASH_MAN_INTEL:	printf ("Intel ");		break; |  | ||||||
| 	default:		printf ("Unknown Vendor ");	break; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	switch (info->flash_id & FLASH_TYPEMASK) { |  | ||||||
| 	case FLASH_AM040:	printf ("AM29F040 (512 Kbit, uniform sector size)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_SST800A:	printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_SST160A:	printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_INTEL320T:	printf ("TE28F320C3 (32 Mbit, top sector size)\n"); |  | ||||||
| 				break; |  | ||||||
| 	case FLASH_AM640U:	printf ("AM29LV640U (64 Mbit, uniform sector size)\n"); |  | ||||||
| 				break; |  | ||||||
| 	default:		printf ("Unknown Chip Type\n"); |  | ||||||
| 				break; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	printf ("  Size: %ld KB in %d Sectors\n", |  | ||||||
| 		info->size >> 10, info->sector_count); |  | ||||||
|  |  | ||||||
| 	printf ("  Sector Start Addresses:"); |  | ||||||
| 	for (i=0; i<info->sector_count; ++i) { |  | ||||||
| 		/* |  | ||||||
| 		 * 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   "); |  | ||||||
| 		printf (" %08lX%s%s", |  | ||||||
| 			info->start[i], |  | ||||||
| 			erased ? " E" : "  ", |  | ||||||
| 			info->protect[i] ? "RO " : "   "); |  | ||||||
| 	} |  | ||||||
| 	printf ("\n"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------- |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------- |  | ||||||
|  |  | ||||||
| */ |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * The following code cannot be run from FLASH! |  | ||||||
|  */ |  | ||||||
| static ulong flash_get_size (vu_long *addr, flash_info_t *info) |  | ||||||
| { |  | ||||||
| 	short i; |  | ||||||
| 	FLASH_WORD_SIZE value; |  | ||||||
| 	ulong base; |  | ||||||
| 	volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; |  | ||||||
|  |  | ||||||
| 	/* Write auto select command: read Manufacturer ID */ |  | ||||||
| 	addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; |  | ||||||
| 	addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; |  | ||||||
| 	addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090; |  | ||||||
|  |  | ||||||
| 	value = addr2[0]; |  | ||||||
| 	/*	printf("flash_get_size value: %x\n",value); */ |  | ||||||
| 	switch (value) { |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_MANUFACT: |  | ||||||
| 		info->flash_id = FLASH_MAN_AMD; |  | ||||||
| 		break; |  | ||||||
| 	case (FLASH_WORD_SIZE)FUJ_MANUFACT: |  | ||||||
| 		info->flash_id = FLASH_MAN_FUJ; |  | ||||||
| 		break; |  | ||||||
| 	case (FLASH_WORD_SIZE)INTEL_MANUFACT: |  | ||||||
| 		info->flash_id = FLASH_MAN_INTEL; |  | ||||||
| 		break; |  | ||||||
| 	case (FLASH_WORD_SIZE)SST_MANUFACT: |  | ||||||
| 		info->flash_id = FLASH_MAN_SST; |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		info->flash_id = FLASH_UNKNOWN; |  | ||||||
| 		info->sector_count = 0; |  | ||||||
| 		info->size = 0; |  | ||||||
| 		return (0);			/* no or unknown flash	*/ |  | ||||||
| 	} |  | ||||||
| 	value = addr2[1];			/* device ID		*/ |  | ||||||
| 	/*	printf("Device value %x\n",value);		    */ |  | ||||||
| 	switch (value) { |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_ID_F040B: |  | ||||||
| 		info->flash_id += FLASH_AM040; |  | ||||||
| 		info->sector_count = 8; |  | ||||||
| 		info->size = 0x0080000; /* => 512 ko */ |  | ||||||
| 		break; |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_ID_LV400T: |  | ||||||
| 		info->flash_id += FLASH_AM400T; |  | ||||||
| 		info->sector_count = 11; |  | ||||||
| 		info->size = 0x00080000; |  | ||||||
| 		break;				/* => 0.5 MB		*/ |  | ||||||
|  |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_ID_LV400B: |  | ||||||
| 		info->flash_id += FLASH_AM400B; |  | ||||||
| 		info->sector_count = 11; |  | ||||||
| 		info->size = 0x00080000; |  | ||||||
| 		break;				/* => 0.5 MB		*/ |  | ||||||
|  |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_ID_LV800T: |  | ||||||
| 		info->flash_id += FLASH_AM800T; |  | ||||||
| 		info->sector_count = 19; |  | ||||||
| 		info->size = 0x00100000; |  | ||||||
| 		break;				/* => 1 MB		*/ |  | ||||||
|  |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_ID_LV800B: |  | ||||||
| 		info->flash_id += FLASH_AM800B; |  | ||||||
| 		info->sector_count = 19; |  | ||||||
| 		info->size = 0x00100000; |  | ||||||
| 		break;				/* => 1 MB		*/ |  | ||||||
|  |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_ID_LV160T: |  | ||||||
| 		info->flash_id += FLASH_AM160T; |  | ||||||
| 		info->sector_count = 35; |  | ||||||
| 		info->size = 0x00200000; |  | ||||||
| 		break;				/* => 2 MB		*/ |  | ||||||
|  |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_ID_LV160B: |  | ||||||
| 		info->flash_id += FLASH_AM160B; |  | ||||||
| 		info->sector_count = 35; |  | ||||||
| 		info->size = 0x00200000; |  | ||||||
| 		break;				/* => 2 MB		*/ |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_ID_LV320T: |  | ||||||
| 		info->flash_id += FLASH_AM320T; |  | ||||||
| 		info->sector_count = 67; |  | ||||||
| 		info->size = 0x00400000; |  | ||||||
| 		break;				/* => 4 MB		*/ |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_ID_LV640U: |  | ||||||
| 		info->flash_id += FLASH_AM640U; |  | ||||||
| 		info->sector_count = 128; |  | ||||||
| 		info->size = 0x00800000; |  | ||||||
| 		break;				/* => 8 MB		*/ |  | ||||||
| #if 0	/* enable when device IDs are available */ |  | ||||||
|  |  | ||||||
| 	case (FLASH_WORD_SIZE)AMD_ID_LV320B: |  | ||||||
| 		info->flash_id += FLASH_AM320B; |  | ||||||
| 		info->sector_count = 67; |  | ||||||
| 		info->size = 0x00400000; |  | ||||||
| 		break;				/* => 4 MB		*/ |  | ||||||
| #endif |  | ||||||
| 	case (FLASH_WORD_SIZE)SST_ID_xF800A: |  | ||||||
| 		info->flash_id += FLASH_SST800A; |  | ||||||
| 		info->sector_count = 16; |  | ||||||
| 		info->size = 0x00100000; |  | ||||||
| 		break;				/* => 1 MB		*/ |  | ||||||
| 	case (FLASH_WORD_SIZE)INTEL_ID_28F320C3T: |  | ||||||
| 		info->flash_id += FLASH_INTEL320T; |  | ||||||
| 		info->sector_count = 71; |  | ||||||
| 		info->size = 0x00400000; |  | ||||||
| 		break;				/* => 4 MB		*/ |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	case (FLASH_WORD_SIZE)SST_ID_xF160A: |  | ||||||
| 		info->flash_id += FLASH_SST160A; |  | ||||||
| 		info->sector_count = 32; |  | ||||||
| 		info->size = 0x00200000; |  | ||||||
| 		break;				/* => 2 MB		*/ |  | ||||||
|  |  | ||||||
| 	default: |  | ||||||
| 		info->flash_id = FLASH_UNKNOWN; |  | ||||||
| 		return (0);			/* => no or unknown flash */ |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
| 	/* base address calculation */ |  | ||||||
| 	base=0-info->size; |  | ||||||
| 	/* set up sector start address table */ |  | ||||||
| 	if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || |  | ||||||
| 	     (info->flash_id  == FLASH_AM040) || |  | ||||||
| 	     (info->flash_id  == FLASH_AM640U)){ |  | ||||||
| 		for (i = 0; i < info->sector_count; i++) |  | ||||||
| 			info->start[i] = base + (i * 0x00010000); |  | ||||||
| 	} |  | ||||||
| 	else { |  | ||||||
| 		if (info->flash_id & FLASH_BTYPE) { |  | ||||||
| 			/* set sector offsets for bottom boot block type	*/ |  | ||||||
| 			info->start[0] = base + 0x00000000; |  | ||||||
| 			info->start[1] = base + 0x00004000; |  | ||||||
| 			info->start[2] = base + 0x00006000; |  | ||||||
| 			info->start[3] = base + 0x00008000; |  | ||||||
| 			for (i = 4; i < info->sector_count; i++) |  | ||||||
| 				info->start[i] = base + (i * 0x00010000) - 0x00030000; |  | ||||||
| 		} |  | ||||||
| 		else { |  | ||||||
| 			/* set sector offsets for top boot block type		*/ |  | ||||||
| 			i = info->sector_count - 1; |  | ||||||
| 			if(info->sector_count==71) { |  | ||||||
|  |  | ||||||
| 				info->start[i--] = base + info->size - 0x00002000; |  | ||||||
| 				info->start[i--] = base + info->size - 0x00004000; |  | ||||||
| 				info->start[i--] = base + info->size - 0x00006000; |  | ||||||
| 				info->start[i--] = base + info->size - 0x00008000; |  | ||||||
| 				info->start[i--] = base + info->size - 0x0000A000; |  | ||||||
| 				info->start[i--] = base + info->size - 0x0000C000; |  | ||||||
| 				info->start[i--] = base + info->size - 0x0000E000; |  | ||||||
| 				for (; i >= 0; i--) |  | ||||||
| 					info->start[i] = base + i * 0x000010000; |  | ||||||
| 			} |  | ||||||
| 			else { |  | ||||||
| 				info->start[i--] = base + info->size - 0x00004000; |  | ||||||
| 				info->start[i--] = base + info->size - 0x00006000; |  | ||||||
| 				info->start[i--] = base + info->size - 0x00008000; |  | ||||||
| 				for (; i >= 0; i--) |  | ||||||
| 					info->start[i] = base + i * 0x00010000; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* check for protected sectors */ |  | ||||||
| 	for (i = 0; i < info->sector_count; i++) { |  | ||||||
| 		/* read sector protection at sector address, (A7 .. A0) = 0x02 */ |  | ||||||
| 		/* D0 = 1 if protected */ |  | ||||||
| 		addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); |  | ||||||
| 		if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) |  | ||||||
| 			info->protect[i] = 0; |  | ||||||
| 		else |  | ||||||
| 			info->protect[i] = addr2[2] & 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * Prevent writes to uninitialized FLASH. |  | ||||||
| 	 */ |  | ||||||
| 	if (info->flash_id != FLASH_UNKNOWN) { |  | ||||||
| 		addr2 = (FLASH_WORD_SIZE *)info->start[0]; |  | ||||||
| 		*addr2 = (FLASH_WORD_SIZE)0x00F000F0;	/* reset bank */ |  | ||||||
| 	} |  | ||||||
| 	return (info->size); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| int wait_for_DQ7(flash_info_t *info, int sect) |  | ||||||
| { |  | ||||||
| 	ulong start, now, last; |  | ||||||
| 	volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]); |  | ||||||
|  |  | ||||||
| 	start = get_timer (0); |  | ||||||
| 	last  = start; |  | ||||||
| 	while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) { |  | ||||||
| 		if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) { |  | ||||||
| 			printf ("Timeout\n"); |  | ||||||
| 			return ERR_TIMOUT; |  | ||||||
| 		} |  | ||||||
| 		/* show that we're waiting */ |  | ||||||
| 		if ((now - last) > 1000) {  /* every second */ |  | ||||||
| 			putc ('.'); |  | ||||||
| 			last = now; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return ERR_OK; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int intel_wait_for_DQ7(flash_info_t *info, int sect) |  | ||||||
| { |  | ||||||
| 	ulong start, now, last, status; |  | ||||||
| 	volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]); |  | ||||||
|  |  | ||||||
| 	start = get_timer (0); |  | ||||||
| 	last  = start; |  | ||||||
| 	while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) { |  | ||||||
| 		if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) { |  | ||||||
| 			printf ("Timeout\n"); |  | ||||||
| 			return ERR_TIMOUT; |  | ||||||
| 		} |  | ||||||
| 		/* show that we're waiting */ |  | ||||||
| 		if ((now - last) > 1000) {  /* every second */ |  | ||||||
| 			putc ('.'); |  | ||||||
| 			last = now; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	status = addr[0] & (FLASH_WORD_SIZE)0x00280028; |  | ||||||
| 	/* clear status register */ |  | ||||||
| 	addr[0] = (FLASH_WORD_SIZE)0x00500050; |  | ||||||
| 	/* check status for block erase fail and VPP low */ |  | ||||||
| 	return (status == 0 ? ERR_OK : ERR_NOT_ERASED); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------- |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| int	flash_erase (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 flag, prot, sect; |  | ||||||
| 	int i, rcode = 0; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	if ((s_first < 0) || (s_first > s_last)) { |  | ||||||
| 		if (info->flash_id == FLASH_UNKNOWN) { |  | ||||||
| 			printf ("- missing\n"); |  | ||||||
| 		} else { |  | ||||||
| 			printf ("- no sectors to erase\n"); |  | ||||||
| 		} |  | ||||||
| 		return 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (info->flash_id == FLASH_UNKNOWN) { |  | ||||||
| 		printf ("Can't erase unknown flash type - aborted\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"); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* Disable interrupts which might cause a timeout here */ |  | ||||||
| 	flag = disable_interrupts(); |  | ||||||
|  |  | ||||||
| 	/* 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("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 */ |  | ||||||
| 				rcode |= wait_for_DQ7(info, sect); |  | ||||||
| 			} |  | ||||||
| 			else { |  | ||||||
| 				if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){ |  | ||||||
| 					addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector */ |  | ||||||
| 					addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */ |  | ||||||
| 					intel_wait_for_DQ7(info, sect); |  | ||||||
| 					addr2[0] = (FLASH_WORD_SIZE)0x00200020;  /* sector erase */ |  | ||||||
| 					addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */ |  | ||||||
| 					rcode |= intel_wait_for_DQ7(info, sect); |  | ||||||
| 				} |  | ||||||
| 				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 */ |  | ||||||
| 					rcode |= wait_for_DQ7(info, sect); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			/* |  | ||||||
| 			 * Wait for each sector to complete, it's more |  | ||||||
| 			 * reliable.  According to AMD Spec, you must |  | ||||||
| 			 * issue all erase commands within a specified |  | ||||||
| 			 * timeout.  This has been seen to fail, especially |  | ||||||
| 			 * if printf()s are included (for debug)!! |  | ||||||
| 			 */ |  | ||||||
| 			/*   wait_for_DQ7(info, sect); */ |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* re-enable interrupts if necessary */ |  | ||||||
| 	if (flag) |  | ||||||
| 		enable_interrupts(); |  | ||||||
|  |  | ||||||
| 	/* wait at least 80us - let's wait 1 ms */ |  | ||||||
| 	udelay (1000); |  | ||||||
|  |  | ||||||
| 	/* reset to read mode */ |  | ||||||
| 	addr = (FLASH_WORD_SIZE *)info->start[0]; |  | ||||||
| 	addr[0] = (FLASH_WORD_SIZE)0x00F000F0;	/* reset bank */ |  | ||||||
|  |  | ||||||
| 	if (!rcode) |  | ||||||
| 	    printf (" done\n"); |  | ||||||
|  |  | ||||||
| 	return rcode; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt) |  | ||||||
| { |  | ||||||
| 	int i; |  | ||||||
| 	volatile FLASH_WORD_SIZE *addr2; |  | ||||||
| 	long c; |  | ||||||
| 	c= (long)cnt; |  | ||||||
| 	for(i=info->sector_count-1;i>0;i--) |  | ||||||
| 	{ |  | ||||||
| 		if(addr>=info->start[i]) |  | ||||||
| 			break; |  | ||||||
| 	} |  | ||||||
| 	do { |  | ||||||
| 		addr2 = (FLASH_WORD_SIZE *)(info->start[i]); |  | ||||||
| 		addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector setup */ |  | ||||||
| 		addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* unlock sector */ |  | ||||||
| 		intel_wait_for_DQ7(info, i); |  | ||||||
| 		i++; |  | ||||||
| 		c-=(info->start[i]-info->start[i-1]); |  | ||||||
| 	}while(c>0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------- |  | ||||||
|  * 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 cp, wp, data; |  | ||||||
| 	int i, l, rc; |  | ||||||
|  |  | ||||||
| 	if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){ |  | ||||||
| 		unlock_intel_sectors(info,addr,cnt); |  | ||||||
| 	} |  | ||||||
| 	wp = (addr & ~3);	/* get lower word aligned address */ |  | ||||||
| 	/* |  | ||||||
| 	 * handle unaligned start bytes |  | ||||||
| 	 */ |  | ||||||
| 	if ((l = addr - wp) != 0) { |  | ||||||
| 		data = 0; |  | ||||||
| 		for (i=0, cp=wp; i<l; ++i, ++cp) { |  | ||||||
| 			data = (data << 8) | (*(uchar *)cp); |  | ||||||
| 		} |  | ||||||
| 		for (; i<4 && cnt>0; ++i) { |  | ||||||
| 			data = (data << 8) | *src++; |  | ||||||
| 			--cnt; |  | ||||||
| 			++cp; |  | ||||||
| 		} |  | ||||||
| 		for (; cnt==0 && i<4; ++i, ++cp) { |  | ||||||
| 			data = (data << 8) | (*(uchar *)cp); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if ((rc = 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 = (data << 8) | *src++; |  | ||||||
| 		} |  | ||||||
| 		if ((rc = write_word(info, wp, data)) != 0) { |  | ||||||
| 			return (rc); |  | ||||||
| 		} |  | ||||||
| 		wp  += 4; |  | ||||||
| 		if((wp % 0x10000)==0) |  | ||||||
| 			printf("."); /* show Progress */ |  | ||||||
| 		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 = (data << 8) | *src++; |  | ||||||
| 		--cnt; |  | ||||||
| 	} |  | ||||||
| 	for (; i<4; ++i, ++cp) { |  | ||||||
| 		data = (data << 8) | (*(uchar *)cp); |  | ||||||
| 	} |  | ||||||
| 	rc=write_word(info, wp, data); |  | ||||||
| 	return rc; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------- |  | ||||||
|  * Write a word to Flash, returns: |  | ||||||
|  * 0 - OK |  | ||||||
|  * 1 - write timeout |  | ||||||
|  * 2 - Flash not erased |  | ||||||
|  */ |  | ||||||
| static FLASH_WORD_SIZE *read_val = (FLASH_WORD_SIZE *)0x200000; |  | ||||||
|  |  | ||||||
| static int write_word (flash_info_t *info, ulong dest, ulong data) |  | ||||||
| { |  | ||||||
| 	volatile FLASH_WORD_SIZE *addr2 = (volatile FLASH_WORD_SIZE *)(info->start[0]); |  | ||||||
| 	volatile FLASH_WORD_SIZE *dest2 = (volatile FLASH_WORD_SIZE *)dest; |  | ||||||
| 	volatile FLASH_WORD_SIZE *data2; |  | ||||||
| 	ulong start; |  | ||||||
| 	ulong *data_p; |  | ||||||
| 	int flag; |  | ||||||
| 	int i; |  | ||||||
|  |  | ||||||
| 	data_p = &data; |  | ||||||
| 	data2 = (volatile FLASH_WORD_SIZE *)data_p; |  | ||||||
|  |  | ||||||
| 	/* Check if Flash is (sufficiently) erased */ |  | ||||||
| 	if ((*((volatile FLASH_WORD_SIZE *)dest) & |  | ||||||
| 		(FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) { |  | ||||||
| 		return (2); |  | ||||||
| 	} |  | ||||||
| 	/* Disable interrupts which might cause a timeout here */ |  | ||||||
| 	flag = disable_interrupts(); |  | ||||||
| 	for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++) |  | ||||||
| 	{ |  | ||||||
| 		if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){ |  | ||||||
| 			/* intel style writting */ |  | ||||||
| 			dest2[i] = (FLASH_WORD_SIZE)0x00500050; |  | ||||||
| 			dest2[i] = (FLASH_WORD_SIZE)0x00400040; |  | ||||||
| 			*read_val++ = data2[i]; |  | ||||||
| 			dest2[i] = data2[i]; |  | ||||||
| 			if (flag) |  | ||||||
| 				enable_interrupts(); |  | ||||||
| 			/* data polling for D7 */ |  | ||||||
| 			start = get_timer (0); |  | ||||||
| 			udelay(10); |  | ||||||
| 			while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) |  | ||||||
| 			{ |  | ||||||
| 				if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) |  | ||||||
| 					return (1); |  | ||||||
| 			} |  | ||||||
| 			dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */ |  | ||||||
| 			udelay(10); |  | ||||||
| 			dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */ |  | ||||||
| 			if(dest2[i]!=data2[i]) |  | ||||||
| 				printf("Error at %p 0x%04X != 0x%04X\n",&dest2[i],dest2[i],data2[i]); |  | ||||||
| 		} |  | ||||||
| 		else { |  | ||||||
| 			addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; |  | ||||||
| 			addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; |  | ||||||
| 			addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0; |  | ||||||
| 			dest2[i] = data2[i]; |  | ||||||
| 			/* re-enable interrupts if necessary */ |  | ||||||
| 			if (flag) |  | ||||||
| 				enable_interrupts(); |  | ||||||
| 			/* data polling for D7 */ |  | ||||||
| 			start = get_timer (0); |  | ||||||
| 			while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != |  | ||||||
| 				(data2[i] & (FLASH_WORD_SIZE)0x00800080)) { |  | ||||||
| 				if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) { |  | ||||||
| 					return (1); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return (0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------- |  | ||||||
|  */ |  | ||||||
		Reference in New Issue
	
	Block a user