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:
		
							
								
								
									
										31
									
								
								fomu-flash.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								fomu-flash.c
									
									
									
									
									
								
							| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								spi.c
									
									
									
									
									
								
							| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								spi.h
									
									
									
									
									
								
							| @@ -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); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user