enable capacity overriding

We have different-sized SPI flash chips, so when possible set the
capacity based on various id codes.

Also allow for manually overriding capacity with the -b option.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2018-12-19 00:00:25 -05:00
parent 9b1b9b8a88
commit 27dec515e7
3 changed files with 55 additions and 11 deletions

View File

@ -132,12 +132,13 @@ static int print_help(FILE *stream, const char *progname) {
fprintf(stream, "Fomu Raspberry Pi Flash Utilities\n"); fprintf(stream, "Fomu Raspberry Pi Flash Utilities\n");
fprintf(stream, "Usage:\n"); fprintf(stream, "Usage:\n");
fprintf(stream, "%15s (-[hri] | [-p offset] | [-f bin] | [-w bin] | [-v bin] | [-s out] | [-k n[:f]])\n", progname); fprintf(stream, "%15s (-[hri] | [-p offset] | [-f bin] | [-w bin] | [-v bin] | [-s out] | [-k n[:f]])\n", progname);
fprintf(stream, " [-g pinspec] [-t spitype] [-r]\n"); fprintf(stream, " [-g pinspec] [-t spitype] [-b bytes]\n");
fprintf(stream, "Program mode (pick one):\n"); fprintf(stream, "Program mode (pick one):\n");
print_program_modes(stream); print_program_modes(stream);
fprintf(stream, "Configuration options:\n"); fprintf(stream, "Configuration options:\n");
fprintf(stream, " -g ps Set the pin assignment with the given pinspec\n"); fprintf(stream, " -g ps Set the pin assignment with the given pinspec\n");
fprintf(stream, " -t type Set the number of bits to use for SPI (1, 2, 4, or Q)\n"); fprintf(stream, " -t type Set the number of bits to use for SPI (1, 2, 4, or Q)\n");
fprintf(stream, " -b bytes Override the size of the SPI flash, in bytes\n");
fprintf(stream, "You can remap various pins with -g. The format is [name]:[number].\n"); fprintf(stream, "You can remap various pins with -g. The format is [name]:[number].\n");
fprintf(stream, "\n"); fprintf(stream, "\n");
fprintf(stream, "The width of SPI can be set with 't [width]'. Valid widths are:\n"); fprintf(stream, "The width of SPI can be set with 't [width]'. Valid widths are:\n");
@ -163,6 +164,7 @@ int main(int argc, char **argv) {
struct ff_spi *spi; struct ff_spi *spi;
struct ff_fpga *fpga; struct ff_fpga *fpga;
int peek_offset = 0; int peek_offset = 0;
int spi_flash_bytes = -1;
uint8_t security_reg; uint8_t security_reg;
uint8_t security_val[256]; uint8_t security_val[256];
enum op op = OP_UNKNOWN; enum op op = OP_UNKNOWN;
@ -191,7 +193,7 @@ int main(int argc, char **argv) {
return 1; return 1;
} }
while ((opt = getopt(argc, argv, "hip:rf:w:s:2:3:v:g:t:k:")) != -1) { while ((opt = getopt(argc, argv, "hip:rf:b:w:s:2:3:v:g:t:k:")) != -1) {
switch (opt) { switch (opt) {
case 'r': case 'r':
@ -200,6 +202,10 @@ int main(int argc, char **argv) {
op = OP_FPGA_RESET; op = OP_FPGA_RESET;
break; break;
case 'b':
spi_flash_bytes = strtoul(optarg, NULL, 0);
break;
case 'k': { case 'k': {
if (op != OP_UNKNOWN) if (op != OP_UNKNOWN)
return print_usage_error(stdout); return print_usage_error(stdout);
@ -332,6 +338,9 @@ int main(int argc, char **argv) {
spiSetType(spi, spi_type); spiSetType(spi, spi_type);
fpgaReset(fpga); fpgaReset(fpga);
if (spi_flash_bytes != -1)
spiOverrideSize(spi, spi_flash_bytes);
switch (op) { switch (op) {
case OP_SPI_ID: { case OP_SPI_ID: {
struct spi_id id = spiId(spi); struct spi_id id = spiId(spi);
@ -366,15 +375,25 @@ int main(int argc, char **argv) {
} }
case OP_SPI_READ: { case OP_SPI_READ: {
struct spi_id id = spiId(spi);
if (id.bytes == -1) {
fprintf(stderr, "unknown spi flash size -- specify with -b\n");
return 1;
}
fd = open(op_filename, O_WRONLY | O_CREAT | O_TRUNC, 0777); fd = open(op_filename, O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (fd == -1) { if (fd == -1) {
perror("unable to open output file"); perror("unable to open output file");
break; break;
} }
uint8_t *bfr = malloc(16777216); uint8_t *bfr = malloc(id.bytes);
spiRead(spi, 0, bfr, 16777216); if (!bfr) {
if (write(fd, bfr, 16777216) != 16777216) { perror("unable to allocate memory for spi");
perror("unable to write SPI flash image"); return 1;
}
spiRead(spi, 0, bfr, id.bytes);
if (write(fd, bfr, id.bytes) != id.bytes) {
perror("unable to write SPI flash image to disk");
break; break;
} }
close(fd); close(fd);

33
spi.c
View File

@ -29,6 +29,7 @@ struct ff_spi {
enum spi_type desired_type; enum spi_type desired_type;
struct spi_id id; struct spi_id id;
enum ff_spi_quirks quirks; enum ff_spi_quirks quirks;
int size_override;
struct { struct {
int clk; int clk;
@ -457,6 +458,7 @@ static void spi_decode_id(struct ff_spi *spi) {
spi->id.manufacturer = "unknown"; spi->id.manufacturer = "unknown";
spi->id.model = "unknown"; spi->id.model = "unknown";
spi->id.capacity = "unknown"; spi->id.capacity = "unknown";
spi->id.bytes = -1; // unknown
if (spi->id.manufacturer_id == 0xef) { if (spi->id.manufacturer_id == 0xef) {
spi->id.manufacturer = "Winbond"; spi->id.manufacturer = "Winbond";
@ -464,6 +466,7 @@ static void spi_decode_id(struct ff_spi *spi) {
&& (spi->id.memory_size == 0x18)) { && (spi->id.memory_size == 0x18)) {
spi->id.model = "W25Q128JV"; spi->id.model = "W25Q128JV";
spi->id.capacity = "128 Mbit"; spi->id.capacity = "128 Mbit";
spi->id.bytes = 16 * 1024 * 1024;
} }
} }
@ -473,6 +476,7 @@ static void spi_decode_id(struct ff_spi *spi) {
&& (spi->id.memory_size == 0x01)) { && (spi->id.memory_size == 0x01)) {
spi->id.model = "AT25SF161"; spi->id.model = "AT25SF161";
spi->id.capacity = "16 Mbit"; spi->id.capacity = "16 Mbit";
spi->id.bytes = 1 * 1024 * 1024;
} }
} }
@ -522,6 +526,16 @@ static void spi_get_id(struct ff_spi *spi) {
return; return;
} }
void spiOverrideSize(struct ff_spi *spi, uint32_t size) {
spi->size_override = size;
// If size is 0, re-read the capacity
if (!size)
spi_decode_id(spi);
else
spi->id.bytes = size;
}
int spiSetType(struct ff_spi *spi, enum spi_type type) { int spiSetType(struct ff_spi *spi, enum spi_type type) {
if (spi->type == type) if (spi->type == type)
@ -606,8 +620,14 @@ int spiRead(struct ff_spi *spi, uint32_t addr, uint8_t *data, unsigned int count
spiCommand(spi, addr >> 8); spiCommand(spi, addr >> 8);
spiCommand(spi, addr >> 0); spiCommand(spi, addr >> 0);
spiCommand(spi, 0x00); spiCommand(spi, 0x00);
for (i = 0; i < count; i++) for (i = 0; i < count; i++) {
if ((i & 0x3fff) == 0) {
printf("\rReading @ %06x / %06x", i, count);
fflush(stdout);
}
data[i] = spiRx(spi); data[i] = spiRx(spi);
}
printf("\rReading @ %06x / %06x Done\n", i, count);
spiEnd(spi); spiEnd(spi);
return 0; return 0;
@ -644,8 +664,9 @@ int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned in
// Erase all applicable blocks // Erase all applicable blocks
uint32_t erase_addr; uint32_t erase_addr;
for (erase_addr = 0; erase_addr < count; erase_addr += 32768) { for (erase_addr = 0; erase_addr < count; erase_addr += 32768) {
printf("\rErasing @ %06x", erase_addr); printf("\rErasing @ %06x / %06x", erase_addr, count);
fflush(stdout); fflush(stdout);
spiBegin(spi); spiBegin(spi);
spiCommand(spi, 0x06); spiCommand(spi, 0x06);
spiEnd(spi); spiEnd(spi);
@ -659,6 +680,7 @@ int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned in
spi_wait_for_not_busy(spi); spi_wait_for_not_busy(spi);
} }
printf(" Done\n");
uint8_t write_cmd; uint8_t write_cmd;
switch (spi->type) { switch (spi->type) {
@ -677,9 +699,9 @@ int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned in
return 1; return 1;
} }
printf("\n"); int total = count;
while (count) { while (count) {
printf("\rProgramming @ %06x", addr); printf("\rProgramming @ %06x / %06x", addr, total);
fflush(stdout); fflush(stdout);
spiBegin(spi); spiBegin(spi);
spiCommand(spi, 0x06); spiCommand(spi, 0x06);
@ -701,7 +723,8 @@ int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned in
addr += i; addr += i;
spi_wait_for_not_busy(spi); spi_wait_for_not_busy(spi);
} }
printf("\n"); printf("\rProgramming @ %06x / %06x", addr, total);
printf(" Done\n");
return 0; return 0;
} }

2
spi.h
View File

@ -42,6 +42,7 @@ struct spi_id {
uint8_t memory_size; // Result from 0x9f uint8_t memory_size; // Result from 0x9f
uint8_t signature; // Result from 0xab uint8_t signature; // Result from 0xab
uint8_t serial[4]; // Result from 0x4b uint8_t serial[4]; // Result from 0x4b
int bytes; // -1 if unknown
const char *manufacturer; const char *manufacturer;
const char *model; const char *model;
const char *capacity; const char *capacity;
@ -70,6 +71,7 @@ int spiSetType(struct ff_spi *spi, enum spi_type type);
int spiRead(struct ff_spi *spi, uint32_t addr, uint8_t *data, unsigned int count); int spiRead(struct ff_spi *spi, uint32_t addr, uint8_t *data, unsigned int count);
struct spi_id spiId(struct ff_spi *spi); struct spi_id spiId(struct ff_spi *spi);
void spiOverrideSize(struct ff_spi *spi, uint32_t new_size);
//int spi_wait_for_not_busy(struct ff_spi *spi); //int spi_wait_for_not_busy(struct ff_spi *spi);
int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned int count); int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned int count);