# HG changeset patch # User Mychaela Falconia # Date 1559020367 0 # Node ID 0dd2c87c1b63e564bc95ca1dabf3c5d1d46150b4 # Parent 7bf0d909c87e76facfad604b0402b3c04f1a5d5e fc-loadtool flash support overhaul diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/Makefile --- a/loadtools/Makefile Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/Makefile Tue May 28 05:12:47 2019 +0000 @@ -16,11 +16,11 @@ romload.o secondprog.o sertool.o srecreader.o ttypassthru.o \ ${EXTRA_OBJ} -LOADTOOL_OBJS= crc32tab.o defpath.o flashops.o flcmplboot.o flmain.o flmisc.o \ - flprogbin.o flprogsrec.o flutil.o hexdecode.o hwparam.o \ - labaud.o ltdispatch.o ltdump.o ltexit.o lthelp.o ltmain.o \ - ltmisc.o ltpassthru.o ltscript.o romload.o srecreader.o \ - tpinterf.o tpinterf2.o tpinterf3.o ${EXTRA_OBJ} +LOADTOOL_OBJS= crc32tab.o defpath.o flashid.o flashops.o flcmplboot.o flconf.o\ + fldevs.o flmain.o flmisc.o flprogbin.o flprogsrec.o flutil.o \ + hexdecode.o hwparam.o labaud.o ltdispatch.o ltdump.o ltexit.o \ + lthelp.o ltmain.o ltmisc.o ltpassthru.o ltscript.o romload.o \ + srecreader.o tpinterf.o tpinterf2.o tpinterf3.o ${EXTRA_OBJ} XRAM_OBJS= chainload.o clmain.o defexitstub.o defpath.o flashstubs.o \ hexdecode.o hwparam.o initscript.o labaud.o romload.o \ diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flash.h --- a/loadtools/flash.h Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/flash.h Tue May 28 05:12:47 2019 +0000 @@ -1,5 +1,11 @@ /* this header file contains definitions for fc-loadtool flash support */ +/* global configuration */ +#define FLASH_GLOBAL_CFG_NONE 0 +#define FLASH_GLOBAL_CFG_SINGLE_4M 1 +#define FLASH_GLOBAL_CFG_SINGLE_8M 2 +#define FLASH_GLOBAL_CFG_DUAL_8M 3 + /* * The following structures represent an "abstract" * description of flash devices. @@ -25,22 +31,16 @@ unsigned total_sectors; }; -struct flash_idcheck { - uint16_t offset; - uint16_t expect_val; +struct cfi_check { + int offset; + uint8_t expect_val; }; -struct flash_bank_desc { - uint32_t align_size; - struct flash_geom *geom; - struct flash_idcheck *idcheck_table; - unsigned idcheck_num; -}; - -struct flash_device_desc { +struct flash_device { char *name; - struct flash_bank_desc *bank_desc; - unsigned nbanks; + struct cfi_check *cfi_table; + int required_global_config; + struct flash_geom *bank_geom[2]; struct flash_cmdset *cmdset; }; @@ -65,9 +65,9 @@ struct flash_bank_info { uint32_t base_addr; - struct flash_bank_desc *bank_desc; + struct flash_device *device; struct flash_geom *geom; struct flash_cmdset *ops; struct sector_info *sectors; - int idcheck_done; + int detect_done; }; diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flashid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadtools/flashid.c Tue May 28 05:12:47 2019 +0000 @@ -0,0 +1,188 @@ +/* + * Flash device detection code lives here + */ + +#include +#include +#include +#include +#include "flash.h" + +extern struct flash_device flashdev_28F160C3T; +extern struct flash_device flashdev_28F320C3T; +extern struct flash_device flashdev_28F640C3T; +extern struct flash_device flashdev_28F640C3B; +extern struct flash_device flashdev_28F640W30T; +extern struct flash_device flashdev_28F640W30B; +extern struct flash_device flashdev_PL129J; +extern struct flash_device flashdev_PL129N; +extern struct flash_device flashdev_K5A32xx_T; + +extern int flash_global_config; +extern struct flash_bank_info flash_bank_info[2]; + +static +run_cfi_check(bi, table) + struct flash_bank_info *bi; + struct cfi_check *table; +{ + struct cfi_check *tp; + uint16_t rdword; + + for (tp = table; tp->offset >= 0; tp++) { + if (do_r16(bi->base_addr + (tp->offset << 1), &rdword) < 0) + return(-1); + if (rdword != tp->expect_val) + return(0); + } + return(1); +} + +static +try_device(bi, dev) + struct flash_bank_info *bi; + struct flash_device *dev; +{ + int rc; + + printf("Appears to be %s or compatible, checking CFI\n", dev->name); + if (do_w16(bi->base_addr + 0xAA, 0x98)) { + fprintf(stderr, "unexpected response to w16 - aborting\n"); + return(-1); + } + rc = run_cfi_check(bi, dev->cfi_table); + if (rc < 0) + return(rc); + if (!rc) { + fprintf(stderr, "Error: CFI mismatch, unsafe to continue\n"); + return(-1); + } + printf("Confirmed %s or compatible\n", dev->name); + bi->device = dev; + return(0); +} + +static +spansion_pl129j_or_n(bi) + struct flash_bank_info *bi; +{ + int rc; + + printf("Spansion PL129J or PL129N, looking at CFI\n"); + if (do_w16(bi->base_addr + 0xAA, 0x98)) { + fprintf(stderr, "unexpected response to w16 - aborting\n"); + return(-1); + } + rc = run_cfi_check(bi, flashdev_PL129N.cfi_table); + if (rc < 0) + return(rc); + if (rc) { + printf("Found PL129N\n"); + bi->device = &flashdev_PL129N; + return(0); + } + rc = run_cfi_check(bi, flashdev_PL129J.cfi_table); + if (rc < 0) + return(rc); + if (rc) { + printf("Found PL129J\n"); + bi->device = &flashdev_PL129J; + return(0); + } + fprintf(stderr, "Error: no matching CFI found\n"); + return(-1); +} + +static +amd_extended_id(bi) + struct flash_bank_info *bi; +{ + uint16_t ext1, ext2; + + printf("AMD-style extended ID device, reading\n"); + if (do_r16(bi->base_addr + 0x1C, &ext1) < 0) + return(-1); + if (do_r16(bi->base_addr + 0x1E, &ext2) < 0) + return(-1); + printf("Extended ID: %04X %04X\n", ext1, ext2); + if (ext1 == 0x2221 && ext2 == 0x2200) + return spansion_pl129j_or_n(bi); + fprintf(stderr, "Error: unknown device ID\n"); + return(-1); +} + +static struct idmap { + uint16_t manuf_id; + uint16_t dev_id; + int (*handler)(); + void *extra_arg; +} device_id_table[] = { + /* AMD/Spansion devices */ + {0x0001, 0x227E, amd_extended_id, 0}, + /* 28F160C3T equivalent found in a C11x phone in the wild */ + {0x0020, 0x88CE, try_device, &flashdev_28F160C3T}, + /* Intel flash chips */ + {0x0089, 0x8854, try_device, &flashdev_28F640W30T}, + {0x0089, 0x8855, try_device, &flashdev_28F640W30B}, + {0x0089, 0x8864, try_device, &flashdev_28F640W30T}, + {0x0089, 0x88C2, try_device, &flashdev_28F160C3T}, + {0x0089, 0x88C4, try_device, &flashdev_28F320C3T}, + {0x0089, 0x88CC, try_device, &flashdev_28F640C3T}, + {0x0089, 0x88CD, try_device, &flashdev_28F640C3B}, + /* Samsung flash */ + {0x00EC, 0x22A0, try_device, &flashdev_K5A32xx_T}, + /* table search terminator */ + {0, 0, 0, 0} +}; + +flash_detect(bank, repeat) +{ + struct flash_bank_info *bi; + uint16_t manuf_id, dev_id; + struct idmap *tp; + int rc; + + bi = flash_bank_info + bank; + if (bi->detect_done && !repeat) + return(0); + printf("Autodetecting flash chip type\n"); + if (do_w16(bi->base_addr + 0xAAA, 0xAA)) { +bad_w16: fprintf(stderr, + "unexpected response to w16 in read ID cmd sequence - aborting\n"); + return(-1); + } + if (do_w16(bi->base_addr + 0x554, 0x55)) + goto bad_w16; + if (do_w16(bi->base_addr + 0xAAA, 0x90)) + goto bad_w16; + if (do_r16(bi->base_addr, &manuf_id) < 0) + return(-1); + if (do_r16(bi->base_addr + 2, &dev_id) < 0) + return(-1); + printf("Basic device ID: %04X %04X\n", manuf_id, dev_id); + for (tp = device_id_table; tp->handler; tp++) + if (tp->manuf_id == manuf_id && tp->dev_id == dev_id) + break; + if (!tp->handler) { + fprintf(stderr, "Error: unknown device ID\n"); + return(-1); + } + rc = tp->handler(bi, tp->extra_arg); + if (rc < 0) + return(rc); + /* got the device, see if it is compatible with global config */ + if (bi->device->required_global_config > flash_global_config) { + fprintf(stderr, +"Error: detected flash device is not compatible with the configured mapping\n"); + return(-1); + } + /* good to go */ + if (bi->device->bank_geom[1] && bank) + bi->geom = bi->device->bank_geom[1]; + else + bi->geom = bi->device->bank_geom[0]; + bi->ops = bi->device->cmdset; + bi->detect_done = 1; + /* return device to read array mode */ + return bi->ops->reset_cmd(bi); +} diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flashops.c --- a/loadtools/flashops.c Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/flashops.c Tue May 28 05:12:47 2019 +0000 @@ -19,10 +19,10 @@ } static -invalid() +amd_invalid() { fprintf(stderr, - "This operation is not applicable to the selected flash type\n"); + "This operation is not applicable to AMD-style flash\n"); return(-1); } @@ -86,8 +86,8 @@ struct flash_cmdset flash_cmdset_amd = { .cmdset_name = "AMD", .reset_cmd = amd_reset_cmd, - .status_cmd = invalid, - .unlock_sector = invalid, + .status_cmd = amd_invalid, + .unlock_sector = amd_invalid, .erase_sector = amd_sector_erase, .prep_for_program = noop, .loadagent_setbase_cmd = "AMFB", diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flashstubs.c --- a/loadtools/flashstubs.c Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/flashstubs.c Tue May 28 05:12:47 2019 +0000 @@ -6,7 +6,7 @@ */ void -set_flash_device() +set_flash_config() { } diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flcmplboot.c --- a/loadtools/flcmplboot.c Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/flcmplboot.c Tue May 28 05:12:47 2019 +0000 @@ -140,7 +140,7 @@ argv[0], argv[1]); return(-1); } - if (flash_get_cfi(0) < 0) + if (flash_detect(0, 0) < 0) return(-1); if (flash_bank_info[0].geom->regions[0].sector_size != boot_sector_size) { diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flconf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadtools/flconf.c Tue May 28 05:12:47 2019 +0000 @@ -0,0 +1,131 @@ +/* + * This module handles flash configuration for fc-loadtool + */ + +#include +#include +#include +#include +#include +#include +#include +#include "flash.h" + +/* the following variables describe our selected flash config */ + +int flash_global_config; +struct flash_bank_info flash_bank_info[2]; + +/* global configurations selected via hw parameter files */ + +static struct global_cfg_kw { + char *kw; + int code; +} global_cfg_keywords[] = { + {"single-4M", FLASH_GLOBAL_CFG_SINGLE_4M}, + {"single-8M", FLASH_GLOBAL_CFG_SINGLE_8M}, + {"dual-8M", FLASH_GLOBAL_CFG_DUAL_8M}, + /* backward compatibility with old hw param files */ + {"cfi-4M", FLASH_GLOBAL_CFG_SINGLE_4M}, + {"cfi-8M", FLASH_GLOBAL_CFG_SINGLE_8M}, + {"k5a32xx_t", FLASH_GLOBAL_CFG_SINGLE_4M}, + {"pl129n", FLASH_GLOBAL_CFG_DUAL_8M}, + {"28f640w30b", FLASH_GLOBAL_CFG_SINGLE_8M}, + {0, 0} /* array terminator */ +}; + +/* called from hwparam.c config file parser */ +void +set_flash_config(arg, filename_for_errs, lineno_for_errs) + char *arg; + char *filename_for_errs; + int lineno_for_errs; +{ + char *cp, *np, *ep; + struct global_cfg_kw *tp; + int bank, nbanks; + struct flash_bank_info *bi; + uint32_t align_size; + + if (flash_global_config) { + fprintf(stderr, "%s line %d: duplicate flash setting\n", + filename_for_errs, lineno_for_errs); + exit(1); + } + for (cp = arg; isspace(*cp); cp++) + ; + if (!*cp || *cp == '#') { +too_few_arg: fprintf(stderr, + "%s line %d: flash setting: too few arguments\n", + filename_for_errs, lineno_for_errs); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + for (tp = global_cfg_keywords; tp->kw; tp++) + if (!strcmp(tp->kw, np)) + break; + if (!tp->kw) { + fprintf(stderr, + "%s line %d: unknown flash config \"%s\"\n", + filename_for_errs, lineno_for_errs, np); + exit(1); + } + flash_global_config = tp->code; + + /* now initialize flash_bank_info (base addresses) */ + switch (flash_global_config) { + case FLASH_GLOBAL_CFG_SINGLE_4M: + nbanks = 1; + align_size = 0x400000; + break; + case FLASH_GLOBAL_CFG_SINGLE_8M: + nbanks = 1; + align_size = 0x800000; + break; + case FLASH_GLOBAL_CFG_DUAL_8M: + nbanks = 2; + align_size = 0x800000; + break; + default: + fprintf(stderr, + "BUG in set_flash_config(): invalid global config\n"); + abort(); + } + for (bank = 0; bank < nbanks; bank++) { + while (isspace(*cp)) + cp++; + if (!*cp || *cp == '#') + goto too_few_arg; + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + bi = flash_bank_info + bank; + bi->base_addr = strtoul(np, &ep, 16); + if (*ep) { + fprintf(stderr, +"%s line %d: syntax error (base addr expected after flash config name)\n", + filename_for_errs, lineno_for_errs); + exit(1); + } + /* check alignment */ + if (bi->base_addr & (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) align_size); + exit(1); + } + } + while (isspace(*cp)) + cp++; + if (*cp && *cp != '#') { + fprintf(stderr, + "%s line %d: flash setting: too many arguments\n", + filename_for_errs, lineno_for_errs); + exit(1); + } +} diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/fldevs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadtools/fldevs.c Tue May 28 05:12:47 2019 +0000 @@ -0,0 +1,302 @@ +/* + * This module holds the tables of supported flash devices + */ + +#include +#include +#include +#include +#include +#include +#include +#include "flash.h" + +extern struct flash_cmdset flash_cmdset_amd; +extern struct flash_cmdset flash_cmdset_intel; +extern struct flash_cmdset flash_cmdset_intel_w30; + +/* flash bank geometries */ + +static struct flash_geom geom_2M_topboot = { + .total_size = 0x200000, + .nregions = 2, + .regions = {0x10000, 31, 0x2000, 8}, + .total_sectors = 39, +}; + +static struct flash_geom geom_4M_topboot = { + .total_size = 0x400000, + .nregions = 2, + .regions = {0x10000, 63, 0x2000, 8}, + .total_sectors = 71, +}; + +static struct flash_geom geom_8M_topboot = { + .total_size = 0x800000, + .nregions = 2, + .regions = {0x10000, 127, 0x2000, 8}, + .total_sectors = 135, +}; + +static struct flash_geom geom_8M_bottomboot = { + .total_size = 0x800000, + .nregions = 2, + .regions = {0x2000, 8, 0x10000, 127}, + .total_sectors = 135, +}; + +static struct flash_geom geom_8M_topboot_big = { + .total_size = 0x800000, + .nregions = 2, + .regions = {0x40000, 31, 0x10000, 4}, + .total_sectors = 35, +}; + +static struct flash_geom geom_8M_bottomboot_big = { + .total_size = 0x800000, + .nregions = 2, + .regions = {0x10000, 4, 0x40000, 31}, + .total_sectors = 35, +}; + +/* Intel and compatible flash chips */ + +static struct cfi_check intel_2M_topboot_cfi[] = { + {0x10, 'Q'}, + {0x11, 'R'}, + {0x12, 'Y'}, + {0x13, 0x03}, + {0x14, 0x00}, + {0x27, 0x15}, + {0x2C, 0x02}, + {0x2D, 0x1E}, + {0x2E, 0x00}, + {0x2F, 0x00}, + {0x30, 0x01}, + {0x31, 0x07}, + {0x32, 0x00}, + {0x33, 0x20}, + {0x34, 0x00}, + {-1, 0} +}; + +static struct cfi_check intel_4M_topboot_cfi[] = { + {0x10, 'Q'}, + {0x11, 'R'}, + {0x12, 'Y'}, + {0x13, 0x03}, + {0x14, 0x00}, + {0x27, 0x16}, + {0x2C, 0x02}, + {0x2D, 0x3E}, + {0x2E, 0x00}, + {0x2F, 0x00}, + {0x30, 0x01}, + {0x31, 0x07}, + {0x32, 0x00}, + {0x33, 0x20}, + {0x34, 0x00}, + {-1, 0} +}; + +static struct cfi_check intel_8M_topboot_cfi[] = { + {0x10, 'Q'}, + {0x11, 'R'}, + {0x12, 'Y'}, + {0x13, 0x03}, + {0x14, 0x00}, + {0x27, 0x17}, + {0x2C, 0x02}, + {0x2D, 0x7E}, + {0x2E, 0x00}, + {0x2F, 0x00}, + {0x30, 0x01}, + {0x31, 0x07}, + {0x32, 0x00}, + {0x33, 0x20}, + {0x34, 0x00}, + {-1, 0} +}; + +static struct cfi_check intel_8M_bottomboot_cfi[] = { + {0x10, 'Q'}, + {0x11, 'R'}, + {0x12, 'Y'}, + {0x13, 0x03}, + {0x14, 0x00}, + {0x27, 0x17}, + {0x2C, 0x02}, + {0x2D, 0x07}, + {0x2E, 0x00}, + {0x2F, 0x20}, + {0x30, 0x00}, + {0x31, 0x7E}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x01}, + {-1, 0} +}; + +struct flash_device flashdev_28F160C3T = { + .name = "Intel 28F160C3T", + .cfi_table = intel_2M_topboot_cfi, + .required_global_config = FLASH_GLOBAL_CFG_SINGLE_4M, + .bank_geom = {&geom_2M_topboot, 0}, + .cmdset = &flash_cmdset_intel, +}; + +struct flash_device flashdev_28F320C3T = { + .name = "Intel 28F320C3T", + .cfi_table = intel_4M_topboot_cfi, + .required_global_config = FLASH_GLOBAL_CFG_SINGLE_4M, + .bank_geom = {&geom_4M_topboot, 0}, + .cmdset = &flash_cmdset_intel, +}; + +struct flash_device flashdev_28F640C3T = { + .name = "Intel 28F640C3T", + .cfi_table = intel_8M_topboot_cfi, + .required_global_config = FLASH_GLOBAL_CFG_SINGLE_8M, + .bank_geom = {&geom_8M_topboot, 0}, + .cmdset = &flash_cmdset_intel, +}; + +struct flash_device flashdev_28F640C3B = { + .name = "Intel 28F640C3B", + .cfi_table = intel_8M_bottomboot_cfi, + .required_global_config = FLASH_GLOBAL_CFG_SINGLE_8M, + .bank_geom = {&geom_8M_bottomboot, 0}, + .cmdset = &flash_cmdset_intel, +}; + +struct flash_device flashdev_28F640W30T = { + .name = "Intel 28F640W30T", + .cfi_table = intel_8M_topboot_cfi, + .required_global_config = FLASH_GLOBAL_CFG_SINGLE_8M, + .bank_geom = {&geom_8M_topboot, 0}, + .cmdset = &flash_cmdset_intel_w30, +}; + +struct flash_device flashdev_28F640W30B = { + .name = "Intel 28F640W30B", + .cfi_table = intel_8M_bottomboot_cfi, + .required_global_config = FLASH_GLOBAL_CFG_SINGLE_8M, + .bank_geom = {&geom_8M_bottomboot, 0}, + .cmdset = &flash_cmdset_intel_w30, +}; + +/* Spansion S71PL-J and S71PL-N flash */ + +static struct cfi_check spansion_PL129J_cfi[] = { + {0x10, 'Q'}, + {0x11, 'R'}, + {0x12, 'Y'}, + {0x13, 0x02}, + {0x14, 0x00}, + {0x15, 0x40}, + {0x16, 0x00}, + {0x27, 0x18}, + {0x2C, 0x03}, + {0x2D, 0x07}, + {0x2E, 0x00}, + {0x2F, 0x20}, + {0x30, 0x00}, + {0x31, 0xFD}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x01}, + {0x35, 0x07}, + {0x36, 0x00}, + {0x37, 0x20}, + {0x38, 0x00}, + {0x40, 'P'}, + {0x41, 'R'}, + {0x42, 'I'}, + {0x43, '1'}, + {0x44, '3'}, + {-1, 0} +}; + +struct flash_device flashdev_PL129J = { + .name = "Spansion S29PL129J", + .cfi_table = spansion_PL129J_cfi, + .required_global_config = FLASH_GLOBAL_CFG_DUAL_8M, + .bank_geom = {&geom_8M_bottomboot, &geom_8M_topboot}, + .cmdset = &flash_cmdset_amd, +}; + +static struct cfi_check spansion_PL129N_cfi[] = { + {0x10, 'Q'}, + {0x11, 'R'}, + {0x12, 'Y'}, + {0x13, 0x02}, + {0x14, 0x00}, + {0x15, 0x40}, + {0x16, 0x00}, + {0x27, 0x18}, + {0x2C, 0x03}, + {0x2D, 0x03}, + {0x2E, 0x00}, + {0x2F, 0x00}, + {0x30, 0x01}, + {0x31, 0x3D}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x04}, + {0x35, 0x03}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x01}, + {0x40, 'P'}, + {0x41, 'R'}, + {0x42, 'I'}, + {0x43, '1'}, + {0x44, '4'}, + {-1, 0} +}; + +struct flash_device flashdev_PL129N = { + .name = "Spansion S29PL129N", + .cfi_table = spansion_PL129N_cfi, + .required_global_config = FLASH_GLOBAL_CFG_DUAL_8M, + .bank_geom = {&geom_8M_bottomboot_big, + &geom_8M_topboot_big}, + .cmdset = &flash_cmdset_amd, +}; + +/* Samsung K5A32xxCTM introduced onto the scene by Openmoko */ + +static struct cfi_check samsung_4M_topboot_cfi[] = { + {0x10, 'Q'}, + {0x11, 'R'}, + {0x12, 'Y'}, + {0x13, 0x02}, + {0x14, 0x00}, + {0x15, 0x40}, + {0x16, 0x00}, + {0x27, 0x16}, + {0x2C, 0x02}, + {0x2D, 0x07}, + {0x2E, 0x00}, + {0x2F, 0x20}, + {0x30, 0x00}, + {0x31, 0x3E}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x01}, + {0x40, 'P'}, + {0x41, 'R'}, + {0x42, 'I'}, + {0x43, '3'}, + {0x44, '3'}, + {0x4F, 0x03}, + {-1, 0} +}; + +struct flash_device flashdev_K5A32xx_T = { + .name = "Samsung K5A32xx_T", + .cfi_table = samsung_4M_topboot_cfi, + .required_global_config = FLASH_GLOBAL_CFG_SINGLE_4M, + .bank_geom = {&geom_4M_topboot, 0}, + .cmdset = &flash_cmdset_amd, +}; diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flmain.c --- a/loadtools/flmain.c Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/flmain.c Tue May 28 05:12:47 2019 +0000 @@ -11,185 +11,10 @@ #include #include "flash.h" -/* K5A32xx device description */ - -static struct flash_geom k5a32xx_topboot_geom = { - .total_size = 0x400000, - .nregions = 2, - .regions = {0x10000, 63, 0x2000, 8}, - .total_sectors = 71, -}; - -static struct flash_idcheck k5a32xx_topboot_idcheck[2] = { - {0x00, 0x00EC}, - {0x02, 0x22A0} -}; - -static struct flash_bank_desc k5a32xx_topboot_bankdesc = { - 0x400000, &k5a32xx_topboot_geom, k5a32xx_topboot_idcheck, 2 -}; - -/* S{29,71}PL129N device description */ - -static struct flash_geom pl129n_ce1_geom = { - .total_size = 0x800000, - .nregions = 2, - .regions = {0x10000, 4, 0x40000, 31}, - .total_sectors = 35, -}; - -static struct flash_geom pl129n_ce2_geom = { - .total_size = 0x800000, - .nregions = 2, - .regions = {0x40000, 31, 0x10000, 4}, - .total_sectors = 35, -}; - -static struct flash_idcheck pl129n_idcheck[4] = { - {0x00, 0x0001}, - {0x02, 0x227E}, - {0x1C, 0x2221}, - {0x1E, 0x2200} -}; - -static struct flash_bank_desc pl129n_banks[2] = { - {0x800000, &pl129n_ce1_geom, pl129n_idcheck, 4}, - {0x800000, &pl129n_ce2_geom, pl129n_idcheck, 4} -}; - -/* 28F640W30B device description */ - -static struct flash_geom f640w30b_geom = { - .total_size = 0x800000, - .nregions = 2, - .regions = {0x2000, 8, 0x10000, 127}, - .total_sectors = 135, -}; - -static struct flash_idcheck f640w30b_idcheck[2] = { - {0x00, 0x0089}, - {0x02, 0x8855} -}; - -static struct flash_bank_desc f640w30b_bankdesc = { - 0x800000, &f640w30b_geom, f640w30b_idcheck, 2 -}; - -/* bank configurations for CFI */ - -static struct flash_bank_desc cfi_4M_bankdesc = { - 0x400000, 0, 0, 0 -}; - -static struct flash_bank_desc cfi_8M_bankdesc = { - 0x800000, 0, 0, 0 -}; - -/* list of supported flash devices */ - -extern struct flash_cmdset flash_cmdset_amd; -extern struct flash_cmdset flash_cmdset_intel_w30; - -struct flash_device_desc flash_device_list[] = { - {"cfi-4M", &cfi_4M_bankdesc, 1, 0}, - {"cfi-8M", &cfi_8M_bankdesc, 1, 0}, - {"k5a32xx_t", &k5a32xx_topboot_bankdesc, 1, &flash_cmdset_amd}, - {"pl129n", pl129n_banks, 2, &flash_cmdset_amd}, - {"28f640w30b", &f640w30b_bankdesc, 1, &flash_cmdset_intel_w30}, - {0, 0, 0, 0} /* array terminator */ -}; - -/* the following variables describe our selected flash device */ +extern int flash_global_config; +extern struct flash_bank_info flash_bank_info[2]; -struct flash_device_desc *selected_flash_device; -struct flash_bank_info flash_bank_info[2]; - -/* called from hwparam.c config file parser */ -void -set_flash_device(arg, filename_for_errs, lineno_for_errs) - char *arg; - char *filename_for_errs; - int lineno_for_errs; -{ - char *cp, *np, *ep; - struct flash_device_desc *tp; - int bank; - struct flash_bank_info *bi; - - if (selected_flash_device) { - fprintf(stderr, "%s line %d: duplicate flash setting\n", - filename_for_errs, lineno_for_errs); - exit(1); - } - for (cp = arg; isspace(*cp); cp++) - ; - if (!*cp || *cp == '#') { -too_few_arg: fprintf(stderr, - "%s line %d: flash setting: too few arguments\n", - filename_for_errs, lineno_for_errs); - exit(1); - } - for (np = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - for (tp = flash_device_list; tp->name; tp++) - if (!strcmp(tp->name, np)) - break; - if (!tp->name) { - fprintf(stderr, - "%s line %d: unknown flash device \"%s\"\n", - filename_for_errs, lineno_for_errs, np); - exit(1); - } - selected_flash_device = tp; - - /* now initialize flash_bank_info */ - for (bank = 0; bank < selected_flash_device->nbanks; bank++) { - while (isspace(*cp)) - cp++; - if (!*cp || *cp == '#') - goto too_few_arg; - for (np = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - bi = flash_bank_info + bank; - bi->base_addr = strtoul(np, &ep, 16); - if (*ep) { - fprintf(stderr, -"%s line %d: syntax error (base addr expected after flash device type)\n", - filename_for_errs, lineno_for_errs); - exit(1); - } - /* the rest comes from the flash device type */ - bi->bank_desc = selected_flash_device->bank_desc + bank; - 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->bank_desc->align_size); - exit(1); - } - bi->geom = bi->bank_desc->geom; - bi->ops = selected_flash_device->cmdset; - } - while (isspace(*cp)) - cp++; - if (*cp && *cp != '#') { - fprintf(stderr, - "%s line %d: flash setting: too many arguments\n", - filename_for_errs, lineno_for_errs); - exit(1); - } -} - -flashcmd_help() -{ - return loadtool_help("flash"); -} - -flashcmd_info(argc, argv, bank) +flashcmd_geom(argc, argv, bank) char **argv; { struct flash_bank_info *bi; @@ -198,19 +23,65 @@ fprintf(stderr, "error: too many arguments\n"); return(-1); } + if (flash_detect(bank, 0) < 0) + return(-1); 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); - if (flash_get_cfi(bank) < 0) - return(-1); + if (bi->device->bank_geom[1]) + printf("Device has two banks, looking at bank %d\n", bank); + else + printf("Single-bank flash device\n"); printf("Bank %d total size: %lx\n", bank, (u_long) bi->geom->total_size); printf("Sectors in bank %d: %u (%u regions)\n", bank, bi->geom->total_sectors, bi->geom->nregions); printf("Command set style: %s\n", bi->ops->cmdset_name); - flash_id_check(bank, 1); - if (selected_flash_device->nbanks == 2 && !bank) - printf("\nFlash device has 2 banks; flash2 command available\n"); + return(0); +} + +flashcmd_help() +{ + return loadtool_help("flash"); +} + +flashcmd_id(argc, argv, bank) + char **argv; +{ + if (argc > 2) { + fprintf(stderr, "error: too many arguments\n"); + return(-1); + } + return flash_detect(bank, 1); +} + +flashcmd_info(argc, argv) + char **argv; +{ + int bank, nbanks; + + if (argc > 2) { + fprintf(stderr, "error: too many arguments\n"); + return(-1); + } + switch (flash_global_config) { + case FLASH_GLOBAL_CFG_SINGLE_4M: + printf("Configured for a single flash bank of up to 4 MiB\n"); + nbanks = 1; + break; + case FLASH_GLOBAL_CFG_SINGLE_8M: + printf("Configured for a single flash bank of up to 8 MiB\n"); + nbanks = 1; + break; + case FLASH_GLOBAL_CFG_DUAL_8M: + printf("Configured for two flash banks of up to 8 MiB each\n"); + nbanks = 2; + break; + default: + fprintf(stderr, "error: invalid global config\n"); + return(-1); + } + for (bank = 0; bank < nbanks; bank++) + printf("Bank %d base address: %08lX\n", bank, + (u_long) flash_bank_info[bank].base_addr); return(0); } @@ -236,7 +107,9 @@ {"dump2srec", flashcmd_dump2file}, {"erase", flashcmd_erase}, {"erase-program-boot", flashcmd_erase_program_boot}, + {"geom", flashcmd_geom}, {"help", flashcmd_help}, + {"id", flashcmd_id}, {"info", flashcmd_info}, {"program-bin", flashcmd_progbin}, {"program-m0", flashcmd_program_m0}, @@ -255,14 +128,13 @@ int bank; struct cmdtab *tp; - if (!selected_flash_device) { + if (!flash_global_config) { fprintf(stderr, "No flash configuration defined\n"); return(-1); } if (argv[0][5] == '2') { - if (selected_flash_device->nbanks < 2) { - fprintf(stderr, "Flash device %s has only one bank\n", - selected_flash_device->name); + if (flash_global_config != FLASH_GLOBAL_CFG_DUAL_8M) { + fprintf(stderr, "No second flash bank configured\n"); return(-1); } bank = 1; diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flmisc.c --- a/loadtools/flmisc.c Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/flmisc.c Tue May 28 05:12:47 2019 +0000 @@ -28,7 +28,7 @@ offset = strtoul(argv[2], &strtoul_endp, 16); if (*strtoul_endp) goto inv; - if (flash_get_cfi(bank) < 0) + if (flash_detect(bank, 0) < 0) return(-1); bi = flash_bank_info + bank; if (offset >= bi->geom->total_size) { @@ -74,7 +74,7 @@ argv[0], argv[1]); return(-1); } - if (flash_get_cfi(bank) < 0) + if (flash_detect(bank, 0) < 0) return(-1); bi = flash_bank_info + bank; if (argc >= 4) { @@ -138,7 +138,7 @@ offset = strtoul(argv[2], &strtoul_endp, 16); if (*strtoul_endp) goto inv; - if (flash_get_cfi(bank) < 0) + if (flash_detect(bank, 0) < 0) return(-1); bi = flash_bank_info + bank; if (offset >= bi->geom->total_size) { @@ -165,9 +165,6 @@ return(-1); if (get_flash_sector_range(bi, offset, len, &startsec, &endsec) < 0) return(-1); - stat = flash_id_check(bank, 0); - if (stat) - return(stat); printf("Erasing %d sector(s)\n", endsec - startsec); for (sp = startsec; sp < endsec; sp++) { stat = bi->ops->erase_sector(bi, sp); @@ -192,7 +189,7 @@ argv[0], argv[1]); return(-1); } - if (flash_get_cfi(bank) < 0) + if (flash_detect(bank, 0) < 0) return(-1); bi = flash_bank_info + bank; sprintf(targ_base, "%lx", (u_long) bi->base_addr); @@ -228,7 +225,7 @@ fprintf(stderr, "error: too many arguments\n"); return(-1); } - if (flash_get_cfi(bank) < 0) + if (flash_detect(bank, 0) < 0) return(-1); bi = flash_bank_info + bank; return bi->ops->reset_cmd(bi); @@ -243,7 +240,7 @@ fprintf(stderr, "error: too many arguments\n"); return(-1); } - if (flash_get_cfi(bank) < 0) + if (flash_detect(bank, 0) < 0) return(-1); bi = flash_bank_info + bank; return bi->ops->status_cmd(bi); @@ -258,12 +255,12 @@ struct sector_info *startsec, *endsec, *sp; int stat; - if (flash_get_cfi(bank) < 0) + if (flash_detect(bank, 0) < 0) return(-1); bi = flash_bank_info + bank; if (!bi->ops->needs_unlock) { fprintf(stderr, - "This operation is not applicable to the selected flash type\n"); + "This operation is not applicable to AMD-style flash\n"); return(-1); } if (argc != 4) { diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flprogbin.c --- a/loadtools/flprogbin.c Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/flprogbin.c Tue May 28 05:12:47 2019 +0000 @@ -38,7 +38,7 @@ flashoff = strtoul(argv[2], &strtoul_endp, 16); if (*strtoul_endp) goto inv; - if (flash_get_cfi(bank) < 0) + if (flash_detect(bank, 0) < 0) return(-1); bi = flash_bank_info + bank; if (flashoff >= bi->geom->total_size) { @@ -109,10 +109,6 @@ } /* finally done with the arg parsing etc, can get to work now */ - if (flash_id_check(bank, 0) < 0) { - fclose(binf); - return(-1); - } crc_base_addr = bi->base_addr + flashoff; sprintf(shortarg, "%lx", (u_long) bi->base_addr); targv[0] = bi->ops->loadagent_setbase_cmd; diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flprogsrec.c --- a/loadtools/flprogsrec.c Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/flprogsrec.c Tue May 28 05:12:47 2019 +0000 @@ -21,18 +21,13 @@ int resp; unsigned long rec_count; - if (flash_get_cfi(bank) < 0) + if (flash_detect(bank, 0) < 0) return(-1); bi = flash_bank_info + bank; srr.filename = imgfile; resp = open_srec_file(&srr); if (resp < 0) return(resp); - resp = flash_id_check(bank, 0); - if (resp) { - fclose(srr.openfile); - return(resp); - } sprintf(shortarg, "%lx", (u_long) bi->base_addr); targv[0] = bi->ops->loadagent_setbase_cmd; targv[1] = shortarg; diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/flutil.c --- a/loadtools/flutil.c Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/flutil.c Tue May 28 05:12:47 2019 +0000 @@ -9,167 +9,6 @@ #include "flash.h" extern struct flash_bank_info flash_bank_info[2]; -extern struct flash_cmdset flash_cmdset_amd; -extern struct flash_cmdset flash_cmdset_intel; - -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); -} - -flash_get_cfi(bank) -{ - struct flash_bank_info *bi; - struct flash_geom *geom; - struct flash_region_desc *reg; - int nr; - uint16_t rdval, cmdset_id; - uint32_t size_check; - - bi = flash_bank_info + bank; - if (bi->geom) - return(0); - 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"); - amd_reset_cmd(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; - if (cfi_read_twobyte(bi, 0x13, &cmdset_id) < 0) - return(-1); - if (!bi->ops) { - switch (cmdset_id) { - case 2: - bi->ops = &flash_cmdset_amd; - break; - case 3: - bi->ops = &flash_cmdset_intel; - break; - default: - fprintf(stderr, "error: command set %04X unsupported\n", - cmdset_id); - amd_reset_cmd(bi); - return(-1); - } - } - geom = malloc(sizeof(struct flash_geom)); - if (!geom) { - fprintf(stderr, - "unable to malloc buffer for flash bank %d CFI geometry structure\n", - bank); - bi->ops->reset_cmd(bi); - return(-1); - } - /* total device size */ - if (cfi_read_byte(bi, 0x27, &rdval) < 0) { -free_and_immed_out: - free(geom); - return(-1); - } - if (rdval < 20 || rdval > 24) { - fprintf(stderr, - "error: CFI reports unreasonable device size\n"); -free_and_clean_out: - free(geom); - bi->ops->reset_cmd(bi); - return(-1); - } - geom->total_size = 1 << rdval; - if (geom->total_size > bi->bank_desc->align_size) { - fprintf(stderr, - "error: CFI device size 0x%lx exceeds configured maximum 0x%lx\n", - (u_long) geom->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; - } - geom->nregions = rdval; - geom->total_sectors = 0; - size_check = 0; - for (nr = 0; nr < geom->nregions; nr++) { - reg = geom->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; - geom->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 (bi->ops->reset_cmd(bi) < 0) { - /* error msg already printed */ - free(geom); - return(-1); - } - if (size_check != geom->total_size) { - fprintf(stderr, -"CFI error: added size of erase regions (%lx) != reported device size (%lx)\n", - (u_long) size_check, (u_long) geom->total_size); - free(geom); - return(-1); - } - /* all checks passed */ - bi->geom = geom; - printf( -"CFI query successful: total size %lx, %u sectors, command set style %04X\n", - (u_long) geom->total_size, geom->total_sectors, cmdset_id); - return(1); -} get_flash_sector_table(bank) { @@ -183,7 +22,7 @@ bi = flash_bank_info + bank; if (bi->sectors) return(0); - i = flash_get_cfi(bank); + i = flash_detect(bank, 0); if (i < 0) return(i); geom = bi->geom; @@ -291,57 +130,3 @@ } *s = '\0'; } - -flash_id_check(bank, repeat) -{ - struct flash_bank_info *bi; - struct flash_bank_desc *bd; - struct flash_idcheck *id; - int stat, fail; - uint16_t rdval; - unsigned cnt; - - 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) { -bad_w16: fprintf(stderr, - "unexpected response to w16 in read ID cmd sequence - aborting\n"); - return(-1); - } - stat = do_w16(bi->base_addr + 0x554, 0x55); - if (stat) - goto bad_w16; - stat = do_w16(bi->base_addr + 0xAAA, 0x90); - if (stat) - goto bad_w16; - id = bd->idcheck_table; - fail = 0; - for (cnt = 0; cnt < bd->idcheck_num; cnt++) { - stat = do_r16(bi->base_addr + id->offset, &rdval); - if (stat) - return(stat); /* error msg already printed */ - printf("offset %02X: %04X -- ", (int)id->offset, (int)rdval); - if (rdval == id->expect_val) - printf("PASS\n"); - else { - printf("FAIL: expected %04X\n", (int)id->expect_val); - fail = 1; - break; - } - id++; - } - if (fail) - return(-1); - if (bi->ops->reset_cmd(bi) < 0) { - /* error msg already printed */ - return(-1); - } - bi->idcheck_done = 1; - return(0); -} diff -r 7bf0d909c87e -r 0dd2c87c1b63 loadtools/hwparam.c --- a/loadtools/hwparam.c Mon May 27 19:58:01 2019 +0000 +++ b/loadtools/hwparam.c Tue May 28 05:12:47 2019 +0000 @@ -14,7 +14,7 @@ extern void set_boot_reflash_hack(); extern void set_default_exit_mode(); -extern void set_flash_device(); +extern void set_flash_config(); char hw_init_script[128]; @@ -133,7 +133,7 @@ {"boot-reflash-hack", set_boot_reflash_hack}, {"compal-stage", handle_compal_stage}, {"exit-mode", set_default_exit_mode}, - {"flash", set_flash_device}, + {"flash", set_flash_config}, {"init-script", handle_init_script}, {"pll-config", handle_pll_config}, {"rhea-cntl", handle_rhea_cntl},