summaryrefslogtreecommitdiff
path: root/board/mpl
diff options
context:
space:
mode:
Diffstat (limited to 'board/mpl')
-rw-r--r--board/mpl/common/common_util.c202
-rw-r--r--board/mpl/common/common_util.h4
-rw-r--r--board/mpl/common/flash.c872
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);
-}
-
-/*-----------------------------------------------------------------------
- */