FreeCalypso > hg > freecalypso-sw
diff loadtools/flmain.c @ 405:a212b4968b29
fc-loadtool flash: another refactoring: geometry vs. command set
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Tue, 17 Jun 2014 00:33:05 +0000 |
parents | loadtools/ltflash.c@7ceeec049be4 |
children | 0b8e5072abde |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadtools/flmain.c Tue Jun 17 00:33:05 2014 +0000 @@ -0,0 +1,251 @@ +/* + * This module is the main entry point for fc-loadtool flash functions + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#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} +}; + +/* 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; + +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}, + {0, 0, 0, 0} /* array terminator */ +}; + +/* the following variables describe our selected flash device */ + +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) + char **argv; +{ + struct flash_bank_info *bi; + + if (argc > 2) { + fprintf(stderr, "error: too many arguments\n"); + 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); + 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); +} + +extern int flashcmd_blankchk(); +extern int flashcmd_dump2file(); +extern int flashcmd_erase(); +extern int flashcmd_progbin(); +extern int flashcmd_program_m0(); +extern int flashcmd_program_srec(); +extern int flashcmd_quickprog(); +extern int flashcmd_sectors(); + +static struct cmdtab { + char *cmd; + int (*func)(); +} cmdtab[] = { + {"blankchk", flashcmd_blankchk}, + {"dump2bin", flashcmd_dump2file}, + {"dump2srec", flashcmd_dump2file}, + {"erase", flashcmd_erase}, + {"help", flashcmd_help}, + {"info", flashcmd_info}, + {"program-bin", flashcmd_progbin}, + {"program-m0", flashcmd_program_m0}, + {"program-srec", flashcmd_program_srec}, + {"quickprog", flashcmd_quickprog}, + {"sectors", flashcmd_sectors}, + {0, 0} +}; + +cmd_flash(argc, argv) + char **argv; +{ + int bank; + struct cmdtab *tp; + + if (!selected_flash_device) { + 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); + return(-1); + } + bank = 1; + } else + bank = 0; + for (tp = cmdtab; tp->cmd; tp++) + if (!strcmp(tp->cmd, argv[1])) + break; + if (!tp->func) { + fprintf(stderr, "%s %s: unknown/unimplemented subcommand\n", + argv[0], argv[1]); + return(-1); + } + return tp->func(argc, argv, bank); +}