diff options
author | wdenk <wdenk> | 2004-06-09 21:54:22 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2004-06-09 21:54:22 +0000 |
commit | 99edcfb29ef8c4865bd26dddf938af0bf5959482 (patch) | |
tree | cbe509d69cb6096313ff6c1177139217e73a85a5 /board/fads/flash.c | |
parent | 2d24a3a787c2376c2c2c86a511eee78ef170923f (diff) | |
download | u-boot-imx-99edcfb29ef8c4865bd26dddf938af0bf5959482.zip u-boot-imx-99edcfb29ef8c4865bd26dddf938af0bf5959482.tar.gz u-boot-imx-99edcfb29ef8c4865bd26dddf938af0bf5959482.tar.bz2 |
Patch by Yuli Barcohen, 09 Jun 2004:
Add support for 8MB flash SIMM and JFFS2 file system on
Motorola FADS board and its derivatives (MPC86xADS, MPC885ADS).
Diffstat (limited to 'board/fads/flash.c')
-rw-r--r-- | board/fads/flash.c | 241 |
1 files changed, 78 insertions, 163 deletions
diff --git a/board/fads/flash.c b/board/fads/flash.c index d2a46b2..f0fb621 100644 --- a/board/fads/flash.c +++ b/board/fads/flash.c @@ -24,7 +24,7 @@ #include <common.h> #include <mpc8xx.h> -flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ #if defined(CFG_ENV_IS_IN_FLASH) # ifndef CFG_ENV_ADDR @@ -38,124 +38,103 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ # endif #endif +#define QUAD_ID(id) ((((ulong)(id) & 0xFF) << 24) | \ + (((ulong)(id) & 0xFF) << 16) | \ + (((ulong)(id) & 0xFF) << 8) | \ + (((ulong)(id) & 0xFF) << 0) \ + ) + /*----------------------------------------------------------------------- * Functions */ static ulong flash_get_size (vu_long * addr, flash_info_t * info); static int write_word (flash_info_t * info, ulong dest, ulong data); -static void flash_get_offsets (ulong base, flash_info_t * info); /*----------------------------------------------------------------------- */ - unsigned long flash_init (void) { volatile immap_t *immap = (immap_t *) CFG_IMMR; volatile memctl8xx_t *memctl = &immap->im_memctl; - unsigned long total_size; - unsigned long size_b0, size_b1; + vu_long *bcsr = (vu_long *)BCSR_ADDR; + unsigned long pd_size, total_size, bsize, or_am; int i; /* Init: no FLASHes known */ for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { flash_info[i].flash_id = FLASH_UNKNOWN; + flash_info[i].size = 0; + flash_info[i].sector_count = 0; + flash_info[i].start[0] = 0xFFFFFFFF; /* For TFTP */ } - total_size = 0; - size_b0 = 0xffffffff; + switch ((bcsr[2] & BCSR2_FLASH_PD_MASK) >> BCSR2_FLASH_PD_SHIFT) { + case 2: + case 4: + case 6: + pd_size = 0x800000; + or_am = 0xFF800000; + break; - for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { - size_b1 = - flash_get_size ((vu_long *) (CFG_FLASH_BASE + - total_size), - &flash_info[i]); + case 5: + case 7: + pd_size = 0x400000; + or_am = 0xFFC00000; + break; - if (flash_info[i].flash_id == FLASH_UNKNOWN) { - printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", i, size_b1, size_b1 >> 20); - } + case 8: + pd_size = 0x200000; + or_am = 0xFFE00000; + break; - /* Is this really needed ? - LP */ - if (size_b1 > size_b0) { - printf ("## ERROR: Bank %d (0x%08lx = %ld MB) > Bank %d (0x%08lx = %ld MB)\n", i, size_b1, size_b1 >> 20, i - 1, size_b0, size_b0 >> 20); - goto out_error; - } - size_b0 = size_b1; - total_size += size_b1; + default: + pd_size = 0; + or_am = 0xFFE00000; + printf("## Unsupported flash detected by BCSR: 0x%08X\n", bcsr[2]); } - /* Compute the Address Mask */ - for (i = 0; (total_size >> i) != 0; ++i) { + total_size = 0; + for (i = 0; i < CFG_MAX_FLASH_BANKS && total_size < pd_size; ++i) { + bsize = flash_get_size((vu_long *)(CFG_FLASH_BASE + total_size), + &flash_info[i]); + + if (flash_info[i].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", + i, bsize, bsize >> 20); + } + + total_size += bsize; } - i--; - if (total_size != (1 << i)) { - printf ("## WARNING: Total FLASH size (0x%08lx = %ld MB) is not a power of 2\n", total_size, total_size >> 20); + if (total_size != pd_size) { + printf("## Detected flash size %lu conflicts with PD data %lu\n", + total_size, pd_size); } /* Remap FLASH according to real size */ - memctl->memc_or0 = - ((((unsigned long) ~0) << i) & OR_AM_MSK) | - CFG_OR_TIMING_FLASH; - memctl->memc_br0 = CFG_BR0_PRELIM; - - total_size = 0; + memctl->memc_or0 = or_am | CFG_OR_TIMING_FLASH; for (i = 0; i < CFG_MAX_FLASH_BANKS && flash_info[i].size != 0; ++i) { - /* Re-do sizing to get full correct info */ - /* Why ? - LP */ - size_b1 = - flash_get_size ((vu_long *) (CFG_FLASH_BASE + - total_size), - &flash_info[i]); - - /* This is done by flash_get_size - LP */ - /* flash_get_offsets (CFG_FLASH_BASE + total_size, &flash_info[i]); */ - #if CFG_MONITOR_BASE >= CFG_FLASH_BASE /* monitor protection ON by default */ - flash_protect (FLAG_PROTECT_SET, - CFG_MONITOR_BASE, - CFG_MONITOR_BASE + monitor_flash_len - 1, - &flash_info[i]); + if (CFG_MONITOR_BASE >= flash_info[i].start[0]) + flash_protect (FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + monitor_flash_len - 1, + &flash_info[i]); #endif #ifdef CFG_ENV_IS_IN_FLASH /* ENV protection ON by default */ - flash_protect (FLAG_PROTECT_SET, - CFG_ENV_ADDR, - CFG_ENV_ADDR + CFG_ENV_SIZE - 1, - &flash_info[i]); + if (CFG_ENV_ADDR >= flash_info[i].start[0]) + flash_protect (FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, + &flash_info[i]); #endif - - total_size += size_b1; } - return (total_size); - - out_error: - for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { - flash_info[i].flash_id = FLASH_UNKNOWN; - flash_info[i].sector_count = -1; - flash_info[i].size = 0; - } - - return (0); -} - -/*----------------------------------------------------------------------- - */ -static void flash_get_offsets (ulong base, flash_info_t * info) -{ - int i; - - /* set up sector start address table */ - if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040 - || (info->flash_id & FLASH_TYPEMASK) == FLASH_AM080) { - /* set sector offsets for uniform sector type */ - for (i = 0; i < info->sector_count; i++) { - info->start[i] = base + (i * 0x00040000); - } - } + return total_size; } /*----------------------------------------------------------------------- @@ -235,48 +214,26 @@ void flash_print_info (flash_info_t * info) } printf ("\n"); - return; } /*----------------------------------------------------------------------- + * The following code can not run from flash! */ - - -/*----------------------------------------------------------------------- - */ - -/* - * The following code cannot be run from FLASH! - */ - static ulong flash_get_size (vu_long * addr, flash_info_t * info) { short i; -#if 0 - ulong base = (ulong) addr; -#endif - uchar value; - /* Write auto select command: read Manufacturer ID */ -#if 0 - addr[0x0555] = 0x00AA00AA; - addr[0x02AA] = 0x00550055; - addr[0x0555] = 0x00900090; -#else addr[0x0555] = 0xAAAAAAAA; addr[0x02AA] = 0x55555555; addr[0x0555] = 0x90909090; -#endif - - value = addr[0]; - switch (value + (value << 16)) { - case AMD_MANUFACT: + switch (addr[0]) { + case QUAD_ID(AMD_MANUFACT): info->flash_id = FLASH_MAN_AMD; break; - case FUJ_MANUFACT: + case QUAD_ID(FUJ_MANUFACT): info->flash_id = FLASH_MAN_FUJ; break; @@ -287,21 +244,20 @@ static ulong flash_get_size (vu_long * addr, flash_info_t * info) break; } - value = addr[1]; /* device ID */ - - switch (value) { - case AMD_ID_F040B: + switch (addr[1]) { /* device ID */ + case QUAD_ID(AMD_ID_F040B): + case QUAD_ID(AMD_ID_LV040B): info->flash_id += FLASH_AM040; info->sector_count = 8; info->size = 0x00200000; break; /* => 2 MB */ - case AMD_ID_F080B: + case QUAD_ID(AMD_ID_F080B): info->flash_id += FLASH_AM080; info->sector_count = 16; info->size = 0x00400000; break; /* => 4 MB */ - +#if 0 case AMD_ID_LV400T: info->flash_id += FLASH_AM400T; info->sector_count = 11; @@ -337,7 +293,7 @@ static ulong flash_get_size (vu_long * addr, flash_info_t * info) info->sector_count = 35; info->size = 0x00400000; break; /* => 4 MB */ -#if 0 /* enable when device IDs are available */ + case AMD_ID_LV320T: info->flash_id += FLASH_AM320T; info->sector_count = 67; @@ -349,11 +305,10 @@ static ulong flash_get_size (vu_long * addr, flash_info_t * info) info->sector_count = 67; info->size = 0x00800000; break; /* => 8 MB */ -#endif +#endif /* 0 */ default: info->flash_id = FLASH_UNKNOWN; return (0); /* => no or unknown flash */ - } #if 0 @@ -378,7 +333,9 @@ static ulong flash_get_size (vu_long * addr, flash_info_t * info) } } #else - flash_get_offsets ((ulong) addr, info); + /* set sector offsets for uniform sector type */ + for (i = 0; i < info->sector_count; i++) + info->start[i] = (ulong)addr + (i * 0x00040000); #endif /* check for protected sectors */ @@ -389,25 +346,16 @@ static ulong flash_get_size (vu_long * addr, flash_info_t * info) info->protect[i] = addr[2] & 1; } - /* - * Prevent writes to uninitialized FLASH. - */ if (info->flash_id != FLASH_UNKNOWN) { addr = (volatile unsigned long *) info->start[0]; -#if 0 - *addr = 0x00F000F0; /* reset bank */ -#else *addr = 0xF0F0F0F0; /* reset bank */ -#endif } return (info->size); } - /*----------------------------------------------------------------------- */ - int flash_erase (flash_info_t * info, int s_first, int s_last) { vu_long *addr = (vu_long *) (info->start[0]); @@ -420,13 +368,13 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) } else { printf ("- no sectors to erase\n"); } - return 1; + return ERR_INVAL; } if ((info->flash_id == FLASH_UNKNOWN) || (info->flash_id > FLASH_AMD_COMP)) { printf ("Can't erase unknown flash type - aborted\n"); - return 1; + return ERR_UNKNOWN_FLASH_TYPE; } prot = 0; @@ -447,29 +395,17 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts (); -#if 0 - addr[0x0555] = 0x00AA00AA; - addr[0x02AA] = 0x00550055; - addr[0x0555] = 0x00800080; - addr[0x0555] = 0x00AA00AA; - addr[0x02AA] = 0x00550055; -#else addr[0x0555] = 0xAAAAAAAA; addr[0x02AA] = 0x55555555; addr[0x0555] = 0x80808080; addr[0x0555] = 0xAAAAAAAA; addr[0x02AA] = 0x55555555; -#endif /* Start erase on unprotected sectors */ for (sect = s_first; sect <= s_last; sect++) { if (info->protect[sect] == 0) { /* not protected */ addr = (vu_long *) (info->start[sect]); -#if 0 - addr[0] = 0x00300030; -#else addr[0] = 0x30303030; -#endif l_sect = sect; } } @@ -490,15 +426,11 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) start = get_timer (0); last = start; addr = (vu_long *) (info->start[l_sect]); -#if 0 - while ((addr[0] & 0x00800080) != 0x00800080) -#else while ((addr[0] & 0xFFFFFFFF) != 0xFFFFFFFF) -#endif { if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) { printf ("Timeout\n"); - return 1; + return ERR_TIMOUT; } /* show that we're waiting */ if ((now - last) > 1000) { /* every second */ @@ -510,13 +442,10 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) DONE: /* reset to read mode */ addr = (volatile unsigned long *) info->start[0]; -#if 0 - addr[0] = 0x00F000F0; /* reset bank */ -#else addr[0] = 0xF0F0F0F0; /* reset bank */ -#endif printf (" done\n"); + return 0; } @@ -526,7 +455,6 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) * 1 - write timeout * 2 - Flash not erased */ - int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) { ulong cp, wp, data; @@ -605,20 +533,14 @@ static int write_word (flash_info_t * info, ulong dest, ulong data) /* Check if Flash is (sufficiently) erased */ if ((*((vu_long *) dest) & data) != data) { - return (2); + return ERR_NOT_ERASED; } /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts (); -#if 0 - addr[0x0555] = 0x00AA00AA; - addr[0x02AA] = 0x00550055; - addr[0x0555] = 0x00A000A0; -#else addr[0x0555] = 0xAAAAAAAA; addr[0x02AA] = 0x55555555; addr[0x0555] = 0xA0A0A0A0; -#endif *((vu_long *) dest) = data; @@ -628,18 +550,11 @@ static int write_word (flash_info_t * info, ulong dest, ulong data) /* data polling for D7 */ start = get_timer (0); -#if 0 - while ((*((vu_long *) dest) & 0x00800080) != (data & 0x00800080)) -#else while ((*((vu_long *) dest) & 0x80808080) != (data & 0x80808080)) -#endif { if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { - return (1); + return ERR_TIMOUT; } } return (0); } - -/*----------------------------------------------------------------------- - */ |