[U-Boot-Users] Mixing CFI and non-CFI flashs?

Michael Schwingen rincewind at discworld.dascon.de
Sat Nov 3 16:00:56 CET 2007


On Sat, Nov 03, 2007 at 08:13:40AM +0100, Stefan Roese wrote:
> I remember a discussion we had a while ago, about supporting non-CFI chips in 
> a common driver, but I can't find the mails right now. IIRC, the idea was to 
> add something close to the Linux JEDEC probe 
> (drivers/mtd/chips/jedec_probe.c) for this.

Good idea. I currently hard-coded the flash parameters for the boot flash,
since I know there is exactly one type on the boards, but having
jedec-probing would be nicer.

I think the CFI driver is a good start as a framework - all the
infrastructure for handling mutliple banks, different chip/bus mappings etc.
is there and could be used by jedec-flash code. For now, it is probably
easiest to add the JEDEC code to cfi_flash.c, to get access to the static
functions defined there, and then later split it out if necessary.

> I suggest that you post your current version for review. This sounds like a 
> start in the correct direction.

Fine. Here is what I have got now - it works for my board, but would
probably need some cleanup/renaming of symbols. The basic idea is that the
board-specific code provides a function "flash_detect_legacy" that is called
for every flash bank, which can provide hardcoded (or in the future
jedec-probed) flash information. If the function returns 0, the normal CFI
code is called.

Since that code is board-specific anyway, I think the board-specific code
can supply the information about chipwidth, buswidth etc. - there is no real
benefit in autoprobing these, and there is less probability for problems
(like 8-bit accesses to a 16-bit bus causing problems, etc.).


I have included one non-conditional patch I made:
@@ -1282,6 +1310,8 @@ ulong flash_get_size (ulong base, int banknum)
which causes the CFI code to stop in case CFG_MAX_FLASH_SECT is defined too
small - without that patch, u-boot overwrites other data and crashes
silently during startup. 

cu
Michael

Signed-off-by: Michael Schwingen <michael at schwingen.org>

diff --git a/include/flash.h b/include/flash.h
index b0bf733..f0ef6f7 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -101,6 +101,11 @@ extern void flash_read_user_serial(flash_info_t * info,
void * buffer, int offse
 extern void flash_read_factory_serial(flash_info_t * info, void * buffer,
int offset, int len);
 #endif /* CFG_FLASH_PROTECTION */
 
+#ifdef CFG_FLASH_CFI_LEGACY
+extern ulong flash_detect_legacy(ulong base, int banknum);
+#define CFI_CMDSET_AMD_LEGACY          0xFFF0
+#endif
+
 /*-----------------------------------------------------------------------
  * return codes from flash_write():
  */


diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c
index 5579a1e..20ccc3a 100644
--- a/drivers/cfi_flash.c
+++ b/drivers/cfi_flash.c
@@ -345,7 +345,13 @@ unsigned long flash_init (void)
 	/* Init: no FLASHes known */
 	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
 		flash_info[i].flash_id = FLASH_UNKNOWN;
-		size += flash_info[i].size = flash_get_size (bank_base[i], i);
+
+#ifdef CFG_FLASH_CFI_LEGACY
+		flash_info[i].size = flash_detect_legacy (bank_base[i], i);
+		if (flash_info[i].size == 0)
+#endif
+		flash_info[i].size = 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",
@@ -488,6 +494,16 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)
 				flash_unlock_seq (info, sect);
 				flash_write_cmd (info, sect, 0, AMD_CMD_ERASE_SECTOR);
 				break;
+#ifdef CFG_FLASH_CFI_LEGACY
+			case CFI_CMDSET_AMD_LEGACY:
+				flash_write_cmd (info, 0,    0x5555, AMD_CMD_UNLOCK_START);
+				flash_write_cmd (info, 0,    0x2AAA, AMD_CMD_UNLOCK_ACK);
+				flash_write_cmd (info, 0,    0x5555, AMD_CMD_ERASE_START);
+				flash_write_cmd (info, 0,    0x5555, AMD_CMD_UNLOCK_START);
+				flash_write_cmd (info, 0,    0x2AAA, AMD_CMD_UNLOCK_ACK);
+				flash_write_cmd (info, sect, 0,      AMD_CMD_ERASE_SECTOR);
+				break;
+#endif
 			default:
 				debug ("Unkown flash vendor %d\n",
 				       info->vendor);
