# HG changeset patch # User Michael Spacefalcon # Date 1402870006 0 # Node ID 7602443edf0d997e7033ecf1511eec232d65fdfd # Parent 582b5052c86d5d87635cb6fedd48643ad5be1dad fc-loadtool flash: CFI query code implemented, compiles diff -r 582b5052c86d -r 7602443edf0d loadtools/flutil.c --- a/loadtools/flutil.c Sun Jun 15 20:38:18 2014 +0000 +++ b/loadtools/flutil.c Sun Jun 15 22:06:46 2014 +0000 @@ -10,15 +10,161 @@ extern struct flash_bank_info flash_bank_info[2]; +static int +cfi_read_byte(bi, off, ret16p) + struct flash_bank_info *bi; + int off; + uint16_t *ret16p; +{ + return do_r16(bi->base_addr + (off << 1), ret16p); +} + +static int +cfi_read_twobyte(bi, off, retptr) + struct flash_bank_info *bi; + int off; + uint16_t *retptr; +{ + uint16_t lo, hi; + + if (cfi_read_byte(bi, off, &lo) < 0) + return(-1); + lo &= 0xFF; + if (cfi_read_byte(bi, off + 1, &hi) < 0) + return(-1); + hi &= 0xFF; + *retptr = (hi << 8) | lo; + return(0); +} + +static int +cfi_id_return_to_read_mode(bi) + struct flash_bank_info *bi; +{ + if (do_w16(bi->base_addr + 0xAAA, 0xF0)) { + fprintf(stderr, + "unexpected response to w16 when resetting flash to read mode!\n"); + return(-1); + } + return(0); +} + flash_get_cfi(bank) { struct flash_bank_info *bi; + struct cfi_info *cfi; + struct flash_region_desc *reg; + int nr; + uint16_t rdval; + uint32_t size_check; bi = flash_bank_info + bank; if (bi->cfi) return(0); - printf("Error: CFI info retrieval not implemented yet\n"); - return(-1); + printf("Performing CFI query\n"); + if (do_w16(bi->base_addr + 0xAA, 0x98)) { + fprintf(stderr, "unexpected response to w16 - aborting\n"); + return(-1); + } + /* if do_r16() returns -1, error msg has already been printed */ + if (cfi_read_byte(bi, 0x10, &rdval) < 0) + return(-1); + if (rdval != 'Q') { +noqry: fprintf(stderr, "error: no QRY response from flash\n"); + cfi_id_return_to_read_mode(bi); + return(-1); + } + if (cfi_read_byte(bi, 0x11, &rdval) < 0) + return(-1); + if (rdval != 'R') + goto noqry; + if (cfi_read_byte(bi, 0x12, &rdval) < 0) + return(-1); + if (rdval != 'Y') + goto noqry; + cfi = malloc(sizeof(struct cfi_info)); + if (!cfi) { + fprintf(stderr, + "unable to malloc buffer for flash bank %d CFI structure\n", + bank); + cfi_id_return_to_read_mode(bi); + return(-1); + } + if (cfi_read_twobyte(bi, 0x13, &cfi->cmdset_style) < 0) { +free_and_immed_out: + free(cfi); + return(-1); + } + /* total device size */ + if (cfi_read_byte(bi, 0x27, &rdval) < 0) + goto free_and_immed_out; + if (rdval < 20 || rdval > 24) { + fprintf(stderr, + "error: CFI reports unreasonable device size\n"); +free_and_clean_out: + free(cfi); + cfi_id_return_to_read_mode(bi); + return(-1); + } + cfi->total_size = 1 << rdval; + if (cfi->total_size > bi->bank_desc->align_size) { + fprintf(stderr, + "error: CFI device size 0x%lx exceeds configured maximum 0x%lx\n", + (u_long) cfi->total_size, bi->bank_desc->align_size); + goto free_and_clean_out; + } + if (cfi_read_byte(bi, 0x2C, &rdval) < 0) + goto free_and_immed_out; + if (rdval < 1 || rdval > CFI_MAX_REGIONS) { + fprintf(stderr, + "error: CFI reports unreasonable # of erase regions\n"); + goto free_and_clean_out; + } + cfi->nregions = rdval; + cfi->total_sectors = 0; + size_check = 0; + for (nr = 0; nr < cfi->nregions; nr++) { + reg = cfi->regions + nr; + if (cfi_read_twobyte(bi, 0x2D + nr*4, &rdval) < 0) + goto free_and_immed_out; + if (rdval > 255) { + fprintf(stderr, + "error: CFI reports unreasonable # of sectors in region %d\n", + nr); + goto free_and_clean_out; + } + reg->nsectors = rdval + 1; + cfi->total_sectors += reg->nsectors; + if (cfi_read_twobyte(bi, 0x2F + nr*4, &rdval) < 0) + goto free_and_immed_out; + if (rdval < 0x20 || rdval > 0x400) { + fprintf(stderr, + "error: CFI reports unreasonable sector size in region %d\n", + nr); + goto free_and_clean_out; + } + reg->sector_size = rdval << 8; + size_check += reg->sector_size * reg->nsectors; + } + if (cfi_id_return_to_read_mode(bi) < 0) { + /* error msg already printed */ + free(cfi); + return(-1); + } + if (size_check != cfi->total_size) { + fprintf(stderr, +"CFI error: added size of erase regions (%lx) != reported devive size (%lx)\n", + (u_long) size_check, (u_long) cfi->total_size); + free(cfi); + return(-1); + } + /* all checks passed */ + bi->cfi = cfi; + printf( +"CFI query successful: total size %lx, %u sectors, command set style %04X\n\n", + (u_long) cfi->total_size, cfi->total_sectors, + cfi->cmdset_style); + return(1); } get_flash_sector_table(bank)