#include <common.h>
#include <environment.h>
-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];
#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)))
int i, j;
ulong size = 0;
- for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+ for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
ulong flashbase = 0;
+ flash_info_t *info = &flash_info[i];
+
+ /* Init: no FLASHes known */
+ info->flash_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):
+ /* 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;
}
/*
*/
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,
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;
+ 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_AM640U & FLASH_TYPEMASK):
+ printf ("2x Am29LV640D (64Mbit)\n");
+ break;
default:
printf ("Unknown Chip Type\n");
goto Done;
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 */
+ default:
+ debug ("## flash_erase: unknown manufacturer\n");
+ return (ERR_UNKNOWN_FLASH_VENDOR);
}
prot = 0;
rc = ERR_TIMOUT;
goto outahere;
}
-
-#if 0
- printf ("ok.\n");
- } else { /* it was protected */
-
- printf ("protected!\n");
-#endif
}
}
#endif
iflag = disable_interrupts ();
- MEM_FLASH_ADDR1 = CMD_UNLOCK1;
- MEM_FLASH_ADDR2 = CMD_UNLOCK2;
- MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
*addr = CMD_PROGRAM;
*addr = data;
int l;
int i, rc;
+ MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+ MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+ MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
+
wp = (addr & ~3); /* get lower word aligned address */
/*
}
if ((rc = write_word (info, wp, data)) != 0) {
- return (rc);
+ goto Done;
}
wp += 4;
}
* 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;
}
if (cnt == 0) {
- return ERR_OK;
+ rc = ERR_OK;
+ goto Done;
}
/*
data = (data >> 8) | (*(uchar *) cp << 24);
}
- return write_word (info, wp, data);
+ rc = write_word (info, wp, data);
+
+ Done:
+
+ MEM_FLASH_ADDR = CMD_UNLOCK_BYPASS_RES1;
+ MEM_FLASH_ADDR = CMD_UNLOCK_BYPASS_RES2;
+
+ 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;
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ addr[0] = 0x00FF00FF; /* 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] = 0x00FF00FF; /* restore read mode */
+ break; /* => 8 MB */
+
+ case AMD_ID_LV640U:
+ info->flash_id += FLASH_AM640U;
+ info->sector_count = 128;
+ info->size = 0x01000000;
+
+ addr[0] = 0x00F000F0; /* restore read mode */
+ break; /* => 16 MB */
+
+ default:
+ debug ("## flash_init: unknown flash chip\n");
+ info->flash_id = FLASH_UNKNOWN;
+ addr[0] = 0x00FF00FF; /* 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);
}