target/sam3x: rework gpnvm command

Signed-off-by: Rafael Silva <perigoso@riseup.net>
This commit is contained in:
Rafael Silva 2022-05-24 22:52:08 +01:00 committed by Rachel Mant
parent cf6ce32371
commit dcc450a494
1 changed files with 79 additions and 32 deletions

View File

@ -35,12 +35,10 @@ static int sam_flash_write(struct target_flash *f, target_addr dest,
static uint32_t sam_gpnvm_get(target *t, uint32_t base);
static bool sam_cmd_gpnvm_get(target *t, int argc, const char **argv);
static bool sam_cmd_gpnvm_set(target *t, int argc, const char **argv);
static bool sam_cmd_gpnvm(target *t, int argc, const char **argv);
const struct command_s sam_cmd_list[] = {
{"gpnvm_get", (cmd_handler)sam_cmd_gpnvm_get, "Get GPVNM value"},
{"gpnvm_set", (cmd_handler)sam_cmd_gpnvm_set, "Set GPVNM bit"},
{"gpnvm", (cmd_handler)sam_cmd_gpnvm, "Set/Get GPVNM bits"},
{NULL, NULL, NULL}
};
@ -166,6 +164,14 @@ const struct command_s sam_cmd_list[] = {
#define GPNVM_SAMX7X_TCM_64K (0x2 << GPNVM_SAMX7X_TCM_BIT_OFFSET)
#define GPNVM_SAMX7X_TCM_128K (0x3 << GPNVM_SAMX7X_TCM_BIT_OFFSET)
enum sam_driver {
DRIVER_SAM3X,
DRIVER_SAM3U,
DRIVER_SAM4S,
DRIVER_SAM3NS,
DRIVER_SAMX7X,
};
struct sam_flash {
struct target_flash f;
uint32_t eefc_base;
@ -504,21 +510,21 @@ sam_flash_cmd(target *t, uint32_t base, uint8_t cmd, uint16_t arg)
return sr & EEFC_FSR_ERROR;
}
static uint32_t sam_flash_base(target *t)
static enum sam_driver sam_driver(target *t)
{
if (strcmp(t->driver, "Atmel SAM3X") == 0) {
return SAM3X_EEFC_BASE(0);
return DRIVER_SAM3X;
}
if (strcmp(t->driver, "Atmel SAM3U") == 0) {
return SAM3U_EEFC_BASE(0);
return DRIVER_SAM3U;
}
if (strcmp(t->driver, "Atmel SAM4S") == 0) {
return SAM4S_EEFC_BASE(0);
return DRIVER_SAM4S;
}
if (strcmp(t->driver, "Atmel SAM3N/S") == 0) {
return SAM3N_EEFC_BASE;
return DRIVER_SAM3NS;
}
return SAMX7X_EEFC_BASE;
return DRIVER_SAMX7X;
}
static int sam_flash_erase(struct target_flash *f, target_addr addr, size_t len)
@ -577,31 +583,72 @@ static uint32_t sam_gpnvm_get(target *t, uint32_t base)
return target_mem_read32(t, EEFC_FRR(base));
}
static bool sam_cmd_gpnvm_get(target *t, int argc, const char **argv)
static bool sam_cmd_gpnvm(target *t, int argc, const char **argv)
{
(void)argc;
(void)argv;
if (argc != 2 && argc != 4) {
goto bad_usage;
}
uint8_t arglen = strlen(argv[1]);
if (arglen == 0) {
goto bad_usage;
}
uint32_t base, gpnvm_mask;
switch(sam_driver(t)) {
case DRIVER_SAM3X:
gpnvm_mask = 0x7;
base = SAM3X_EEFC_BASE(0);
break;
case DRIVER_SAM3U:
gpnvm_mask = 0x7;
base = SAM3U_EEFC_BASE(0);
break;
case DRIVER_SAM4S:
gpnvm_mask = 0x7;
base = SAM4S_EEFC_BASE(0);
break;
case DRIVER_SAM3NS:
gpnvm_mask = 0x3;
base = SAM3N_EEFC_BASE;
break;
case DRIVER_SAMX7X:
gpnvm_mask = 0x1BF;
base = SAMX7X_EEFC_BASE;
break;
}
if (strncmp(argv[1], "get", arglen) == 0) {
/* nothing to do */
} else if (strncmp(argv[1], "set", arglen) == 0) {
char *eos;
uint32_t mask = strtoul(argv[2], &eos, 0);
uint32_t values = strtoul(argv[3], &eos, 0);
if (mask == 0 || mask & ~gpnvm_mask) {
/* trying to write invalid bits */
goto bad_usage;
}
for (uint16_t bit = 0; mask > 0; bit++)
{
if (mask & 1) {
uint8_t cmd = (values & 1) ? EEFC_FCR_FCMD_SGPB : EEFC_FCR_FCMD_CGPB;
sam_flash_cmd(t, base, cmd, bit);
}
mask >>= 1;
values >>= 1;
}
} else {
goto bad_usage;
}
uint32_t base = sam_flash_base(t);
tc_printf(t, "GPNVM: 0x%08X\n", sam_gpnvm_get(t, base));
return true;
}
static bool sam_cmd_gpnvm_set(target *t, int argc, const char **argv)
{
uint32_t bit, cmd;
uint32_t base = sam_flash_base(t);
if (argc != 3) {
tc_printf(t, "usage: monitor gpnvm_set <bit> <val>\n");
return false;
}
bit = atol(argv[1]);
cmd = atol(argv[2]) ? EEFC_FCR_FCMD_SGPB : EEFC_FCR_FCMD_CGPB;
sam_flash_cmd(t, base, cmd, bit);
sam_cmd_gpnvm_get(t, 0, NULL);
return true;
bad_usage:
tc_printf(t, "usage: monitor gpnvm get\n");
tc_printf(t, "usage: monitor gpnvm set <bit> <val>\n");
return false;
}