diff options
-rw-r--r-- | board/mpl/common/common_util.c | 202 | ||||
-rw-r--r-- | board/mpl/common/common_util.h | 4 | ||||
-rw-r--r-- | board/mpl/common/flash.c | 872 |
3 files changed, 182 insertions, 896 deletions
diff --git a/board/mpl/common/common_util.c b/board/mpl/common/common_util.c index d3300ed..a61a98c 100644 --- a/board/mpl/common/common_util.c +++ b/board/mpl/common/common_util.c @@ -53,13 +53,156 @@ extern int mem_test(ulong start, ulong ramsize, int quiet); #define I2C_BACKUP_ADDR 0x7C00 /* 0x200 bytes for backup */ #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 mpl_prg(uchar *src, ulong size) { ulong start; - flash_info_t *info; + flash_info_t *info = &flash_info[0]; int i, rc; #if defined(CONFIG_PATI) int start_sect; @@ -69,8 +212,6 @@ mpl_prg(uchar *src, ulong size) ulong *magic = (ulong *)src; #endif - info = &flash_info[0]; - #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) || defined(CONFIG_PATI) if (uimage_to_cpu (magic[0]) != IH_MAGIC) { puts("Bad Magic number\n"); @@ -96,12 +237,18 @@ mpl_prg(uchar *src, ulong size) } #if !defined(CONFIG_PATI) 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]) break; - } - /* set-up flash location */ + /* now erase flash */ printf("Erasing at %lx (sector %d) (start %lx)\n", start,i,info->start[i]); @@ -114,22 +261,24 @@ mpl_prg(uchar *src, ulong size) #else /* #if !defined(CONFIG_PATI */ start = FIRM_START; start_sect = -1; - for (i = 0; i < info->sector_count; i++) { - if (start < info->start[i]) { - start_sect = i - 1; + + /* search start sector */ + for (i = info->sector_count-1; i > 0; i--) + if (start >= info->start[i]) break; - } - } - info->protect[i - 1] = 0; /* unprotect this sector */ - for (; i < info->sector_count; i++) { - if ((start + size) < info->start[i]) + start_sect = i; + + for (i = info->sector_count-1; i > 0; i--) + if ((start + size) >= info->start[i]) break; - info->protect[i] = 0; /* unprotect this sector */ - } - i--; - /* set-up flash location */ + /* unprotect sectors used by u-boot */ + flash_protect(FLAG_PROTECT_CLEAR, + start, + start + size, + info); + /* now erase flash */ printf ("Erasing at %lx to %lx (sector %d to %d) (%lx to %lx)\n", start, start + size, start_sect, i, @@ -143,12 +292,17 @@ mpl_prg(uchar *src, ulong size) #elif defined(CONFIG_VCMA9) 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]) break; - } - /* set-up flash location */ + + flash_protect(FLAG_PROTECT_CLEAR, + start, + size, + info); + /* now erase flash */ printf("Erasing at %lx (sector %d) (start %lx)\n", start,0,info->start[0]); diff --git a/board/mpl/common/common_util.h b/board/mpl/common/common_util.h index 29cd14f..a0ea239 100644 --- a/board/mpl/common/common_util.h +++ b/board/mpl/common/common_util.h @@ -30,11 +30,15 @@ typedef struct { char eth_addr[21]; /* "00:60:C2:0a:00:00" */ } backup_t; +extern flash_info_t flash_info[]; /* info for FLASH chips */ + void get_backup_values(backup_t *buf); #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) #define BOOT_MPS 0x01 #define BOOT_PCI 0x02 +int get_boot_mode(void); +void setup_cs_reloc(void); #endif void check_env(void); diff --git a/board/mpl/common/flash.c b/board/mpl/common/flash.c deleted file mode 100644 index d5b63c0..0000000 --- a/board/mpl/common/flash.c +++ /dev/null @@ -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); -} - -/*----------------------------------------------------------------------- - */ |