Nor Flash支持SST39VF1601)
mini2440的配置文件include/configs/mini2440.h中對flash的設置為:
#define CONFIG_SYS_FLASH_CFI
#define CONFIG_FLASH_CFI_DRIVER
#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_16BIT
CFI接口的flash驅動cfi_flash.c中,讀取“QRY”的過程並不支持SST39VF1601,
SST37VF1601進入CFI QRY query模式要多兩步,參照linux內核
修改如下:
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
old mode 100644
new mode 100755
index 25a5710..930395b
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -64,7 +64,7 @@
* reading and writing ... (yes there is such a Hardware).
*/
-static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT };
+//static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT };
#ifdef CONFIG_FLASH_CFI_MTD
static uint flash_verbose = 1;
#else
@@ -546,6 +546,7 @@ static int flash_is_busy (flash_info_t * info, flash_sect_t sect)
break;
case CFI_CMDSET_AMD_STANDARD:
case CFI_CMDSET_AMD_EXTENDED:
+ case CFI_CMDSET_SST_OLD:
#ifdef CONFIG_FLASH_CFI_LEGACY
case CFI_CMDSET_AMD_LEGACY:
#endif
@@ -823,14 +824,15 @@ static int flash_write_cfiword (flash_info_t * info, ulong dest,
flash_write_cmd (info, sect, info->addr_unlock1, AMD_CMD_WRITE);
sect_found = 1;
break;
+ case CFI_CMDSET_SST_OLD:
#ifdef CONFIG_FLASH_CFI_LEGACY
case CFI_CMDSET_AMD_LEGACY:
+#endif
sect = find_sector(info, dest);
flash_unlock_seq (info, 0);
flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_WRITE);
sect_found = 1;
break;
-#endif
}
switch (info->portwidth) {
@@ -1133,6 +1135,9 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)
break;
#ifdef CONFIG_FLASH_CFI_LEGACY
case CFI_CMDSET_AMD_LEGACY:
+#endif
+ case CFI_CMDSET_SST_OLD:
+
flash_unlock_seq (info, 0);
flash_write_cmd (info, 0, info->addr_unlock1,
AMD_CMD_ERASE_START);
@@ -1140,7 +1145,7 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)
flash_write_cmd (info, sect, 0,
AMD_CMD_ERASE_SECTOR);
break;
-#endif
+
default:
debug ("Unkown flash vendor %d\n",
info->vendor);
@@ -1876,25 +1881,80 @@ static void __flash_cmd_reset(flash_info_t *info)
void flash_cmd_reset(flash_info_t *info)
__attribute__((weak,alias("__flash_cmd_reset")));
+
+static int __cfi_qry_present(flash_info_t * info)
+{
+ 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'))
+ return 1;
+ return 0;
+
+}
+static int __cfi_qry_mode_on(flash_info_t * info)
+{
+ flash_write_cmd(info, 0, 0, AMD_CMD_RESET);//0xf0
+ flash_write_cmd (info, 0, 0x55, FLASH_CMD_CFI);//0x98
+ if( __cfi_qry_present(info))
+ {
+ info->cfi_offset = 0x55;
+ return 1;
+ }
+
+ flash_write_cmd(info, 0, 0, AMD_CMD_RESET);//0xf0
+ flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);//0xff
+ flash_write_cmd (info, 0, 0x55, FLASH_CMD_CFI);
+ if( __cfi_qry_present(info))
+ {
+ info->cfi_offset = 0x55;
+ return 1;
+ }
+
+ flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+ flash_write_cmd (info, 0, 0x555, FLASH_CMD_CFI);
+ if( __cfi_qry_present(info))
+ {
+ info->cfi_offset = 0x555;
+ return 1;
+ }
+
+ flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+ flash_write_cmd (info, 0, 0x5555, 0xaa);
+ flash_write_cmd (info, 0, 0x2aaa, 0x55);
+ flash_write_cmd (info, 0, 0x5555, FLASH_CMD_CFI);
+ if( __cfi_qry_present(info))
+ {
+ info->cfi_offset = 0x5555;
+ return 1;
+ }
+
+ flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+ flash_write_cmd (info, 0, 0x555, 0xAA);
+ flash_write_cmd (info, 0, 0x2AA, 0x55);
+ flash_write_cmd (info, 0, 0x555, FLASH_CMD_CFI);
+ if( __cfi_qry_present(info))
+ {
+ info->cfi_offset = 0x555;
+ return 1;
+ }
+ //QRY not found
+ return 0;
+}
+
static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
{
- int cfi_offset;
+ //int cfi_offset;
/* Issue FLASH reset command */
- flash_cmd_reset(info);
-
- for (cfi_offset = 0; cfi_offset < ARRAY_SIZE(flash_offset_cfi);
- 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')) {
+ //flash_cmd_reset(info);
+
+ //for (cfi_offset = 0; cfi_offset < ARRAY_SIZE(flash_offset_cfi);
+ // cfi_offset++) {
+ if(__cfi_qry_mode_on(info)) {
flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
sizeof(struct cfi_qry));
info->interface = le16_to_cpu(qry->interface_desc);
- info->cfi_offset = flash_offset_cfi[cfi_offset];
debug ("device interface is %d\n",
info->interface);
debug ("found port %d chip %d ",
@@ -1921,15 +1981,21 @@ static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
info->addr_unlock1 = 0xaaa;
info->addr_unlock2 = 0x555;
}
-
+ //for SST
+ if(le16_to_cpu(get_unaligned(&qry->p_id)) == CFI_CMDSET_SST_OLD)
+ {
+ info->addr_unlock1 = 0x5555;
+ info->addr_unlock2 = 0x2AAA;
+ }
info->name = "CFI conformant";
return 1;
- }
}
return 0;
}
+
+
static int flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
{
debug ("flash detect cfi\n");
@@ -1938,7 +2004,7 @@ static int flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
for (info->chipwidth = FLASH_CFI_BY8;
info->chipwidth <= info->portwidth;
- info->chipwidth <<= 1)
+ info->chipwidth <<= 1)
if (__flash_detect_cfi(info, qry))
return 1;
}
@@ -2097,6 +2163,7 @@ ulong flash_get_size (phys_addr_t base, int banknum)
break;
case CFI_CMDSET_AMD_STANDARD:
case CFI_CMDSET_AMD_EXTENDED:
+ case CFI_CMDSET_SST_OLD:
cmdset_amd_init(info, &qry);
break;
default:
diff --git a/include/mtd/cfi_flash.h b/include/mtd/cfi_flash.h
old mode 100644
new mode 100755
index b644b91..0456877
--- a/include/mtd/cfi_flash.h
+++ b/include/mtd/cfi_flash.h
@@ -112,6 +112,7 @@
#define CFI_CMDSET_MITSU_STANDARD 256
#define CFI_CMDSET_MITSU_EXTENDED 257
#define CFI_CMDSET_SST 258
+#define CFI_CMDSET_SST_OLD 0x701
#define CFI_CMDSET_INTEL_PROG_REGIONS 512
#ifdef CONFIG_SYS_FLASH_CFI_AMD_RESET /* needed for STM_ID_29W320DB on UC100 */
本文出自 “一地在要工上是中國同” 博客,請務必保留此出處http://gfdsahjklm.blog.51cto.com/7806691/1282529