#include <common.h>
#include <asm/processor.h>
+#include <asm/io.h>
#include <asm/byteorder.h>
#include <environment.h>
#ifdef CFG_FLASH_CFI_DRIVER
* AMD/Spansion Application Note: Migration from Single-byte to Three-byte
* Device IDs, Publication Number 25538 Revision A, November 8, 2001
*
+ * define CFG_WRITE_SWAPPED_DATA, if you have to swap the Bytes between
+ * reading and writing ... (yes there is such a Hardware).
*/
#ifndef CFG_FLASH_BANKS_LIST
#define FLASH_OFFSET_DEVICE_ID2 0x0E
#define FLASH_OFFSET_DEVICE_ID3 0x0F
#define FLASH_OFFSET_CFI 0x55
+#define FLASH_OFFSET_CFI_ALT 0x555
#define FLASH_OFFSET_CFI_RESP 0x10
#define FLASH_OFFSET_PRIMARY_VENDOR 0x13
#define FLASH_OFFSET_EXT_QUERY_T_P_ADDR 0x15 /* extended query table primary addr */
#define NUM_ERASE_REGIONS 4 /* max. number of erase regions */
+static uint flash_offset_cfi[2]={FLASH_OFFSET_CFI,FLASH_OFFSET_CFI_ALT};
+
/* use CFG_MAX_FLASH_BANKS_DETECT if defined */
#ifdef CFG_MAX_FLASH_BANKS_DETECT
static ulong bank_base[CFG_MAX_FLASH_BANKS_DETECT] = CFG_FLASH_BANKS_LIST;
uchar *cp;
cp = flash_make_addr (info, 0, offset);
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
return (cp[0]);
#else
return (cp[info->portwidth - 1]);
debug ("addr[%x] = 0x%x\n", x, addr[x]);
}
#endif
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
retval = ((addr[(info->portwidth)] << 8) | addr[0]);
#else
retval = ((addr[(2 * info->portwidth) - 1] << 8) |
debug ("addr[%x] = 0x%x\n", x, addr[x]);
}
#endif
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) |
(addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8);
#else
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, flash_info[i].size, flash_info[i].size << 20);
+ i+1, flash_info[i].size, flash_info[i].size << 20);
#endif /* CFG_FLASH_QUIET_TEST */
}
#ifdef CFG_FLASH_PROTECTION
*/
static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
{
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
unsigned short w;
unsigned int l;
unsigned long long ll;
cword->c = c;
break;
case FLASH_CFI_16BIT:
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
w = c;
w <<= 8;
cword->w = (cword->w >> 8) | w;
#endif
break;
case FLASH_CFI_32BIT:
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
l = c;
l <<= 24;
cword->l = (cword->l >> 8) | l;
#endif
break;
case FLASH_CFI_64BIT:
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
ll = c;
ll <<= 56;
cword->ll = (cword->ll >> 8) | ll;
int i;
uchar *cp = (uchar *) cmdbuf;
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
for (i = info->portwidth; i > 0; i--)
#else
for (i = 1; i <= info->portwidth; i++)
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;
-#ifdef CONFIG_BLACKFIN
- asm("ssync;");
-#endif
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;
-#ifdef CONFIG_BLACKFIN
- asm("ssync;");
-#endif
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;
-#ifdef CONFIG_BLACKFIN
- asm("ssync;");
-#endif
break;
case FLASH_CFI_64BIT:
#ifdef DEBUG
}
#endif
*addr.llp = cword.ll;
-#ifdef CONFIG_BLACKFIN
- asm("ssync;");
-#endif
break;
}
+
+ /* Ensure all the instructions are fully finished */
+ sync();
}
static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
*/
static int flash_detect_cfi (flash_info_t * info)
{
+ int cfi_offset;
debug ("flash detect cfi\n");
for (info->portwidth = CFG_FLASH_CFI_WIDTH;
info->chipwidth <= info->portwidth;
info->chipwidth <<= 1) {
flash_write_cmd (info, 0, 0, info->cmd_reset);
- flash_write_cmd (info, 0, FLASH_OFFSET_CFI, 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);
- 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);
- return 1;
+ 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);
+ return 1;
+ }
}
}
}
info->vendor = flash_read_ushort (info, 0,
FLASH_OFFSET_PRIMARY_VENDOR);
flash_read_jedec_ids (info);
- flash_write_cmd (info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI);
+ flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI);
num_erase_regions = flash_read_uchar (info,
FLASH_OFFSET_NUM_ERASE_REGIONS);
info->ext_addr = flash_read_ushort (info, 0,
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:
}
}
#endif /* CFG_FLASH_USE_BUFFER_WRITE */
+
#endif /* CFG_FLASH_CFI */