diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c index 6d22a53..2fa2c6b 100644 --- a/drivers/nor/cfi_flash.c +++ b/drivers/nor/cfi_flash.c @@ -314,7 +314,6 @@ uchar num_erase_regions; int erase_region_size; int erase_region_count; - int geometry_reversed = 0; int cur_offset = 0; struct cfi_qry qry; @@ -368,38 +367,7 @@ info->cfi_cmd_set->flash_read_jedec_ids (info); flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI); - switch (info->vendor) { - case CFI_CMDSET_INTEL_STANDARD: - case CFI_CMDSET_INTEL_EXTENDED: - default: -#ifdef CFG_FLASH_PROTECTION - /* read legacy lock/unlock bit from intel flash */ - if (info->ext_addr) { - info->legacy_unlock = flash_read_uchar (info, - info->ext_addr + 5) & 0x08; - } -#endif - break; - case CFI_CMDSET_AMD_STANDARD: - case CFI_CMDSET_AMD_EXTENDED: - /* check if flash geometry needs reversal */ - if (num_erase_regions <= 1) - break; - /* reverse geometry if top boot part */ - if (info->cfi_version < 0x3131) { - /* CFI < 1.1, try to guess from device id */ - if ((info->device_id & 0x80) != 0) { - geometry_reversed = 1; - } - break; - } - /* CFI >= 1.1, deduct from top/bottom flag */ - /* note: ext_addr is valid since cfi_version > 0 */ - if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) { - geometry_reversed = 1; - } - break; - } + info->cfi_cmd_set->flash_fixup (info, &qry); debug ("manufacturer is %d\n", info->vendor); debug ("manufacturer id is 0x%x\n", info->manufacturer_id); @@ -423,7 +391,6 @@ sector = base; for (i = 0; i < num_erase_regions; i++) { - unsigned int __region = i; struct mtd_erase_region_info *region = &info->eraseregions[i]; if (i > NUM_ERASE_REGIONS) { @@ -431,11 +398,9 @@ num_erase_regions, NUM_ERASE_REGIONS); break; } - if (geometry_reversed) - __region = num_erase_regions - 1 - i; - - tmp = le32_to_cpu(qry.erase_region_info[__region]); - debug("erase region %u: 0x%08lx\n", __region, tmp); + + tmp = le32_to_cpu(qry.erase_region_info[i]); + debug("erase region %u: 0x%08lx\n", i, tmp); erase_region_count = (tmp & 0xffff) + 1; tmp >>= 16; diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h index bbeb377..f9023dc 100644 --- a/drivers/nor/cfi_flash.h +++ b/drivers/nor/cfi_flash.h @@ -114,6 +114,7 @@ void (*flash_prepare_write) (struct flash_info *info); int (*flash_status_check) (struct flash_info *info, flash_sect_t sector, uint64_t tout, char *prompt); int (*flash_real_protect) (struct flash_info *info, long sector, int prot); + void (*flash_fixup) (struct flash_info *info, struct cfi_qry *qry); }; extern struct cfi_cmd_set cfi_cmd_set_intel; diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c index f225757..b50de22 100644 --- a/drivers/nor/cfi_flash_amd.c +++ b/drivers/nor/cfi_flash_amd.c @@ -2,6 +2,23 @@ #include #include "cfi_flash.h" +/*----------------------------------------------------------------------- + * Reverse the order of the erase regions in the CFI QRY structure. + * This is needed for chips that are either a) correctly detected as + * top-boot, or b) buggy. + */ +static void cfi_reverse_geometry(struct cfi_qry *qry) +{ + unsigned int i, j; + u32 tmp; + + for (i = 0, j = qry->num_erase_regions - 1; i < j; i++, j--) { + tmp = qry->erase_region_info[i]; + qry->erase_region_info[i] = qry->erase_region_info[j]; + qry->erase_region_info[j] = tmp; + } +} + static void flash_unlock_seq (struct flash_info *info) { flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_UNLOCK_START); @@ -184,6 +201,23 @@ return 0; } +static void amd_flash_fixup (struct flash_info *info, struct cfi_qry *qry) +{ + /* check if flash geometry needs reversal */ + if (qry->num_erase_regions > 1) { + /* reverse geometry if top boot part */ + if (info->cfi_version < 0x3131) { + /* CFI < 1.1, try to guess from device id */ + if ((info->device_id & 0x80) != 0) + cfi_reverse_geometry(qry); + } else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) { + /* CFI >= 1.1, deduct from top/bottom flag */ + /* note: ext_addr is valid since cfi_version > 0 */ + cfi_reverse_geometry(qry); + } + } +} + struct cfi_cmd_set cfi_cmd_set_amd = { .flash_write_cfibuffer = amd_flash_write_cfibuffer, .flash_erase_one = amd_flash_erase_one, @@ -192,5 +226,6 @@ .flash_prepare_write = amd_flash_prepare_write, .flash_status_check = flash_generic_status_check, .flash_real_protect = amd_flash_real_protect, + .flash_fixup = amd_flash_fixup, }; diff --git a/drivers/nor/cfi_flash_intel.c b/drivers/nor/cfi_flash_intel.c index 8e8a820..c3cbad5 100644 --- a/drivers/nor/cfi_flash_intel.c +++ b/drivers/nor/cfi_flash_intel.c @@ -141,6 +141,17 @@ return 0; } +static void intel_flash_fixup (struct flash_info *info, struct cfi_qry *qry) +{ +#ifdef CFG_FLASH_PROTECTION + /* read legacy lock/unlock bit from intel flash */ + if (info->ext_addr) { + info->legacy_unlock = flash_read_uchar (info, + info->ext_addr + 5) & 0x08; + } +#endif +} + struct cfi_cmd_set cfi_cmd_set_intel = { .flash_write_cfibuffer = intel_flash_write_cfibuffer, .flash_erase_one = intel_flash_erase_one, @@ -149,5 +160,6 @@ .flash_prepare_write = intel_flash_prepare_write, .flash_status_check = intel_flash_status_check, .flash_real_protect = intel_flash_real_protect, + .flash_fixup = intel_flash_fixup, };