X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=board%2Ftrab%2Fflash.c;h=3e8f105a0316632fc435c3f955e7e427cf4d5479;hb=6bf6f114dcdd97ec3f80c2761ed40e31229d6b78;hp=2443777ae18fb0529cf91588324915c9bd25cfb8;hpb=f682e42599fb951a178b81528586f01662dc9de9;p=oweals%2Fu-boot.git diff --git a/board/trab/flash.c b/board/trab/flash.c index 2443777ae1..3e8f105a03 100644 --- a/board/trab/flash.c +++ b/board/trab/flash.c @@ -26,12 +26,7 @@ #include #include -ulong myflush (void); - - -#define FLASH_BANK_SIZE 0x800000 /* 8 MB */ -/* this varies depending on the sector */ -#define MAIN_SECT_SIZE 0x20000 /* 2 x 64 kB */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; @@ -43,7 +38,11 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; #define CMD_ERASE_CONFIRM 0x00300030 #define CMD_PROGRAM 0x00A000A0 #define CMD_UNLOCK_BYPASS 0x00200020 +#define CMD_READ_MANF_ID 0x00900090 +#define CMD_UNLOCK_BYPASS_RES1 0x00900090 +#define CMD_UNLOCK_BYPASS_RES2 0x00000000 +#define MEM_FLASH_ADDR (*(volatile u32 *)CFG_FLASH_BASE) #define MEM_FLASH_ADDR1 (*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2))) #define MEM_FLASH_ADDR2 (*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2))) @@ -64,27 +63,39 @@ ulong flash_init (void) int i, j; ulong size = 0; - for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { + for (i=0; iflash_id = FLASH_UNKNOWN; + + size += flash_get_size (CFG_FLASH_BASE, info); - flash_info[i].flash_id = - (AMD_MANUFACT & FLASH_VENDMASK) | - (AMD_ID_LV320B & FLASH_TYPEMASK); - flash_info[i].size = FLASH_BANK_SIZE; - flash_info[i].sector_count = CFG_MAX_FLASH_SECT; - memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); if (i == 0) - flashbase = PHYS_FLASH_1; + flashbase = CFG_FLASH_BASE; else panic ("configured too many flash banks!\n"); - for (j = 0; j < flash_info[i].sector_count; j++) { - - flash_info[i].start[j] = flashbase; - - /* the first 8 sectors are 8 kB */ - flashbase += (j < 8) ? 0x4000 : MAIN_SECT_SIZE; + for (j = 0; j < info->sector_count; j++) { + + info->protect[j] = 0; + info->start[j] = flashbase; + + switch (info->flash_id & FLASH_TYPEMASK) { + case (FLASH_AM320B & FLASH_TYPEMASK): + case (FLASH_MXLV320B & FLASH_TYPEMASK): + /* Boot sector type: 8 x 8 + N x 128 kB */ + flashbase += (j < 8) ? 0x4000 : 0x20000; + break; + case (FLASH_AM640U & FLASH_TYPEMASK): + /* Uniform sector type: 128 kB */ + flashbase += 0x20000; + break; + default: + printf ("## Bad flash chip type 0x%04lX\n", + info->flash_id & FLASH_TYPEMASK); + } } - size += flash_info[i].size; } /* @@ -92,7 +103,7 @@ ulong flash_init (void) */ flash_protect ( FLAG_PROTECT_SET, CFG_FLASH_BASE, - CFG_FLASH_BASE + _armboot_end_data - _armboot_start, + CFG_FLASH_BASE + monitor_flash_len - 1, &flash_info[0]); flash_protect ( FLAG_PROTECT_SET, @@ -116,18 +127,25 @@ void flash_print_info (flash_info_t * info) int i; switch (info->flash_id & FLASH_VENDMASK) { - case (AMD_MANUFACT & FLASH_VENDMASK): - printf ("AMD: "); - break; - default: - printf ("Unknown Vendor "); - break; + case (FLASH_MAN_AMD & FLASH_VENDMASK): + printf ("AMD "); break; + case (FLASH_MAN_FUJ & FLASH_VENDMASK): + printf ("FUJITSU "); break; + case (FLASH_MAN_MX & FLASH_VENDMASK): + printf ("MACRONIX "); break; + default: printf ("Unknown Vendor "); break; } switch (info->flash_id & FLASH_TYPEMASK) { - case (AMD_ID_LV320B & FLASH_TYPEMASK): + case (FLASH_AM320B & FLASH_TYPEMASK): printf ("2x Am29LV320DB (32Mbit)\n"); break; + case (FLASH_MXLV320B & FLASH_TYPEMASK): + printf ("2x MX29LV320DB (32Mbit)\n"); + break; + case (FLASH_AM640U & FLASH_TYPEMASK): + printf ("2x Am29LV640D (64Mbit)\n"); + break; default: printf ("Unknown Chip Type\n"); goto Done; @@ -148,7 +166,7 @@ void flash_print_info (flash_info_t * info) } printf ("\n"); - Done: +Done: ; } /*----------------------------------------------------------------------- @@ -176,9 +194,13 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) return ERR_INVAL; } - if ((info->flash_id & FLASH_VENDMASK) != - (AMD_MANUFACT & FLASH_VENDMASK)) { - return ERR_UNKNOWN_FLASH_VENDOR; + switch (info->flash_id & FLASH_VENDMASK) { + case (FLASH_MAN_AMD & FLASH_VENDMASK): break; /* OK */ + case (FLASH_MAN_FUJ & FLASH_VENDMASK): break; /* OK */ + case (FLASH_MAN_MX & FLASH_VENDMASK): break; /* OK */ + default: + debug ("## flash_erase: unknown manufacturer\n"); + return (ERR_UNKNOWN_FLASH_VENDOR); } prot = 0; @@ -259,19 +281,14 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) if (chip1 == ERR || chip2 == ERR) { rc = ERR_PROG_ERROR; + printf ("Flash erase error\n"); goto outahere; } if (chip1 == TMO) { rc = ERR_TIMOUT; + printf ("Flash erase timeout error\n"); goto outahere; } - -#if 0 - printf ("ok.\n"); - } else { /* it was protected */ - - printf ("protected!\n"); -#endif } } @@ -293,8 +310,7 @@ outahere: * Copy memory to flash */ -volatile static int write_word (flash_info_t * info, ulong dest, - ulong data) +static int write_word (flash_info_t * info, ulong dest, ulong data) { vu_long *addr = (vu_long *) dest; ulong result; @@ -328,8 +344,7 @@ volatile static int write_word (flash_info_t * info, ulong dest, MEM_FLASH_ADDR1 = CMD_UNLOCK1; MEM_FLASH_ADDR2 = CMD_UNLOCK2; - MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS; - *addr = CMD_PROGRAM; + MEM_FLASH_ADDR1 = CMD_PROGRAM; *addr = data; /* arm simple, non interrupt dependent timer */ @@ -341,7 +356,7 @@ volatile static int write_word (flash_info_t * info, ulong dest, result = *addr; /* check timeout */ - if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) { + if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) { chip1 = ERR | TMO; break; } @@ -373,8 +388,13 @@ volatile static int write_word (flash_info_t * info, ulong dest, *addr = CMD_READ_ARRAY; - if (chip1 == ERR || chip2 == ERR || *addr != data) + if (chip1 == ERR || chip2 == ERR || *addr != data) { rc = ERR_PROG_ERROR; + printf ("Flash program error\n"); + debug ("chip1: %#x, chip2: %#x, addr: %#lx *addr: %#lx, " + "data: %#lx\n", + chip1, chip2, addr, *addr, data); + } if (iflag) enable_interrupts (); @@ -417,7 +437,7 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) } if ((rc = write_word (info, wp, data)) != 0) { - return (rc); + goto Done; } wp += 4; } @@ -426,9 +446,17 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) * handle word aligned part */ while (cnt >= 4) { - data = *((vu_long *) src); + if (((ulong)src) & 0x3) { + for (i = 0; i < 4; i++) { + ((char *)&data)[i] = ((vu_char *)src)[i]; + } + } + else { + data = *((vu_long *) src); + } + if ((rc = write_word (info, wp, data)) != 0) { - return (rc); + goto Done; } src += 4; wp += 4; @@ -436,7 +464,8 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) } if (cnt == 0) { - return ERR_OK; + rc = ERR_OK; + goto Done; } /* @@ -451,5 +480,90 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) data = (data >> 8) | (*(uchar *) cp << 24); } - return write_word (info, wp, data); + rc = write_word (info, wp, data); + + Done: + + return (rc); +} + +/*----------------------------------------------------------------------- + */ + +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + ulong value; + + /* Write auto select command sequence and read Manufacturer ID */ + addr[0x0555] = CMD_UNLOCK1; + addr[0x02AA] = CMD_UNLOCK2; + addr[0x0555] = CMD_READ_MANF_ID; + + value = addr[0]; + + debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value); + + switch (value) { + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case MX_MANUFACT: + info->flash_id = FLASH_MAN_MX; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + addr[0] = CMD_READ_ARRAY; /* restore read mode */ + debug ("## flash_init: unknown manufacturer\n"); + return (0); /* no or unknown flash */ + } + + value = addr[1]; /* device ID */ + + debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value); + + switch (value) { + case AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 71; + info->size = 0x00800000; + + addr[0] = CMD_READ_ARRAY; /* restore read mode */ + break; /* => 8 MB */ + + case AMD_ID_LV640U: + info->flash_id += FLASH_AM640U; + info->sector_count = 128; + info->size = 0x01000000; + + addr[0] = CMD_READ_ARRAY; /* restore read mode */ + break; /* => 16 MB */ + + case MX_ID_LV320B: + info->flash_id += FLASH_MXLV320B; + info->sector_count = 71; + info->size = 0x00800000; + + addr[0] = CMD_READ_ARRAY; /* restore read mode */ + break; /* => 8 MB */ + + default: + debug ("## flash_init: unknown flash chip\n"); + info->flash_id = FLASH_UNKNOWN; + addr[0] = CMD_READ_ARRAY; /* restore read mode */ + return (0); /* => no or unknown flash */ + + } + + if (info->sector_count > CFG_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CFG_MAX_FLASH_SECT); + info->sector_count = CFG_MAX_FLASH_SECT; + } + + return (info->size); }