#endif /* CFG_FLASH_PROTECTION */
 
+/*-----------------------------------------------------------------------
+ * 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;
+       }
+}
 
 /*-----------------------------------------------------------------------
  * read jedec ids from device and set corresponding fields in info struct
  *
  * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct
  *
-*/
+ */
+static void cmdset_intel_read_jedec_ids(flash_info_t *info)
+{
+       flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+       flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
+       udelay(1000); /* some flash are slow to respond */
+       info->manufacturer_id = flash_read_uchar (info,
+                                       FLASH_OFFSET_MANUFACTURER_ID);
+       info->device_id = flash_read_uchar (info,
+                                       FLASH_OFFSET_DEVICE_ID);
+       flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+}
+
+static int cmdset_intel_init(flash_info_t *info, struct cfi_qry *qry)
+{
+       info->cmd_reset = FLASH_CMD_RESET;
+
+       cmdset_intel_read_jedec_ids(info);
+       flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
+
+#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
+
+       return 0;
+}
+
+static void cmdset_amd_read_jedec_ids(flash_info_t *info)
+{
+       flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+       flash_unlock_seq(info, 0);
+       flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID);
+       udelay(1000); /* some flash are slow to respond */
+       info->manufacturer_id = flash_read_uchar (info,
+                                       FLASH_OFFSET_MANUFACTURER_ID);
+       info->device_id = flash_read_uchar (info,
+                                       FLASH_OFFSET_DEVICE_ID);
+       if (info->device_id == 0x7E) {
+               /* AMD 3-byte (expanded) device ids */
+               info->device_id2 = flash_read_uchar (info,
+                                       FLASH_OFFSET_DEVICE_ID2);
+               info->device_id2 <<= 8;
+               info->device_id2 |= flash_read_uchar (info,
+                                       FLASH_OFFSET_DEVICE_ID3);
+       }
+       flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+}
+
+static int cmdset_amd_init(flash_info_t *info, struct cfi_qry *qry)
+{
+       info->cmd_reset = AMD_CMD_RESET;
+
+       cmdset_amd_read_jedec_ids(info);
+       flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
+
+       /* 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);
+               }
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_FLASH_CFI_LEGACY
 static void flash_read_jedec_ids (flash_info_t * info)
 {
        info->manufacturer_id = 0;
        switch (info->vendor) {
        case CFI_CMDSET_INTEL_STANDARD:
        case CFI_CMDSET_INTEL_EXTENDED:
-               flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
-               flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
-               udelay(1000); /* some flash are slow to respond */
-               info->manufacturer_id = flash_read_uchar (info,
-                                               FLASH_OFFSET_MANUFACTURER_ID);
-               info->device_id = flash_read_uchar (info,
-                                               FLASH_OFFSET_DEVICE_ID);
-               flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+               flash_read_jedec_ids_intel(info);
                break;
        case CFI_CMDSET_AMD_STANDARD:
        case CFI_CMDSET_AMD_EXTENDED:
-               flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
-               flash_unlock_seq(info, 0);
-               flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID);
-               udelay(1000); /* some flash are slow to respond */
-               info->manufacturer_id = flash_read_uchar (info,
-                                               FLASH_OFFSET_MANUFACTURER_ID);
-               info->device_id = flash_read_uchar (info,
-                                               FLASH_OFFSET_DEVICE_ID);
-               if (info->device_id == 0x7E) {
-                       /* AMD 3-byte (expanded) device ids */
-                       info->device_id2 = flash_read_uchar (info,
-                                               FLASH_OFFSET_DEVICE_ID2);
-                       info->device_id2 <<= 8;
-                       info->device_id2 |= flash_read_uchar (info,
-                                               FLASH_OFFSET_DEVICE_ID3);
-               }
-               flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+               flash_read_jedec_ids_amd(info);
                break;
        default:
                break;
        }
 }
 
-#ifdef CONFIG_FLASH_CFI_LEGACY
 /*-----------------------------------------------------------------------
  * Call board code to request info about non-CFI flash.
  * board_flash_get_legacy needs to fill in at least:
        uchar num_erase_regions;
        int erase_region_size;
        int erase_region_count;
-       int geometry_reversed = 0;
        struct cfi_qry qry;
 
        info->ext_addr = 0;
                info->ext_addr = le16_to_cpu(qry.p_adr);
                num_erase_regions = qry.num_erase_regions;
 
-               flash_read_jedec_ids (info);
-               flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI);
-
                if (info->ext_addr) {
                        info->cfi_version = (ushort) flash_read_uchar (info,
                                                info->ext_addr + 3) << 8;
                        info->cfi_version |= (ushort) flash_read_uchar (info,
                                                info->ext_addr + 4);
                }
+
 #ifdef DEBUG
                flash_printqry (&qry);
 #endif
+
                switch (info->vendor) {
                case CFI_CMDSET_INTEL_STANDARD:
                case CFI_CMDSET_INTEL_EXTENDED:
-               default:
-                       info->cmd_reset = FLASH_CMD_RESET;
-#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
+                       cmdset_intel_init(info, &qry);
                        break;
                case CFI_CMDSET_AMD_STANDARD:
                case CFI_CMDSET_AMD_EXTENDED:
-                       info->cmd_reset = AMD_CMD_RESET;
-                       /* 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;
-                       }
+                       cmdset_amd_init(info, &qry);
                        break;
+               default:
+                       printf("CFI: Unknown command set 0x%x\n",
+                                       info->vendor);
+                       /*
+                        * Unfortunately, this means we don't know how
+                        * to get the chip back to Read mode. Might
+                        * as well try an Intel-style reset...
+                        */
+                       flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+                       return 0;
                }
 
                debug ("manufacturer is %d\n", info->vendor);
                sect_cnt = 0;
                sector = base;
                for (i = 0; i < num_erase_regions; i++) {
-                       unsigned int region = i;
-
                        if (i > NUM_ERASE_REGIONS) {
                                printf ("%d erase regions found, only %d used\n",
                                        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;