#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
#endif
+typedef unsigned long flash_sect_t;
/*-----------------------------------------------------------------------
- * Functions
*/
+#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
+static flash_info_t *flash_get_info(ulong base)
+{
+ int i;
+ flash_info_t * info = 0;
-typedef unsigned long flash_sect_t;
+ for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+ info = & flash_info[i];
+ if (info->size && info->start[0] <= base &&
+ base <= info->start[0] + info->size - 1)
+ break;
+ }
-static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c);
-static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf);
-static void flash_write_cmd (flash_info_t * info, flash_sect_t sect,
- uint offset, uchar cmd);
-static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect);
-static int flash_isequal (flash_info_t * info, flash_sect_t sect,
- uint offset, uchar cmd);
-static int flash_isset (flash_info_t * info, flash_sect_t sect,
- uint offset, uchar cmd);
-static int flash_toggle (flash_info_t * info, flash_sect_t sect,
- uint offset, uchar cmd);
-static void flash_read_jedec_ids (flash_info_t * info);
-static int flash_detect_cfi (flash_info_t * info);
-static int flash_write_cfiword (flash_info_t * info, ulong dest,
- cfiword_t cword);
-static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
- ulong tout, char *prompt);
-ulong flash_get_size (ulong base, int banknum);
-#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
-static flash_info_t *flash_get_info(ulong base);
-#endif
-#ifdef CFG_FLASH_USE_BUFFER_WRITE
-static int flash_write_cfibuffer (flash_info_t * info, ulong dest,
- uchar * cp, int len);
+ return i == CFG_MAX_FLASH_BANKS ? 0 : info;
+}
#endif
/*-----------------------------------------------------------------------
return ((uchar *) (info->start[sect] + (offset * info->portwidth)));
}
+/*-----------------------------------------------------------------------
+ * make a proper sized command based on the port and chip widths
+ */
+static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
+{
+ int i;
+ uchar *cp = (uchar *) cmdbuf;
+
+#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
+ for (i = info->portwidth; i > 0; i--)
+#else
+ for (i = 1; i <= info->portwidth; i++)
+#endif
+ *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd;
+}
+
#ifdef DEBUG
/*-----------------------------------------------------------------------
* Debug support
for (i = 0; i < 8; i++)
sprintf (&str[i * 2], "%2.2x", *cp++);
}
+
static void flash_printqry (flash_info_t * info, flash_sect_t sect)
{
cfiptr_t cptr;
return retval;
}
-
-#ifdef CONFIG_FLASH_CFI_LEGACY
-/*-----------------------------------------------------------------------
- * Call board code to request info about non-CFI flash.
- * board_flash_get_legacy needs to fill in at least:
- * info->portwidth, info->chipwidth and info->interface for Jedec probing.
+/*
+ * Write a proper sized command to the correct address
*/
-static int flash_detect_legacy(ulong base, int banknum)
+static void flash_write_cmd (flash_info_t * info, flash_sect_t sect,
+ uint offset, uchar cmd)
{
- flash_info_t *info = &flash_info[banknum];
- if (board_flash_get_legacy(base, banknum, info)) {
- /* board code may have filled info completely. If not, we
- use JEDEC ID probing. */
- if (!info->vendor) {
- int modes[] = {
- CFI_CMDSET_AMD_STANDARD,
- CFI_CMDSET_INTEL_STANDARD
- };
- int i;
+ volatile cfiptr_t addr;
+ cfiword_t cword;
- for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
- info->vendor = modes[i];
- info->start[0] = base;
- if (info->portwidth == FLASH_CFI_8BIT
- && info->interface == FLASH_CFI_X8X16) {
- info->addr_unlock1 = 0x2AAA;
- info->addr_unlock2 = 0x5555;
- } else {
- info->addr_unlock1 = 0x5555;
- info->addr_unlock2 = 0x2AAA;
- }
- flash_read_jedec_ids(info);
- debug("JEDEC PROBE: ID %x %x %x\n",
- info->manufacturer_id,
- info->device_id,
- info->device_id2);
- if (jedec_flash_match(info, base))
- break;
- }
- }
+ addr.cp = flash_make_addr (info, sect, offset);
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr.cp, cmd,
+ cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ *addr.cp = cword.c;
+ break;
+ case FLASH_CFI_16BIT:
+ debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr.wp,
+ cmd, cword.w,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ *addr.wp = cword.w;
+ break;
+ case FLASH_CFI_32BIT:
+ debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr.lp,
+ cmd, cword.l,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ *addr.lp = cword.l;
+ break;
+ case FLASH_CFI_64BIT:
+#ifdef DEBUG
+ {
+ char str[20];
- switch(info->vendor) {
- case CFI_CMDSET_INTEL_STANDARD:
- case CFI_CMDSET_INTEL_EXTENDED:
- info->cmd_reset = FLASH_CMD_RESET;
- break;
- case CFI_CMDSET_AMD_STANDARD:
- case CFI_CMDSET_AMD_EXTENDED:
- case CFI_CMDSET_AMD_LEGACY:
- info->cmd_reset = AMD_CMD_RESET;
- break;
+ print_longlong (str, cword.ll);
+
+ debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
+ addr.llp, cmd, str,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
}
- info->flash_id = FLASH_MAN_CFI;
- return 1;
+#endif
+ *addr.llp = cword.ll;
+ break;
}
- return 0; /* use CFI */
+
+ /* Ensure all the instructions are fully finished */
+ sync();
}
-#else
-static inline int flash_detect_legacy(ulong base, int banknum)
+
+static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
{
- return 0; /* use CFI */
+ flash_write_cmd (info, sect, info->addr_unlock1, AMD_CMD_UNLOCK_START);
+ flash_write_cmd (info, sect, info->addr_unlock2, AMD_CMD_UNLOCK_ACK);
}
-#endif
-
/*-----------------------------------------------------------------------
*/
-unsigned long flash_init (void)
+static int flash_isequal (flash_info_t * info, flash_sect_t sect,
+ uint offset, uchar cmd)
{
- unsigned long size = 0;
- int i;
+ cfiptr_t cptr;
+ cfiword_t cword;
+ int retval;
-#ifdef CFG_FLASH_PROTECTION
- char *s = getenv("unlock");
-#endif
+ cptr.cp = flash_make_addr (info, sect, offset);
+ flash_make_cmd (info, cmd, &cword);
- /* Init: no FLASHes known */
- for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
- flash_info[i].flash_id = FLASH_UNKNOWN;
+ debug ("is= cmd %x(%c) addr %p ", cmd, cmd, cptr.cp);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ debug ("is= %x %x\n", cptr.cp[0], cword.c);
+ retval = (cptr.cp[0] == cword.c);
+ break;
+ case FLASH_CFI_16BIT:
+ debug ("is= %4.4x %4.4x\n", cptr.wp[0], cword.w);
+ retval = (cptr.wp[0] == cword.w);
+ break;
+ case FLASH_CFI_32BIT:
+ debug ("is= %8.8lx %8.8lx\n", cptr.lp[0], cword.l);
+ retval = (cptr.lp[0] == cword.l);
+ break;
+ case FLASH_CFI_64BIT:
+#ifdef DEBUG
+ {
+ char str1[20];
+ char str2[20];
- if (!flash_detect_legacy (bank_base[i], i))
- flash_get_size (bank_base[i], i);
- size += flash_info[i].size;
- if (flash_info[i].flash_id == FLASH_UNKNOWN) {
-#ifndef CFG_FLASH_QUIET_TEST
- printf ("## Unknown FLASH on Bank %d "
- "- Size = 0x%08lx = %ld MB\n",
- i+1, flash_info[i].size,
- flash_info[i].size << 20);
-#endif /* CFG_FLASH_QUIET_TEST */
+ print_longlong (str1, cptr.llp[0]);
+ print_longlong (str2, cword.ll);
+ debug ("is= %s %s\n", str1, str2);
}
-#ifdef CFG_FLASH_PROTECTION
- else if ((s != NULL) && (strcmp(s, "yes") == 0)) {
- /*
- * Only the U-Boot image and it's environment
- * is protected, all other sectors are
- * unprotected (unlocked) if flash hardware
- * protection is used (CFG_FLASH_PROTECTION)
- * and the environment variable "unlock" is
- * set to "yes".
- */
- if (flash_info[i].legacy_unlock) {
- int k;
-
- /*
- * Disable legacy_unlock temporarily,
- * since flash_real_protect would
- * relock all other sectors again
- * otherwise.
- */
- flash_info[i].legacy_unlock = 0;
+#endif
+ retval = (cptr.llp[0] == cword.ll);
+ break;
+ default:
+ retval = 0;
+ break;
+ }
+ return retval;
+}
- /*
- * Legacy unlocking (e.g. Intel J3) ->
- * unlock only one sector. This will
- * unlock all sectors.
- */
- flash_real_protect (&flash_info[i], 0, 0);
+/*-----------------------------------------------------------------------
+ */
+static int flash_isset (flash_info_t * info, flash_sect_t sect,
+ uint offset, uchar cmd)
+{
+ cfiptr_t cptr;
+ cfiword_t cword;
+ int retval;
- flash_info[i].legacy_unlock = 1;
+ cptr.cp = flash_make_addr (info, sect, offset);
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ retval = ((cptr.cp[0] & cword.c) == cword.c);
+ break;
+ case FLASH_CFI_16BIT:
+ retval = ((cptr.wp[0] & cword.w) == cword.w);
+ break;
+ case FLASH_CFI_32BIT:
+ retval = ((cptr.lp[0] & cword.l) == cword.l);
+ break;
+ case FLASH_CFI_64BIT:
+ retval = ((cptr.llp[0] & cword.ll) == cword.ll);
+ break;
+ default:
+ retval = 0;
+ break;
+ }
+ return retval;
+}
- /*
- * Manually mark other sectors as
- * unlocked (unprotected)
- */
- for (k = 1; k < flash_info[i].sector_count; k++)
- flash_info[i].protect[k] = 0;
- } else {
- /*
- * No legancy unlocking -> unlock all sectors
- */
- flash_protect (FLAG_PROTECT_CLEAR,
- flash_info[i].start[0],
- flash_info[i].start[0]
- + flash_info[i].size - 1,
- &flash_info[i]);
- }
- }
-#endif /* CFG_FLASH_PROTECTION */
- }
-
- /* Monitor protection ON by default */
-#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
- flash_protect (FLAG_PROTECT_SET,
- CFG_MONITOR_BASE,
- CFG_MONITOR_BASE + monitor_flash_len - 1,
- flash_get_info(CFG_MONITOR_BASE));
-#endif
-
- /* Environment protection ON by default */
-#ifdef CFG_ENV_IS_IN_FLASH
- flash_protect (FLAG_PROTECT_SET,
- CFG_ENV_ADDR,
- CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
- flash_get_info(CFG_ENV_ADDR));
-#endif
+/*-----------------------------------------------------------------------
+ */
+static int flash_toggle (flash_info_t * info, flash_sect_t sect,
+ uint offset, uchar cmd)
+{
+ cfiptr_t cptr;
+ cfiword_t cword;
+ int retval;
- /* Redundant environment protection ON by default */
-#ifdef CFG_ENV_ADDR_REDUND
- flash_protect (FLAG_PROTECT_SET,
- CFG_ENV_ADDR_REDUND,
- CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
- flash_get_info(CFG_ENV_ADDR_REDUND));
-#endif
- return (size);
+ cptr.cp = flash_make_addr (info, sect, offset);
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c));
+ break;
+ case FLASH_CFI_16BIT:
+ retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w));
+ break;
+ case FLASH_CFI_32BIT:
+ retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l));
+ break;
+ case FLASH_CFI_64BIT:
+ retval = ((cptr.llp[0] & cword.ll) !=
+ (cptr.llp[0] & cword.ll));
+ break;
+ default:
+ retval = 0;
+ break;
+ }
+ return retval;
}
-/*-----------------------------------------------------------------------
+/*
+ * flash_is_busy - check to see if the flash is busy
+ *
+ * This routine checks the status of the chip and returns true if the
+ * chip is busy.
*/
-#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
-static flash_info_t *flash_get_info(ulong base)
+static int flash_is_busy (flash_info_t * info, flash_sect_t sect)
{
- int i;
- flash_info_t * info = 0;
+ int retval;
- for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
- info = & flash_info[i];
- if (info->size && info->start[0] <= base &&
- base <= info->start[0] + info->size - 1)
- break;
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_STANDARD:
+ case CFI_CMDSET_INTEL_EXTENDED:
+ retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE);
+ break;
+ case CFI_CMDSET_AMD_STANDARD:
+ case CFI_CMDSET_AMD_EXTENDED:
+#ifdef CONFIG_FLASH_CFI_LEGACY
+ case CFI_CMDSET_AMD_LEGACY:
+#endif
+ retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
+ break;
+ default:
+ retval = 0;
}
-
- return i == CFG_MAX_FLASH_BANKS ? 0 : info;
+ debug ("flash_is_busy: %d\n", retval);
+ return retval;
}
-#endif
/*-----------------------------------------------------------------------
+ * wait for XSR.7 to be set. Time out with an error if it does not.
+ * This routine does not set the flash to read-array mode.
*/
-int flash_erase (flash_info_t * info, int s_first, int s_last)
+static int flash_status_check (flash_info_t * info, flash_sect_t sector,
+ ulong tout, char *prompt)
{
- int rcode = 0;
- int prot;
- flash_sect_t sect;
+ ulong start;
- if (info->flash_id != FLASH_MAN_CFI) {
- puts ("Can't erase unknown flash type - aborted\n");
- return 1;
- }
- if ((s_first < 0) || (s_first > s_last)) {
- puts ("- no sectors to erase\n");
- return 1;
- }
+#if CFG_HZ != 1000
+ tout *= CFG_HZ/1000;
+#endif
- prot = 0;
- for (sect = s_first; sect <= s_last; ++sect) {
- if (info->protect[sect]) {
- prot++;
+ /* Wait for command completion */
+ start = get_timer (0);
+ while (flash_is_busy (info, sector)) {
+ if (get_timer (start) > tout) {
+ printf ("Flash %s timeout at address %lx data %lx\n",
+ prompt, info->start[sector],
+ flash_read_long (info, sector, 0));
+ flash_write_cmd (info, sector, 0, info->cmd_reset);
+ return ERR_TIMOUT;
}
+ udelay (1); /* also triggers watchdog */
}
- if (prot) {
- printf ("- Warning: %d protected sectors will not be erased!\n",
- prot);
- } else {
- putc ('\n');
- }
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------
+ * Wait for XSR.7 to be set, if it times out print an error, otherwise
+ * do a full status check.
+ *
+ * This routine sets the flash to read-array mode.
+ */
+static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
+ ulong tout, char *prompt)
+{
+ int retcode;
- for (sect = s_first; sect <= s_last; sect++) {
- if (info->protect[sect] == 0) { /* not protected */
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_STANDARD:
- case CFI_CMDSET_INTEL_EXTENDED:
- flash_write_cmd (info, sect, 0,
- FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sect, 0,
- FLASH_CMD_BLOCK_ERASE);
- flash_write_cmd (info, sect, 0,
- FLASH_CMD_ERASE_CONFIRM);
- break;
- case CFI_CMDSET_AMD_STANDARD:
- case CFI_CMDSET_AMD_EXTENDED:
- flash_unlock_seq (info, sect);
- flash_write_cmd (info, sect,
- info->addr_unlock1,
- AMD_CMD_ERASE_START);
- flash_unlock_seq (info, sect);
- flash_write_cmd (info, sect, 0,
- AMD_CMD_ERASE_SECTOR);
- break;
-#ifdef CONFIG_FLASH_CFI_LEGACY
- case CFI_CMDSET_AMD_LEGACY:
- flash_unlock_seq (info, 0);
- flash_write_cmd (info, 0, info->addr_unlock1,
- AMD_CMD_ERASE_START);
- flash_unlock_seq (info, 0);
- flash_write_cmd (info, sect, 0,
- AMD_CMD_ERASE_SECTOR);
- break;
-#endif
- default:
- debug ("Unkown flash vendor %d\n",
- info->vendor);
- break;
+ retcode = flash_status_check (info, sector, tout, prompt);
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_EXTENDED:
+ case CFI_CMDSET_INTEL_STANDARD:
+ if ((retcode == ERR_OK)
+ && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
+ retcode = ERR_INVAL;
+ printf ("Flash %s error at address %lx\n", prompt,
+ info->start[sector]);
+ if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS |
+ FLASH_STATUS_PSLBS)) {
+ puts ("Command Sequence Error.\n");
+ } else if (flash_isset (info, sector, 0,
+ FLASH_STATUS_ECLBS)) {
+ puts ("Block Erase Error.\n");
+ retcode = ERR_NOT_ERASED;
+ } else if (flash_isset (info, sector, 0,
+ FLASH_STATUS_PSLBS)) {
+ puts ("Locking Error\n");
}
-
- if (flash_full_status_check
- (info, sect, info->erase_blk_tout, "erase")) {
- rcode = 1;
- } else
- putc ('.');
+ if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
+ puts ("Block locked.\n");
+ retcode = ERR_PROTECTED;
+ }
+ if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
+ puts ("Vpp Low Error.\n");
}
+ flash_write_cmd (info, sector, 0, info->cmd_reset);
+ break;
+ default:
+ break;
}
- puts (" done\n");
- return rcode;
+ return retcode;
}
/*-----------------------------------------------------------------------
*/
-void flash_print_info (flash_info_t * info)
+static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
{
- int i;
-
- if (info->flash_id != FLASH_MAN_CFI) {
- puts ("missing or unknown FLASH type\n");
- return;
- }
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
+ unsigned short w;
+ unsigned int l;
+ unsigned long long ll;
+#endif
- printf ("%s FLASH (%d x %d)",
- info->name,
- (info->portwidth << 3), (info->chipwidth << 3));
- if (info->size < 1024*1024)
- printf (" Size: %ld kB in %d Sectors\n",
- info->size >> 10, info->sector_count);
- else
- printf (" Size: %ld MB in %d Sectors\n",
- info->size >> 20, info->sector_count);
- printf (" ");
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_STANDARD:
- printf ("Intel Standard");
- break;
- case CFI_CMDSET_INTEL_EXTENDED:
- printf ("Intel Extended");
- break;
- case CFI_CMDSET_AMD_STANDARD:
- printf ("AMD Standard");
- break;
- case CFI_CMDSET_AMD_EXTENDED:
- printf ("AMD Extended");
- break;
-#ifdef CONFIG_FLASH_CFI_LEGACY
- case CFI_CMDSET_AMD_LEGACY:
- printf ("AMD Legacy");
- break;
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ cword->c = c;
+ break;
+ case FLASH_CFI_16BIT:
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
+ w = c;
+ w <<= 8;
+ cword->w = (cword->w >> 8) | w;
+#else
+ cword->w = (cword->w << 8) | c;
#endif
- default:
- printf ("Unknown (%d)", info->vendor);
- break;
- }
- printf (" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X",
- info->manufacturer_id, info->device_id);
- if (info->device_id == 0x7E) {
- printf("%04X", info->device_id2);
- }
- printf ("\n Erase timeout: %ld ms, write timeout: %ld ms\n",
- info->erase_blk_tout,
- info->write_tout);
- if (info->buffer_size > 1) {
- printf (" Buffer write timeout: %ld ms, "
- "buffer size: %d bytes\n",
- info->buffer_write_tout,
- info->buffer_size);
+ break;
+ case FLASH_CFI_32BIT:
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
+ l = c;
+ l <<= 24;
+ cword->l = (cword->l >> 8) | l;
+#else
+ cword->l = (cword->l << 8) | c;
+#endif
+ break;
+ case FLASH_CFI_64BIT:
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
+ ll = c;
+ ll <<= 56;
+ cword->ll = (cword->ll >> 8) | ll;
+#else
+ cword->ll = (cword->ll << 8) | c;
+#endif
+ break;
}
+}
- puts ("\n Sector Start Addresses:");
- for (i = 0; i < info->sector_count; ++i) {
- if ((i % 5) == 0)
- printf ("\n");
-#ifdef CFG_FLASH_EMPTY_INFO
- int k;
- int size;
- int erased;
- volatile unsigned long *flash;
-
- /*
- * 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;
- }
- }
+/* loop through the sectors from the highest address when the passed
+ * address is greater or equal to the sector address we have a match
+ */
+static flash_sect_t find_sector (flash_info_t * info, ulong addr)
+{
+ flash_sect_t sector;
- /* print empty and read-only info */
- printf (" %08lX %c %s ",
- info->start[i],
- erased ? 'E' : ' ',
- info->protect[i] ? "RO" : " ");
-#else /* ! CFG_FLASH_EMPTY_INFO */
- printf (" %08lX %s ",
- info->start[i],
- info->protect[i] ? "RO" : " ");
-#endif
+ for (sector = info->sector_count - 1; sector >= 0; sector--) {
+ if (addr >= info->start[sector])
+ break;
}
- putc ('\n');
- return;
+ return sector;
}
/*-----------------------------------------------------------------------
- * 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)
+static int flash_write_cfiword (flash_info_t * info, ulong dest,
+ cfiword_t cword)
{
- ulong wp;
- ulong cp;
- int aln;
- cfiword_t cword;
- int i, rc;
-
-#ifdef CFG_FLASH_USE_BUFFER_WRITE
- int buffered_size;
-#endif
- /* get lower aligned address */
- /* get lower aligned address */
- wp = (addr & ~(info->portwidth - 1));
+ cfiptr_t ctladdr;
+ cfiptr_t cptr;
+ int flag;
- /* handle unaligned start */
- if ((aln = addr - wp) != 0) {
- cword.l = 0;
- cp = wp;
- for (i = 0; i < aln; ++i, ++cp)
- flash_add_byte (info, &cword, (*(uchar *) cp));
+ ctladdr.cp = flash_make_addr (info, 0, 0);
+ cptr.cp = (uchar *) dest;
- for (; (i < info->portwidth) && (cnt > 0); i++) {
- flash_add_byte (info, &cword, *src++);
- cnt--;
- cp++;
- }
- for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)
- flash_add_byte (info, &cword, (*(uchar *) cp));
- if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
- return rc;
- wp = cp;
+ /* Check if Flash is (sufficiently) erased */
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ flag = ((cptr.cp[0] & cword.c) == cword.c);
+ break;
+ case FLASH_CFI_16BIT:
+ flag = ((cptr.wp[0] & cword.w) == cword.w);
+ break;
+ case FLASH_CFI_32BIT:
+ flag = ((cptr.lp[0] & cword.l) == cword.l);
+ break;
+ case FLASH_CFI_64BIT:
+ flag = ((cptr.llp[0] & cword.ll) == cword.ll);
+ break;
+ default:
+ return 2;
}
+ if (!flag)
+ return 2;
- /* handle the aligned part */
-#ifdef CFG_FLASH_USE_BUFFER_WRITE
- buffered_size = (info->portwidth / info->chipwidth);
- buffered_size *= info->buffer_size;
- while (cnt >= info->portwidth) {
- /* prohibit buffer write when buffer_size is 1 */
- if (info->buffer_size == 1) {
- cword.l = 0;
- for (i = 0; i < info->portwidth; i++)
- flash_add_byte (info, &cword, *src++);
- if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
- return rc;
- wp += info->portwidth;
- cnt -= info->portwidth;
- continue;
- }
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts ();
- /* write buffer until next buffered_size aligned boundary */
- i = buffered_size - (wp % buffered_size);
- if (i > cnt)
- i = cnt;
- if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
- return rc;
- i -= i & (info->portwidth - 1);
- wp += i;
- src += i;
- cnt -= i;
- }
-#else
- while (cnt >= info->portwidth) {
- cword.l = 0;
- for (i = 0; i < info->portwidth; i++) {
- flash_add_byte (info, &cword, *src++);
- }
- if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
- return rc;
- wp += info->portwidth;
- cnt -= info->portwidth;
- }
-#endif /* CFG_FLASH_USE_BUFFER_WRITE */
- if (cnt == 0) {
- return (0);
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_EXTENDED:
+ case CFI_CMDSET_INTEL_STANDARD:
+ flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE);
+ break;
+ case CFI_CMDSET_AMD_EXTENDED:
+ case CFI_CMDSET_AMD_STANDARD:
+#ifdef CONFIG_FLASH_CFI_LEGACY
+ case CFI_CMDSET_AMD_LEGACY:
+#endif
+ flash_unlock_seq (info, 0);
+ flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_WRITE);
+ break;
}
- /*
- * handle unaligned tail bytes
- */
- cword.l = 0;
- for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {
- flash_add_byte (info, &cword, *src++);
- --cnt;
- }
- for (; i < info->portwidth; ++i, ++cp) {
- flash_add_byte (info, &cword, (*(uchar *) cp));
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ cptr.cp[0] = cword.c;
+ break;
+ case FLASH_CFI_16BIT:
+ cptr.wp[0] = cword.w;
+ break;
+ case FLASH_CFI_32BIT:
+ cptr.lp[0] = cword.l;
+ break;
+ case FLASH_CFI_64BIT:
+ cptr.llp[0] = cword.ll;
+ break;
}
- return flash_write_cfiword (info, wp, cword);
-}
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts ();
-/*-----------------------------------------------------------------------
- */
-#ifdef CFG_FLASH_PROTECTION
-
-int flash_real_protect (flash_info_t * info, long sector, int prot)
-{
- int retcode = 0;
-
- flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
- if (prot)
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
- else
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
-
- if ((retcode =
- flash_full_status_check (info, sector, info->erase_blk_tout,
- prot ? "protect" : "unprotect")) == 0) {
-
- info->protect[sector] = prot;
-
- /*
- * On some of Intel's flash chips (marked via legacy_unlock)
- * unprotect unprotects all locking.
- */
- if ((prot == 0) && (info->legacy_unlock)) {
- flash_sect_t i;
-
- for (i = 0; i < info->sector_count; i++) {
- if (info->protect[i])
- flash_real_protect (info, i, 1);
- }
- }
- }
- return retcode;
-}
-
-/*-----------------------------------------------------------------------
- * flash_read_user_serial - read the OneTimeProgramming cells
- */
-void flash_read_user_serial (flash_info_t * info, void *buffer, int offset,
- int len)
-{
- uchar *src;
- uchar *dst;
-
- dst = buffer;
- src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION);
- flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
- memcpy (dst, src + offset, len);
- flash_write_cmd (info, 0, 0, info->cmd_reset);
-}
-
-/*
- * flash_read_factory_serial - read the device Id from the protection area
- */
-void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset,
- int len)
-{
- uchar *src;
-
- src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
- flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
- memcpy (buffer, src + offset, len);
- flash_write_cmd (info, 0, 0, info->cmd_reset);
+ return flash_full_status_check (info, find_sector (info, dest),
+ info->write_tout, "write");
}
-#endif /* CFG_FLASH_PROTECTION */
+#ifdef CFG_FLASH_USE_BUFFER_WRITE
-/*
- * flash_is_busy - check to see if the flash is busy
- *
- * This routine checks the status of the chip and returns true if the
- * chip is busy.
- */
-static int flash_is_busy (flash_info_t * info, flash_sect_t sect)
+static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
+ int len)
{
- int retval;
+ flash_sect_t sector;
+ int cnt;
+ int retcode;
+ volatile cfiptr_t src;
+ volatile cfiptr_t dst;
switch (info->vendor) {
case CFI_CMDSET_INTEL_STANDARD:
case CFI_CMDSET_INTEL_EXTENDED:
- retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE);
- break;
+ src.cp = cp;
+ dst.cp = (uchar *) dest;
+ sector = find_sector (info, dest);
+ flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
+ retcode = flash_status_check (info, sector,
+ info->buffer_write_tout,
+ "write to buffer");
+ if (retcode == ERR_OK) {
+ /* reduce the number of loops by the width of
+ * the port */
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ cnt = len;
+ break;
+ case FLASH_CFI_16BIT:
+ cnt = len >> 1;
+ break;
+ case FLASH_CFI_32BIT:
+ cnt = len >> 2;
+ break;
+ case FLASH_CFI_64BIT:
+ cnt = len >> 3;
+ break;
+ default:
+ return ERR_INVAL;
+ break;
+ }
+ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+ while (cnt-- > 0) {
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ *dst.cp++ = *src.cp++;
+ break;
+ case FLASH_CFI_16BIT:
+ *dst.wp++ = *src.wp++;
+ break;
+ case FLASH_CFI_32BIT:
+ *dst.lp++ = *src.lp++;
+ break;
+ case FLASH_CFI_64BIT:
+ *dst.llp++ = *src.llp++;
+ break;
+ default:
+ return ERR_INVAL;
+ break;
+ }
+ }
+ flash_write_cmd (info, sector, 0,
+ FLASH_CMD_WRITE_BUFFER_CONFIRM);
+ retcode = flash_full_status_check (
+ info, sector, info->buffer_write_tout,
+ "buffer write");
+ }
+ return retcode;
+
case CFI_CMDSET_AMD_STANDARD:
case CFI_CMDSET_AMD_EXTENDED:
-#ifdef CONFIG_FLASH_CFI_LEGACY
- case CFI_CMDSET_AMD_LEGACY:
-#endif
- retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
- break;
+ src.cp = cp;
+ dst.cp = (uchar *) dest;
+ sector = find_sector (info, dest);
+
+ flash_unlock_seq(info,0);
+ flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER);
+
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ cnt = len;
+ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+ while (cnt-- > 0) *dst.cp++ = *src.cp++;
+ break;
+ case FLASH_CFI_16BIT:
+ cnt = len >> 1;
+ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+ while (cnt-- > 0) *dst.wp++ = *src.wp++;
+ break;
+ case FLASH_CFI_32BIT:
+ cnt = len >> 2;
+ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+ while (cnt-- > 0) *dst.lp++ = *src.lp++;
+ break;
+ case FLASH_CFI_64BIT:
+ cnt = len >> 3;
+ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+ while (cnt-- > 0) *dst.llp++ = *src.llp++;
+ break;
+ default:
+ return ERR_INVAL;
+ }
+
+ flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
+ retcode = flash_full_status_check (info, sector,
+ info->buffer_write_tout,
+ "buffer write");
+ return retcode;
+
default:
- retval = 0;
+ debug ("Unknown Command Set\n");
+ return ERR_INVAL;
}
- debug ("flash_is_busy: %d\n", retval);
- return retval;
}
+#endif /* CFG_FLASH_USE_BUFFER_WRITE */
+
/*-----------------------------------------------------------------------
- * wait for XSR.7 to be set. Time out with an error if it does not.
- * This routine does not set the flash to read-array mode.
*/
-static int flash_status_check (flash_info_t * info, flash_sect_t sector,
- ulong tout, char *prompt)
+int flash_erase (flash_info_t * info, int s_first, int s_last)
{
- ulong start;
+ int rcode = 0;
+ int prot;
+ flash_sect_t sect;
-#if CFG_HZ != 1000
- tout *= CFG_HZ/1000;
-#endif
+ if (info->flash_id != FLASH_MAN_CFI) {
+ puts ("Can't erase unknown flash type - aborted\n");
+ return 1;
+ }
+ if ((s_first < 0) || (s_first > s_last)) {
+ puts ("- no sectors to erase\n");
+ return 1;
+ }
- /* Wait for command completion */
- start = get_timer (0);
- while (flash_is_busy (info, sector)) {
- if (get_timer (start) > tout) {
- printf ("Flash %s timeout at address %lx data %lx\n",
- prompt, info->start[sector],
- flash_read_long (info, sector, 0));
- flash_write_cmd (info, sector, 0, info->cmd_reset);
- return ERR_TIMOUT;
+ prot = 0;
+ for (sect = s_first; sect <= s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
}
- udelay (1); /* also triggers watchdog */
}
- return ERR_OK;
-}
+ if (prot) {
+ printf ("- Warning: %d protected sectors will not be erased!\n",
+ prot);
+ } else {
+ putc ('\n');
+ }
-/*-----------------------------------------------------------------------
- * Wait for XSR.7 to be set, if it times out print an error, otherwise
- * do a full status check.
- *
- * This routine sets the flash to read-array mode.
- */
-static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
- ulong tout, char *prompt)
-{
- int retcode;
- retcode = flash_status_check (info, sector, tout, prompt);
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_EXTENDED:
- case CFI_CMDSET_INTEL_STANDARD:
- if ((retcode == ERR_OK)
- && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
- retcode = ERR_INVAL;
- printf ("Flash %s error at address %lx\n", prompt,
- info->start[sector]);
- if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS |
- FLASH_STATUS_PSLBS)) {
- puts ("Command Sequence Error.\n");
- } else if (flash_isset (info, sector, 0,
- FLASH_STATUS_ECLBS)) {
- puts ("Block Erase Error.\n");
- retcode = ERR_NOT_ERASED;
- } else if (flash_isset (info, sector, 0,
- FLASH_STATUS_PSLBS)) {
- puts ("Locking Error\n");
- }
- if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
- puts ("Block locked.\n");
- retcode = ERR_PROTECTED;
+ for (sect = s_first; sect <= s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_STANDARD:
+ case CFI_CMDSET_INTEL_EXTENDED:
+ flash_write_cmd (info, sect, 0,
+ FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd (info, sect, 0,
+ FLASH_CMD_BLOCK_ERASE);
+ flash_write_cmd (info, sect, 0,
+ FLASH_CMD_ERASE_CONFIRM);
+ break;
+ case CFI_CMDSET_AMD_STANDARD:
+ case CFI_CMDSET_AMD_EXTENDED:
+ flash_unlock_seq (info, sect);
+ flash_write_cmd (info, sect,
+ info->addr_unlock1,
+ AMD_CMD_ERASE_START);
+ flash_unlock_seq (info, sect);
+ flash_write_cmd (info, sect, 0,
+ AMD_CMD_ERASE_SECTOR);
+ break;
+#ifdef CONFIG_FLASH_CFI_LEGACY
+ case CFI_CMDSET_AMD_LEGACY:
+ flash_unlock_seq (info, 0);
+ flash_write_cmd (info, 0, info->addr_unlock1,
+ AMD_CMD_ERASE_START);
+ flash_unlock_seq (info, 0);
+ flash_write_cmd (info, sect, 0,
+ AMD_CMD_ERASE_SECTOR);
+ break;
+#endif
+ default:
+ debug ("Unkown flash vendor %d\n",
+ info->vendor);
+ break;
}
- if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
- puts ("Vpp Low Error.\n");
+
+ if (flash_full_status_check
+ (info, sect, info->erase_blk_tout, "erase")) {
+ rcode = 1;
+ } else
+ putc ('.');
}
- flash_write_cmd (info, sector, 0, info->cmd_reset);
- break;
- default:
- break;
}
- return retcode;
+ puts (" done\n");
+ return rcode;
}
/*-----------------------------------------------------------------------
*/
-static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
+void flash_print_info (flash_info_t * info)
{
-#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
- unsigned short w;
- unsigned int l;
- unsigned long long ll;
-#endif
+ int i;
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- cword->c = c;
- break;
- case FLASH_CFI_16BIT:
-#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
- w = c;
- w <<= 8;
- cword->w = (cword->w >> 8) | w;
-#else
- cword->w = (cword->w << 8) | c;
-#endif
- break;
- case FLASH_CFI_32BIT:
-#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
- l = c;
- l <<= 24;
- cword->l = (cword->l >> 8) | l;
-#else
- cword->l = (cword->l << 8) | c;
-#endif
- break;
- case FLASH_CFI_64BIT:
-#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
- ll = c;
- ll <<= 56;
- cword->ll = (cword->ll >> 8) | ll;
-#else
- cword->ll = (cword->ll << 8) | c;
+ if (info->flash_id != FLASH_MAN_CFI) {
+ puts ("missing or unknown FLASH type\n");
+ return;
+ }
+
+ printf ("%s FLASH (%d x %d)",
+ info->name,
+ (info->portwidth << 3), (info->chipwidth << 3));
+ if (info->size < 1024*1024)
+ printf (" Size: %ld kB in %d Sectors\n",
+ info->size >> 10, info->sector_count);
+ else
+ printf (" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+ printf (" ");
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_STANDARD:
+ printf ("Intel Standard");
+ break;
+ case CFI_CMDSET_INTEL_EXTENDED:
+ printf ("Intel Extended");
+ break;
+ case CFI_CMDSET_AMD_STANDARD:
+ printf ("AMD Standard");
+ break;
+ case CFI_CMDSET_AMD_EXTENDED:
+ printf ("AMD Extended");
+ break;
+#ifdef CONFIG_FLASH_CFI_LEGACY
+ case CFI_CMDSET_AMD_LEGACY:
+ printf ("AMD Legacy");
+ break;
#endif
- break;
+ default:
+ printf ("Unknown (%d)", info->vendor);
+ break;
+ }
+ printf (" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X",
+ info->manufacturer_id, info->device_id);
+ if (info->device_id == 0x7E) {
+ printf("%04X", info->device_id2);
+ }
+ printf ("\n Erase timeout: %ld ms, write timeout: %ld ms\n",
+ info->erase_blk_tout,
+ info->write_tout);
+ if (info->buffer_size > 1) {
+ printf (" Buffer write timeout: %ld ms, "
+ "buffer size: %d bytes\n",
+ info->buffer_write_tout,
+ info->buffer_size);
}
-}
+ puts ("\n Sector Start Addresses:");
+ for (i = 0; i < info->sector_count; ++i) {
+ if ((i % 5) == 0)
+ printf ("\n");
+#ifdef CFG_FLASH_EMPTY_INFO
+ int k;
+ int size;
+ int erased;
+ volatile unsigned long *flash;
-/*-----------------------------------------------------------------------
- * make a proper sized command based on the port and chip widths
- */
-static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
-{
- int i;
- uchar *cp = (uchar *) cmdbuf;
+ /*
+ * 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 defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
- for (i = info->portwidth; i > 0; i--)
-#else
- for (i = 1; i <= info->portwidth; i++)
+ /* print empty and read-only info */
+ printf (" %08lX %c %s ",
+ info->start[i],
+ erased ? 'E' : ' ',
+ info->protect[i] ? "RO" : " ");
+#else /* ! CFG_FLASH_EMPTY_INFO */
+ printf (" %08lX %s ",
+ info->start[i],
+ info->protect[i] ? "RO" : " ");
#endif
- *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd;
+ }
+ putc ('\n');
+ return;
}
-/*
- * Write a proper sized command to the correct address
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
*/
-static void flash_write_cmd (flash_info_t * info, flash_sect_t sect,
- uint offset, uchar cmd)
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
{
-
- volatile cfiptr_t addr;
+ ulong wp;
+ ulong cp;
+ int aln;
cfiword_t cword;
+ int i, rc;
- addr.cp = flash_make_addr (info, sect, offset);
- flash_make_cmd (info, cmd, &cword);
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr.cp, cmd,
- cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- *addr.cp = cword.c;
- break;
- case FLASH_CFI_16BIT:
- debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr.wp,
- cmd, cword.w,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- *addr.wp = cword.w;
- break;
- case FLASH_CFI_32BIT:
- debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr.lp,
- cmd, cword.l,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- *addr.lp = cword.l;
- break;
- case FLASH_CFI_64BIT:
-#ifdef DEBUG
- {
- char str[20];
-
- print_longlong (str, cword.ll);
-
- debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
- addr.llp, cmd, str,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- }
+#ifdef CFG_FLASH_USE_BUFFER_WRITE
+ int buffered_size;
#endif
- *addr.llp = cword.ll;
- break;
- }
+ /* get lower aligned address */
+ /* get lower aligned address */
+ wp = (addr & ~(info->portwidth - 1));
- /* Ensure all the instructions are fully finished */
- sync();
-}
+ /* handle unaligned start */
+ if ((aln = addr - wp) != 0) {
+ cword.l = 0;
+ cp = wp;
+ for (i = 0; i < aln; ++i, ++cp)
+ flash_add_byte (info, &cword, (*(uchar *) cp));
-static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
-{
- flash_write_cmd (info, sect, info->addr_unlock1, AMD_CMD_UNLOCK_START);
- flash_write_cmd (info, sect, info->addr_unlock2, AMD_CMD_UNLOCK_ACK);
+ for (; (i < info->portwidth) && (cnt > 0); i++) {
+ flash_add_byte (info, &cword, *src++);
+ cnt--;
+ cp++;
+ }
+ for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)
+ flash_add_byte (info, &cword, (*(uchar *) cp));
+ if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
+ return rc;
+ wp = cp;
+ }
+
+ /* handle the aligned part */
+#ifdef CFG_FLASH_USE_BUFFER_WRITE
+ buffered_size = (info->portwidth / info->chipwidth);
+ buffered_size *= info->buffer_size;
+ while (cnt >= info->portwidth) {
+ /* prohibit buffer write when buffer_size is 1 */
+ if (info->buffer_size == 1) {
+ cword.l = 0;
+ for (i = 0; i < info->portwidth; i++)
+ flash_add_byte (info, &cword, *src++);
+ if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
+ return rc;
+ wp += info->portwidth;
+ cnt -= info->portwidth;
+ continue;
+ }
+
+ /* write buffer until next buffered_size aligned boundary */
+ i = buffered_size - (wp % buffered_size);
+ if (i > cnt)
+ i = cnt;
+ if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
+ return rc;
+ i -= i & (info->portwidth - 1);
+ wp += i;
+ src += i;
+ cnt -= i;
+ }
+#else
+ while (cnt >= info->portwidth) {
+ cword.l = 0;
+ for (i = 0; i < info->portwidth; i++) {
+ flash_add_byte (info, &cword, *src++);
+ }
+ if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
+ return rc;
+ wp += info->portwidth;
+ cnt -= info->portwidth;
+ }
+#endif /* CFG_FLASH_USE_BUFFER_WRITE */
+ if (cnt == 0) {
+ return (0);
+ }
+
+ /*
+ * handle unaligned tail bytes
+ */
+ cword.l = 0;
+ for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {
+ flash_add_byte (info, &cword, *src++);
+ --cnt;
+ }
+ for (; i < info->portwidth; ++i, ++cp) {
+ flash_add_byte (info, &cword, (*(uchar *) cp));
+ }
+
+ return flash_write_cfiword (info, wp, cword);
}
/*-----------------------------------------------------------------------
*/
-static int flash_isequal (flash_info_t * info, flash_sect_t sect,
- uint offset, uchar cmd)
+#ifdef CFG_FLASH_PROTECTION
+
+int flash_real_protect (flash_info_t * info, long sector, int prot)
{
- cfiptr_t cptr;
- cfiword_t cword;
- int retval;
+ int retcode = 0;
- cptr.cp = flash_make_addr (info, sect, offset);
- flash_make_cmd (info, cmd, &cword);
+ flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
+ if (prot)
+ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
+ else
+ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
- debug ("is= cmd %x(%c) addr %p ", cmd, cmd, cptr.cp);
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- debug ("is= %x %x\n", cptr.cp[0], cword.c);
- retval = (cptr.cp[0] == cword.c);
- break;
- case FLASH_CFI_16BIT:
- debug ("is= %4.4x %4.4x\n", cptr.wp[0], cword.w);
- retval = (cptr.wp[0] == cword.w);
- break;
- case FLASH_CFI_32BIT:
- debug ("is= %8.8lx %8.8lx\n", cptr.lp[0], cword.l);
- retval = (cptr.lp[0] == cword.l);
- break;
- case FLASH_CFI_64BIT:
-#ifdef DEBUG
- {
- char str1[20];
- char str2[20];
+ if ((retcode =
+ flash_full_status_check (info, sector, info->erase_blk_tout,
+ prot ? "protect" : "unprotect")) == 0) {
- print_longlong (str1, cptr.llp[0]);
- print_longlong (str2, cword.ll);
- debug ("is= %s %s\n", str1, str2);
+ info->protect[sector] = prot;
+
+ /*
+ * On some of Intel's flash chips (marked via legacy_unlock)
+ * unprotect unprotects all locking.
+ */
+ if ((prot == 0) && (info->legacy_unlock)) {
+ flash_sect_t i;
+
+ for (i = 0; i < info->sector_count; i++) {
+ if (info->protect[i])
+ flash_real_protect (info, i, 1);
+ }
}
-#endif
- retval = (cptr.llp[0] == cword.ll);
- break;
- default:
- retval = 0;
- break;
}
- return retval;
+ return retcode;
}
/*-----------------------------------------------------------------------
+ * flash_read_user_serial - read the OneTimeProgramming cells
*/
-static int flash_isset (flash_info_t * info, flash_sect_t sect,
- uint offset, uchar cmd)
+void flash_read_user_serial (flash_info_t * info, void *buffer, int offset,
+ int len)
{
- cfiptr_t cptr;
- cfiword_t cword;
- int retval;
+ uchar *src;
+ uchar *dst;
- cptr.cp = flash_make_addr (info, sect, offset);
- flash_make_cmd (info, cmd, &cword);
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- retval = ((cptr.cp[0] & cword.c) == cword.c);
- break;
- case FLASH_CFI_16BIT:
- retval = ((cptr.wp[0] & cword.w) == cword.w);
- break;
- case FLASH_CFI_32BIT:
- retval = ((cptr.lp[0] & cword.l) == cword.l);
- break;
- case FLASH_CFI_64BIT:
- retval = ((cptr.llp[0] & cword.ll) == cword.ll);
- break;
- default:
- retval = 0;
- break;
- }
- return retval;
+ dst = buffer;
+ src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION);
+ flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
+ memcpy (dst, src + offset, len);
+ flash_write_cmd (info, 0, 0, info->cmd_reset);
}
-/*-----------------------------------------------------------------------
+/*
+ * flash_read_factory_serial - read the device Id from the protection area
*/
-static int flash_toggle (flash_info_t * info, flash_sect_t sect,
- uint offset, uchar cmd)
+void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset,
+ int len)
{
- cfiptr_t cptr;
- cfiword_t cword;
- int retval;
+ uchar *src;
- cptr.cp = flash_make_addr (info, sect, offset);
- flash_make_cmd (info, cmd, &cword);
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c));
- break;
- case FLASH_CFI_16BIT:
- retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w));
- break;
- case FLASH_CFI_32BIT:
- retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l));
- break;
- case FLASH_CFI_64BIT:
- retval = ((cptr.llp[0] & cword.ll) !=
- (cptr.llp[0] & cword.ll));
- break;
- default:
- retval = 0;
- break;
- }
- return retval;
+ src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
+ flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
+ memcpy (buffer, src + offset, len);
+ flash_write_cmd (info, 0, 0, info->cmd_reset);
}
+#endif /* CFG_FLASH_PROTECTION */
+
+
/*-----------------------------------------------------------------------
* read jedec ids from device and set corresponding fields in info struct
*
}
}
+#ifdef CONFIG_FLASH_CFI_LEGACY
/*-----------------------------------------------------------------------
- * detect if flash is compatible with the Common Flash Interface (CFI)
- * http://www.jedec.org/download/search/jesd68.pdf
+ * Call board code to request info about non-CFI flash.
+ * board_flash_get_legacy needs to fill in at least:
+ * info->portwidth, info->chipwidth and info->interface for Jedec probing.
*/
-static int __flash_detect_cfi (flash_info_t * info)
+static int flash_detect_legacy(ulong base, int banknum)
{
- int cfi_offset;
+ flash_info_t *info = &flash_info[banknum];
- flash_write_cmd (info, 0, 0, info->cmd_reset);
- for (cfi_offset=0;
- cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint);
- cfi_offset++) {
- flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset],
- FLASH_CMD_CFI);
- if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
- && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
- && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
- info->interface = flash_read_ushort (info, 0,
- FLASH_OFFSET_INTERFACE);
- info->cfi_offset = flash_offset_cfi[cfi_offset];
- debug ("device interface is %d\n",
- info->interface);
- debug ("found port %d chip %d ",
- info->portwidth, info->chipwidth);
- debug ("port %d bits chip %d bits\n",
- info->portwidth << CFI_FLASH_SHIFT_WIDTH,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ if (board_flash_get_legacy(base, banknum, info)) {
+ /* board code may have filled info completely. If not, we
+ use JEDEC ID probing. */
+ if (!info->vendor) {
+ int modes[] = {
+ CFI_CMDSET_AMD_STANDARD,
+ CFI_CMDSET_INTEL_STANDARD
+ };
+ int i;
- /* calculate command offsets as in the Linux driver */
- info->addr_unlock1 = 0x555;
+ for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
+ info->vendor = modes[i];
+ info->start[0] = base;
+ if (info->portwidth == FLASH_CFI_8BIT
+ && info->interface == FLASH_CFI_X8X16) {
+ info->addr_unlock1 = 0x2AAA;
+ info->addr_unlock2 = 0x5555;
+ } else {
+ info->addr_unlock1 = 0x5555;
+ info->addr_unlock2 = 0x2AAA;
+ }
+ flash_read_jedec_ids(info);
+ debug("JEDEC PROBE: ID %x %x %x\n",
+ info->manufacturer_id,
+ info->device_id,
+ info->device_id2);
+ if (jedec_flash_match(info, base))
+ break;
+ }
+ }
+
+ switch(info->vendor) {
+ case CFI_CMDSET_INTEL_STANDARD:
+ case CFI_CMDSET_INTEL_EXTENDED:
+ info->cmd_reset = FLASH_CMD_RESET;
+ break;
+ case CFI_CMDSET_AMD_STANDARD:
+ case CFI_CMDSET_AMD_EXTENDED:
+ case CFI_CMDSET_AMD_LEGACY:
+ info->cmd_reset = AMD_CMD_RESET;
+ break;
+ }
+ info->flash_id = FLASH_MAN_CFI;
+ return 1;
+ }
+ return 0; /* use CFI */
+}
+#else
+static inline int flash_detect_legacy(ulong base, int banknum)
+{
+ return 0; /* use CFI */
+}
+#endif
+
+/*-----------------------------------------------------------------------
+ * detect if flash is compatible with the Common Flash Interface (CFI)
+ * http://www.jedec.org/download/search/jesd68.pdf
+ */
+static int __flash_detect_cfi (flash_info_t * info)
+{
+ int cfi_offset;
+
+ flash_write_cmd (info, 0, 0, info->cmd_reset);
+ for (cfi_offset=0;
+ cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint);
+ cfi_offset++) {
+ flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset],
+ FLASH_CMD_CFI);
+ if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
+ && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
+ && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
+ info->interface = flash_read_ushort (info, 0,
+ FLASH_OFFSET_INTERFACE);
+ info->cfi_offset = flash_offset_cfi[cfi_offset];
+ debug ("device interface is %d\n",
+ info->interface);
+ debug ("found port %d chip %d ",
+ info->portwidth, info->chipwidth);
+ debug ("port %d bits chip %d bits\n",
+ info->portwidth << CFI_FLASH_SHIFT_WIDTH,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+
+ /* calculate command offsets as in the Linux driver */
+ info->addr_unlock1 = 0x555;
info->addr_unlock2 = 0x2aa;
/*
return (info->size);
}
-/* loop through the sectors from the highest address when the passed
- * address is greater or equal to the sector address we have a match
- */
-static flash_sect_t find_sector (flash_info_t * info, ulong addr)
-{
- flash_sect_t sector;
-
- for (sector = info->sector_count - 1; sector >= 0; sector--) {
- if (addr >= info->start[sector])
- break;
- }
- return sector;
-}
-
/*-----------------------------------------------------------------------
*/
-static int flash_write_cfiword (flash_info_t * info, ulong dest,
- cfiword_t cword)
+unsigned long flash_init (void)
{
- cfiptr_t ctladdr;
- cfiptr_t cptr;
- int flag;
-
- ctladdr.cp = flash_make_addr (info, 0, 0);
- cptr.cp = (uchar *) dest;
-
- /* Check if Flash is (sufficiently) erased */
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- flag = ((cptr.cp[0] & cword.c) == cword.c);
- break;
- case FLASH_CFI_16BIT:
- flag = ((cptr.wp[0] & cword.w) == cword.w);
- break;
- case FLASH_CFI_32BIT:
- flag = ((cptr.lp[0] & cword.l) == cword.l);
- break;
- case FLASH_CFI_64BIT:
- flag = ((cptr.llp[0] & cword.ll) == cword.ll);
- break;
- default:
- return 2;
- }
- if (!flag)
- return 2;
-
- /* Disable interrupts which might cause a timeout here */
- flag = disable_interrupts ();
+ unsigned long size = 0;
+ int i;
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_EXTENDED:
- case CFI_CMDSET_INTEL_STANDARD:
- flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE);
- break;
- case CFI_CMDSET_AMD_EXTENDED:
- case CFI_CMDSET_AMD_STANDARD:
-#ifdef CONFIG_FLASH_CFI_LEGACY
- case CFI_CMDSET_AMD_LEGACY:
+#ifdef CFG_FLASH_PROTECTION
+ char *s = getenv("unlock");
#endif
- flash_unlock_seq (info, 0);
- flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_WRITE);
- break;
- }
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- cptr.cp[0] = cword.c;
- break;
- case FLASH_CFI_16BIT:
- cptr.wp[0] = cword.w;
- break;
- case FLASH_CFI_32BIT:
- cptr.lp[0] = cword.l;
- break;
- case FLASH_CFI_64BIT:
- cptr.llp[0] = cword.ll;
- break;
- }
+ /* Init: no FLASHes known */
+ for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
- /* re-enable interrupts if necessary */
- if (flag)
- enable_interrupts ();
+ if (!flash_detect_legacy (bank_base[i], i))
+ flash_get_size (bank_base[i], i);
+ size += flash_info[i].size;
+ if (flash_info[i].flash_id == FLASH_UNKNOWN) {
+#ifndef CFG_FLASH_QUIET_TEST
+ printf ("## Unknown FLASH on Bank %d "
+ "- Size = 0x%08lx = %ld MB\n",
+ i+1, flash_info[i].size,
+ flash_info[i].size << 20);
+#endif /* CFG_FLASH_QUIET_TEST */
+ }
+#ifdef CFG_FLASH_PROTECTION
+ else if ((s != NULL) && (strcmp(s, "yes") == 0)) {
+ /*
+ * Only the U-Boot image and it's environment
+ * is protected, all other sectors are
+ * unprotected (unlocked) if flash hardware
+ * protection is used (CFG_FLASH_PROTECTION)
+ * and the environment variable "unlock" is
+ * set to "yes".
+ */
+ if (flash_info[i].legacy_unlock) {
+ int k;
- return flash_full_status_check (info, find_sector (info, dest),
- info->write_tout, "write");
-}
+ /*
+ * Disable legacy_unlock temporarily,
+ * since flash_real_protect would
+ * relock all other sectors again
+ * otherwise.
+ */
+ flash_info[i].legacy_unlock = 0;
-#ifdef CFG_FLASH_USE_BUFFER_WRITE
+ /*
+ * Legacy unlocking (e.g. Intel J3) ->
+ * unlock only one sector. This will
+ * unlock all sectors.
+ */
+ flash_real_protect (&flash_info[i], 0, 0);
-static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
- int len)
-{
- flash_sect_t sector;
- int cnt;
- int retcode;
- volatile cfiptr_t src;
- volatile cfiptr_t dst;
+ flash_info[i].legacy_unlock = 1;
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_STANDARD:
- case CFI_CMDSET_INTEL_EXTENDED:
- src.cp = cp;
- dst.cp = (uchar *) dest;
- sector = find_sector (info, dest);
- flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
- retcode = flash_status_check (info, sector,
- info->buffer_write_tout,
- "write to buffer");
- if (retcode == ERR_OK) {
- /* reduce the number of loops by the width of
- * the port */
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- cnt = len;
- break;
- case FLASH_CFI_16BIT:
- cnt = len >> 1;
- break;
- case FLASH_CFI_32BIT:
- cnt = len >> 2;
- break;
- case FLASH_CFI_64BIT:
- cnt = len >> 3;
- break;
- default:
- return ERR_INVAL;
- break;
- }
- flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) {
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- *dst.cp++ = *src.cp++;
- break;
- case FLASH_CFI_16BIT:
- *dst.wp++ = *src.wp++;
- break;
- case FLASH_CFI_32BIT:
- *dst.lp++ = *src.lp++;
- break;
- case FLASH_CFI_64BIT:
- *dst.llp++ = *src.llp++;
- break;
- default:
- return ERR_INVAL;
- break;
- }
+ /*
+ * Manually mark other sectors as
+ * unlocked (unprotected)
+ */
+ for (k = 1; k < flash_info[i].sector_count; k++)
+ flash_info[i].protect[k] = 0;
+ } else {
+ /*
+ * No legancy unlocking -> unlock all sectors
+ */
+ flash_protect (FLAG_PROTECT_CLEAR,
+ flash_info[i].start[0],
+ flash_info[i].start[0]
+ + flash_info[i].size - 1,
+ &flash_info[i]);
}
- flash_write_cmd (info, sector, 0,
- FLASH_CMD_WRITE_BUFFER_CONFIRM);
- retcode = flash_full_status_check (
- info, sector, info->buffer_write_tout,
- "buffer write");
}
- return retcode;
-
- case CFI_CMDSET_AMD_STANDARD:
- case CFI_CMDSET_AMD_EXTENDED:
- src.cp = cp;
- dst.cp = (uchar *) dest;
- sector = find_sector (info, dest);
-
- flash_unlock_seq(info,0);
- flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER);
+#endif /* CFG_FLASH_PROTECTION */
+ }
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- cnt = len;
- flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.cp++ = *src.cp++;
- break;
- case FLASH_CFI_16BIT:
- cnt = len >> 1;
- flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.wp++ = *src.wp++;
- break;
- case FLASH_CFI_32BIT:
- cnt = len >> 2;
- flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.lp++ = *src.lp++;
- break;
- case FLASH_CFI_64BIT:
- cnt = len >> 3;
- flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.llp++ = *src.llp++;
- break;
- default:
- return ERR_INVAL;
- }
+ /* Monitor protection ON by default */
+#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
+ flash_protect (FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE + monitor_flash_len - 1,
+ flash_get_info(CFG_MONITOR_BASE));
+#endif
- flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
- retcode = flash_full_status_check (info, sector,
- info->buffer_write_tout,
- "buffer write");
- return retcode;
+ /* Environment protection ON by default */
+#ifdef CFG_ENV_IS_IN_FLASH
+ flash_protect (FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
+ flash_get_info(CFG_ENV_ADDR));
+#endif
- default:
- debug ("Unknown Command Set\n");
- return ERR_INVAL;
- }
+ /* Redundant environment protection ON by default */
+#ifdef CFG_ENV_ADDR_REDUND
+ flash_protect (FLAG_PROTECT_SET,
+ CFG_ENV_ADDR_REDUND,
+ CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
+ flash_get_info(CFG_ENV_ADDR_REDUND));
+#endif
+ return (size);
}
-#endif /* CFG_FLASH_USE_BUFFER_WRITE */
#endif /* CFG_FLASH_CFI */