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, "Usage:\n");
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");
print_program_modes(stream);
fprintf(stream, "Configuration options:\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, " -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, "\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_fpga *fpga;
int peek_offset = 0;
int spi_flash_bytes = -1;
uint8_t security_reg;
uint8_t security_val[256];
enum op op = OP_UNKNOWN;
@ -191,7 +193,7 @@ int main(int argc, char **argv) {
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) {
case 'r':
@ -200,6 +202,10 @@ int main(int argc, char **argv) {
op = OP_FPGA_RESET;
break;
case 'b':
spi_flash_bytes = strtoul(optarg, NULL, 0);
break;
case 'k': {
if (op != OP_UNKNOWN)
return print_usage_error(stdout);
@ -332,6 +338,9 @@ int main(int argc, char **argv) {
spiSetType(spi, spi_type);
fpgaReset(fpga);
if (spi_flash_bytes != -1)
spiOverrideSize(spi, spi_flash_bytes);
switch (op) {
case OP_SPI_ID: {
struct spi_id id = spiId(spi);
@ -366,15 +375,25 @@ int main(int argc, char **argv) {
}
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);
if (fd == -1) {
perror("unable to open output file");
break;
}
uint8_t *bfr = malloc(16777216);
spiRead(spi, 0, bfr, 16777216);
if (write(fd, bfr, 16777216) != 16777216) {
perror("unable to write SPI flash image");
uint8_t *bfr = malloc(id.bytes);
if (!bfr) {
perror("unable to allocate memory for spi");
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;
}
close(fd);

33
spi.c
View File

@ -29,6 +29,7 @@ struct ff_spi {
enum spi_type desired_type;
struct spi_id id;
enum ff_spi_quirks quirks;
int size_override;
struct {
int clk;
@ -457,6 +458,7 @@ static void spi_decode_id(struct ff_spi *spi) {
spi->id.manufacturer = "unknown";
spi->id.model = "unknown";
spi->id.capacity = "unknown";
spi->id.bytes = -1; // unknown
if (spi->id.manufacturer_id == 0xef) {
spi->id.manufacturer = "Winbond";
@ -464,6 +466,7 @@ static void spi_decode_id(struct ff_spi *spi) {
&& (spi->id.memory_size == 0x18)) {
spi->id.model = "W25Q128JV";
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.model = "AT25SF161";
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;
}
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) {
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 >> 0);
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);
}
printf("\rReading @ %06x / %06x Done\n", i, count);
spiEnd(spi);
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
uint32_t erase_addr;
for (erase_addr = 0; erase_addr < count; erase_addr += 32768) {
printf("\rErasing @ %06x", erase_addr);
printf("\rErasing @ %06x / %06x", erase_addr, count);
fflush(stdout);
spiBegin(spi);
spiCommand(spi, 0x06);
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);
}
printf(" Done\n");
uint8_t write_cmd;
switch (spi->type) {
@ -677,9 +699,9 @@ int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned in
return 1;
}
printf("\n");
int total = count;
while (count) {
printf("\rProgramming @ %06x", addr);
printf("\rProgramming @ %06x / %06x", addr, total);
fflush(stdout);
spiBegin(spi);
spiCommand(spi, 0x06);
@ -701,7 +723,8 @@ int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned in
addr += i;
spi_wait_for_not_busy(spi);
}
printf("\n");
printf("\rProgramming @ %06x / %06x", addr, total);
printf(" Done\n");
return 0;
}

2
spi.h
View File

@ -42,6 +42,7 @@ struct spi_id {
uint8_t memory_size; // Result from 0x9f
uint8_t signature; // Result from 0xab
uint8_t serial[4]; // Result from 0x4b
int bytes; // -1 if unknown
const char *manufacturer;
const char *model;
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);
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 spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned int count);