view loadtools/flmain.c @ 923:10b4bed10192

gsm-fw/L1: fix for the DSP patch corruption bug The L1 code we got from the LoCosto fw contains a feature for DSP CPU load measurement. This feature is a LoCosto-ism, i.e., not applicable to earlier DBB chips (Calypso) with their respective earlier DSP ROMs. Most of the code dealing with that feature is conditionalized as #if (DSP >= 38), but one spot was missed, and the MCU code was writing into an API word dealing with this feature. In TCS211 this DSP API word happens to be used by the DSP code patch, hence that write was corrupting the patched DSP code.
author Mychaela Falconia <falcon@ivan.Harhan.ORG>
date Mon, 19 Oct 2015 17:13:56 +0000
parents b2487cfd68fd
children
line wrap: on
line source

/*
 * This module is the main entry point for fc-loadtool flash functions
 */

#include <sys/types.h>
#include <ctype.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_erase_program_boot();
extern int flashcmd_progbin();
extern int flashcmd_program_m0();
extern int flashcmd_program_srec();
extern int flashcmd_quickprog();
extern int flashcmd_reset();
extern int flashcmd_sectors();
extern int flashcmd_status();
extern int flashcmd_unlock();

static struct cmdtab {
	char *cmd;
	int (*func)();
} cmdtab[] = {
	{"blankchk", flashcmd_blankchk},
	{"dump2bin", flashcmd_dump2file},
	{"dump2srec", flashcmd_dump2file},
	{"erase", flashcmd_erase},
	{"erase-program-boot", flashcmd_erase_program_boot},
	{"help", flashcmd_help},
	{"info", flashcmd_info},
	{"program-bin", flashcmd_progbin},
	{"program-m0", flashcmd_program_m0},
	{"program-srec", flashcmd_program_srec},
	{"quickprog", flashcmd_quickprog},
	{"reset", flashcmd_reset},
	{"sectors", flashcmd_sectors},
	{"status", flashcmd_status},
	{"unlock", flashcmd_unlock},
	{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);
}