# HG changeset patch # User Michael Spacefalcon # Date 1402862754 0 # Node ID f027c6fbe37efc9bf80ccdb552760bb2c4654ec2 # Parent d26a9e3de6265ac07004b9f65b7b8f0ba9fee142 fc-loadtool flash: first round of refactoring for CFI diff -r d26a9e3de626 -r f027c6fbe37e loadtools/flash.h --- a/loadtools/flash.h Sun Jun 15 00:47:06 2014 +0000 +++ b/loadtools/flash.h Sun Jun 15 20:05:54 2014 +0000 @@ -12,16 +12,27 @@ unsigned nsectors; }; +#define CFI_MAX_REGIONS 4 + +/* The info in struct cfi_info can be either gathered from CFI or hard-coded. */ +struct cfi_info { + uint16_t cmdset_style; + uint32_t total_size; + unsigned nregions; + struct flash_region_desc regions[CFI_MAX_REGIONS]; + unsigned total_sectors; +}; + struct flash_idcheck { uint16_t offset; uint16_t expect_val; }; struct flash_bank_desc { - struct flash_region_desc *regions; - uint32_t prog_base_mask; - struct flash_idcheck *idcheck_table; - unsigned idcheck_num; + uint32_t align_size; + struct cfi_info *hard_cfi; + struct flash_idcheck *idcheck_table; + unsigned idcheck_num; }; struct flash_device_desc { @@ -39,9 +50,8 @@ struct flash_bank_info { uint32_t base_addr; - uint32_t total_size; struct flash_bank_desc *bank_desc; + struct cfi_info *cfi; struct sector_info *sectors; - unsigned nsectors; int idcheck_done; }; diff -r d26a9e3de626 -r f027c6fbe37e loadtools/flerase.c --- a/loadtools/flerase.c Sun Jun 15 00:47:06 2014 +0000 +++ b/loadtools/flerase.c Sun Jun 15 20:05:54 2014 +0000 @@ -72,20 +72,27 @@ offset = strtoul(argv[2], &strtoul_endp, 16); if (*strtoul_endp) goto inv; + if (flash_get_cfi(bank) < 0) + return(-1); bi = flash_bank_info + bank; - if (offset >= bi->total_size) { + if (bi->cfi->cmdset_style != 2) { + fprintf(stderr, +"error: this command is currently only implemented for AMD-style flash\n"); + return(-1); + } + if (offset >= bi->cfi->total_size) { fprintf(stderr, "error: specified offset exceeds flash bank size (0x%lx)\n", - (u_long) bi->total_size); + (u_long) bi->cfi->total_size); return(-1); } len = strtoul(argv[3], &strtoul_endp, 16); if (*strtoul_endp) goto inv; - if (len > bi->total_size - offset) { + if (len > bi->cfi->total_size - offset) { fprintf(stderr, "error: specified offset+length exceed flash bank size (0x%lx)\n", - (u_long) bi->total_size); + (u_long) bi->cfi->total_size); return(-1); } if (!len) { diff -r d26a9e3de626 -r f027c6fbe37e loadtools/flprogbin.c --- a/loadtools/flprogbin.c Sun Jun 15 00:47:06 2014 +0000 +++ b/loadtools/flprogbin.c Sun Jun 15 20:05:54 2014 +0000 @@ -35,11 +35,18 @@ flashoff = strtoul(argv[2], &strtoul_endp, 16); if (*strtoul_endp) goto inv; + if (flash_get_cfi(bank) < 0) + return(-1); bi = flash_bank_info + bank; - if (flashoff >= bi->total_size) { + if (bi->cfi->cmdset_style != 2) { + fprintf(stderr, +"error: this command is currently only implemented for AMD-style flash\n"); + return(-1); + } + if (flashoff >= bi->cfi->total_size) { fprintf(stderr, "error: specified flash offset exceeds bank size (0x%lx)\n", - (u_long) bi->total_size); + (u_long) bi->cfi->total_size); return(-1); } if (flashoff & 1) { @@ -90,10 +97,10 @@ fclose(binf); return(0); } - if (len > bi->total_size - flashoff) { + if (len > bi->cfi->total_size - flashoff) { fprintf(stderr, "error: specified flash offset+length exceed bank size (0x%lx)\n", - (u_long) bi->total_size); + (u_long) bi->cfi->total_size); fclose(binf); return(-1); } diff -r d26a9e3de626 -r f027c6fbe37e loadtools/flprogsrec.c --- a/loadtools/flprogsrec.c Sun Jun 15 00:47:06 2014 +0000 +++ b/loadtools/flprogsrec.c Sun Jun 15 20:05:54 2014 +0000 @@ -22,6 +22,14 @@ int resp; unsigned long rec_count; + if (flash_get_cfi(bank) < 0) + return(-1); + bi = flash_bank_info + bank; + if (bi->cfi->cmdset_style != 2) { + fprintf(stderr, +"error: this command is currently only implemented for AMD-style flash\n"); + return(-1); + } srr.filename = imgfile; resp = open_srec_file(&srr); if (resp < 0) @@ -31,7 +39,6 @@ fclose(srr.openfile); return(resp); } - bi = flash_bank_info + bank; sprintf(shortarg, "%lx", (u_long) bi->base_addr); targv[0] = "AMFB"; targv[1] = shortarg; @@ -91,8 +98,8 @@ fclose(srr.openfile); return(-1); } - srr.addr &= bi->total_size - 1; - if (srr.addr + srr.datalen > bi->total_size) { + srr.addr &= bi->cfi->total_size - 1; + if (srr.addr + srr.datalen > bi->cfi->total_size) { fprintf(stderr, "%s line %d: goes past the end of the flash bank\n", srr.filename, srr.lineno); diff -r d26a9e3de626 -r f027c6fbe37e loadtools/flutil.c --- a/loadtools/flutil.c Sun Jun 15 00:47:06 2014 +0000 +++ b/loadtools/flutil.c Sun Jun 15 20:05:54 2014 +0000 @@ -10,42 +10,35 @@ extern struct flash_bank_info flash_bank_info[2]; -compute_flash_totsize_nsecs(bank) +flash_get_cfi(bank) { struct flash_bank_info *bi; - struct flash_region_desc *reg; bi = flash_bank_info + bank; - for (reg = bi->bank_desc->regions; reg->nsectors; reg++) { - bi->nsectors += reg->nsectors; - bi->total_size += reg->sector_size * reg->nsectors; - } -} - -/* the following function is used to verify that total_size is a power of 2 */ -count_ones(word) - uint32_t word; -{ - int count; - - for (count = 0; word; word >>= 1) - count += word & 1; - return count; + if (bi->cfi) + return(0); + printf("Error: CFI info retrieval not implemented yet\n"); + return(-1); } get_flash_sector_table(bank) { struct flash_bank_info *bi; + struct cfi_info *cfi; struct flash_region_desc *reg; struct sector_info *sp; uint32_t offset; - int i; + int nr, i; bi = flash_bank_info + bank; if (bi->sectors) return(0); + i = flash_get_cfi(bank); + if (i < 0) + return(i); + cfi = bi->cfi; sp = (struct sector_info *) malloc(sizeof(struct sector_info) - * (bi->nsectors + 1)); + * (cfi->total_sectors + 1)); if (!sp) { fprintf(stderr, "unable to malloc buffer for flash bank %d sector table\n", @@ -55,7 +48,8 @@ bi->sectors = sp; /* now fill it */ offset = 0; - for (reg = bi->bank_desc->regions; reg->nsectors; reg++) { + for (nr = 0; nr < cfi->nregions; nr++) { + reg = cfi->regions + nr; for (i = 0; i < reg->nsectors; i++) { sp->start = offset; sp->size = reg->sector_size; @@ -64,12 +58,12 @@ } } /* sanity checks */ - if (sp - bi->sectors != bi->nsectors) { + if (sp - bi->sectors != cfi->total_sectors) { fprintf(stderr, "BUG in get_flash_sector_table(): wrong # of sectors at the end\n"); abort(); } - if (offset != bi->total_size) { + if (offset != cfi->total_size) { fprintf(stderr, "BUG in get_flash_sector_table(): wrong offset at the end\n"); abort(); @@ -93,7 +87,7 @@ if (get_flash_sector_table(bank) < 0) return(-1); bi = flash_bank_info + bank; - printf("%u sectors in flash bank %d:\n", bi->nsectors, bank); + printf("%u sectors in flash bank %d:\n", bi->cfi->total_sectors, bank); printf("Offset Size\n"); for (sp = bi->sectors; sp->size; sp++) printf("%08lX %lx\n", (u_long) sp->start, (u_long) sp->size); @@ -160,6 +154,9 @@ bi = flash_bank_info + bank; if (bi->idcheck_done && !repeat) return(0); + bd = bi->bank_desc; + if (!bd->idcheck_table || !bd->idcheck_num) + return(0); printf("Performing flash ID check\n"); stat = do_w16(bi->base_addr + 0xAAA, 0xAA); if (stat) { @@ -173,7 +170,6 @@ stat = do_w16(bi->base_addr + 0xAAA, 0x90); if (stat) goto bad_w16; - bd = bi->bank_desc; id = bd->idcheck_table; fail = 0; for (cnt = 0; cnt < bd->idcheck_num; cnt++) { diff -r d26a9e3de626 -r f027c6fbe37e loadtools/ltflash.c --- a/loadtools/ltflash.c Sun Jun 15 00:47:06 2014 +0000 +++ b/loadtools/ltflash.c Sun Jun 15 20:05:54 2014 +0000 @@ -1,6 +1,6 @@ /* - * In this module we are going to implement the flash operation commands - * of fc-loadtool. + * This module contains the "core" of fc-loadtool flash operations; + * fl*.c modules contain the rest. */ #include @@ -13,11 +13,12 @@ /* K5A32xx device description */ -static struct flash_region_desc k5a32xx_topboot_regions[] = { - /* 4 MiB total, 64 KiB sectors except for the boot block of 8x 8 KiB */ - {0x10000, 63}, - {0x2000, 8}, - {0, 0} /* array terminator */ +static struct cfi_info k5a32xx_topboot_hardcfi = { + .cmdset_style = 2, + .total_size = 0x400000, + .nregions = 2, + .regions = {0x10000, 63, 0x2000, 8}, + .total_sectors = 71 }; static struct flash_idcheck k5a32xx_topboot_idcheck[2] = { @@ -26,23 +27,25 @@ }; static struct flash_bank_desc k5a32xx_topboot_bankdesc = { - k5a32xx_topboot_regions, 0xFFF00000, k5a32xx_topboot_idcheck, 2 + 0x400000, &k5a32xx_topboot_hardcfi, k5a32xx_topboot_idcheck, 2 }; /* S{29,71}PL129N device description */ -static struct flash_region_desc pl129n_ce1_regions[] = { - /* 4 sectors of 64 KiB each at the beginning, then 256 KiB sectors */ - {0x10000, 4}, - {0x40000, 31}, - {0, 0} /* array terminator */ +static struct cfi_info pl129n_ce1_hardcfi = { + .cmdset_style = 2, + .total_size = 0x800000, + .nregions = 2, + .regions = {0x10000, 4, 0x40000, 31}, + .total_sectors = 35 }; -static struct flash_region_desc pl129n_ce2_regions[] = { - /* the other way around now */ - {0x40000, 31}, - {0x10000, 4}, - {0, 0} /* array terminator */ +static struct cfi_info pl129n_ce2_hardcfi = { + .cmdset_style = 2, + .total_size = 0x800000, + .nregions = 2, + .regions = {0x40000, 31, 0x10000, 4}, + .total_sectors = 35 }; static struct flash_idcheck pl129n_idcheck[4] = { @@ -53,8 +56,8 @@ }; static struct flash_bank_desc pl129n_banks[2] = { - {pl129n_ce1_regions, 0xFFFC0000, pl129n_idcheck, 4}, - {pl129n_ce2_regions, 0xFFFC0000, pl129n_idcheck, 4} + {0x800000, &pl129n_ce1_hardcfi, pl129n_idcheck, 4}, + {0x800000, &pl129n_ce2_hardcfi, pl129n_idcheck, 4} }; /* list of supported flash devices */ @@ -130,20 +133,14 @@ } /* the rest comes from the flash device type */ bi->bank_desc = selected_flash_device->bank_desc + bank; - compute_flash_totsize_nsecs(bank); - if (count_ones(bi->total_size) != 1) { - fprintf(stderr, -"fc-loadtool internal bug: flash bank %d size for %s is not a power of 2\n", - bank, selected_flash_device->name); - exit(1); - } - if (bi->base_addr & (bi->total_size - 1)) { + if (bi->base_addr & (bi->bank_desc->align_size - 1)) { fprintf(stderr, "%s line %d: flash bank %d base addr is not aligned to the bank size (0x%lx)\n", filename_for_errs, lineno_for_errs, bank, - (u_long) bi->total_size); + (u_long) bi->bank_desc->align_size); exit(1); } + bi->cfi = bi->bank_desc->hard_cfi; } while (isspace(*cp)) cp++; @@ -171,20 +168,22 @@ offset = strtoul(argv[2], &strtoul_endp, 16); if (*strtoul_endp) goto inv; + if (flash_get_cfi(bank) < 0) + return(-1); bi = flash_bank_info + bank; - if (offset >= bi->total_size) { + if (offset >= bi->cfi->total_size) { fprintf(stderr, "error: specified offset exceeds flash bank size (0x%lx)\n", - (u_long) bi->total_size); + (u_long) bi->cfi->total_size); return(-1); } len = strtoul(argv[3], &strtoul_endp, 16); if (*strtoul_endp) goto inv; - if (len > bi->total_size - offset) { + if (len > bi->cfi->total_size - offset) { fprintf(stderr, "error: specified offset+length exceed flash bank size (0x%lx)\n", - (u_long) bi->total_size); + (u_long) bi->cfi->total_size); return(-1); } sprintf(targ_start, "%lx", (u_long) bi->base_addr + offset); @@ -212,20 +211,22 @@ argv[0], argv[1]); return(-1); } + if (flash_get_cfi(bank) < 0) + return(-1); bi = flash_bank_info + bank; if (argc >= 4) { offset = strtoul(argv[3], &strtoul_endp, 16); if (*strtoul_endp) goto inv; - if (offset >= bi->total_size) { + if (offset >= bi->cfi->total_size) { fprintf(stderr, "error: specified offset exceeds flash bank size (0x%lx)\n", - (u_long) bi->total_size); + (u_long) bi->cfi->total_size); return(-1); } } else offset = 0; - maxlen = bi->total_size - offset; + maxlen = bi->cfi->total_size - offset; if (argc >= 5) { dumplen = strtoul(argv[4], &strtoul_endp, 16); if (*strtoul_endp) @@ -233,7 +234,7 @@ if (dumplen > maxlen) { fprintf(stderr, "error: specified offset+length exceed flash bank size (0x%lx)\n", - (u_long) bi->total_size); + (u_long) bi->cfi->total_size); return(-1); } } else @@ -271,8 +272,11 @@ bi = flash_bank_info + bank; printf("Flash device type: %s\n", selected_flash_device->name); printf("Bank %d base address: %08lX\n", bank, (u_long) bi->base_addr); - printf("Bank %d total size: %lx\n", bank, (u_long) bi->total_size); - printf("Sectors in bank %d: %u\n", bank, bi->nsectors); + if (flash_get_cfi(bank) < 0) + return(-1); + printf("Bank %d total size: %lx\n", bank, (u_long) bi->cfi->total_size); + printf("Sectors in bank %d: %u (%u regions)\n", bank, + bi->cfi->total_sectors, bi->cfi->nregions); flash_id_check(bank, 1); if (selected_flash_device->nbanks == 2 && !bank) printf("\nFlash device has 2 banks; flash2 command available\n"); @@ -285,8 +289,15 @@ char *targv[4], targ_base[10]; int stat; + if (flash_get_cfi(bank) < 0) + return(-1); + if (flash_bank_info[bank].cfi->cmdset_style != 2) { + fprintf(stderr, +"error: this command is currently only implemented for AMD-style flash\n"); + return(-1); + } if (argc != 4) { -inv: fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n", + fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n", argv[0], argv[1]); return(-1); }