
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@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; }