@@ -518,8 +534,12 @@ void flash_print_info (flash_info_t * info)
 
 	printf ("CFI conformant FLASH (%d x %d)",
 		(info->portwidth << 3), (info->chipwidth << 3));
-	printf ("  Size: %ld MB in %d Sectors\n",
-		info->size >> 20, info->sector_count);
+	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:
@@ -534,6 +554,11 @@ void flash_print_info (flash_info_t * info)
 		case CFI_CMDSET_AMD_EXTENDED:
 			printf ("AMD Extended");
 			break;
+#ifdef CFG_FLASH_CFI_LEGACY
+		case CFI_CMDSET_AMD_LEGACY:
+			printf ("AMD (non-CFI)");
+			break;
+#endif
 		default:
 			printf ("Unknown (%d)", info->vendor);
 			break;
@@ -777,6 +802,9 @@ static int flash_is_busy (flash_info_t * info, flash_sect_t sect)
 		break;
 	case CFI_CMDSET_AMD_STANDARD:
 	case CFI_CMDSET_AMD_EXTENDED:
+#ifdef CFG_FLASH_CFI_LEGACY
+	case CFI_CMDSET_AMD_LEGACY:
+#endif
 		retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
 		break;
 	default:
@@ -1282,6 +1310,8 @@ ulong flash_get_size (ulong base, int banknum)
 			debug ("erase_region_count = %d erase_region_size = %d\n",
 				erase_region_count, erase_region_size);
 			for (j = 0; j < erase_region_count; j++) {
+				if (sect_cnt >= CFG_MAX_FLASH_SECT)
+					break;
 				info->start[sect_cnt] = sector;
 				sector += (erase_region_size * size_ratio);
 
@@ -1387,6 +1417,12 @@ static int flash_write_cfiword (flash_info_t * info, ulong dest,
 		flash_unlock_seq (info, 0);
 		flash_write_cmd (info, 0, AMD_ADDR_START, AMD_CMD_WRITE);
 		break;
+#ifdef CFG_FLASH_CFI_LEGACY
+	case CFI_CMDSET_AMD_LEGACY:
+		flash_write_cmd (info, 0, 0x5555, AMD_CMD_UNLOCK_START);
+		flash_write_cmd (info, 0, 0x2AAA, AMD_CMD_UNLOCK_ACK);
+		flash_write_cmd (info, 0, 0x5555, AMD_CMD_WRITE);
+#endif
 	}
 
 	switch (info->portwidth) {





and then in the board-init code:

extern flash_info_t flash_info[];
#define AMD_CMD_RESET			0xF0

ulong flash_detect_legacy(ulong base, int banknum)
{
	if (banknum == 0) {
		flash_info_t *info = &flash_info[banknum];
		int i;
		unsigned long sector;

		info->portwidth = 1;
		info->chipwidth = 1;
		info->ext_addr = 0;
		info->cfi_version = 0;
		info->legacy_unlock = 0;
		info->start[0] = base;
		info->cmd_reset = AMD_CMD_RESET;
		info->vendor = CFI_CMDSET_AMD_LEGACY;
		info->flash_id = FLASH_MAN_CFI;

		info->sector_count = 64;

		for (i = 0, sector = base; i < info->sector_count; i++) {
			info->protect[i] = 0;
			info->start[i] = sector;
			sector += 4096;
		}

		info->buffer_size = 1;
		info->erase_blk_tout = 10000;
		info->buffer_write_tout = 1000;
		info->write_tout = 100;
		return 256*1024;
	}
	else
		return 0;
}




More information about the U-Boot mailing list