diff options
| author | Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> | 2012-12-29 15:04:20 +0000 | 
|---|---|---|
| committer | Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> | 2012-12-29 15:04:20 +0000 | 
| commit | 57794ac1580fc5efee3ba01a0c3e4539bb58d088 (patch) | |
| tree | 4212a02023a6a8c6dd0b03d234e66471ddb5d634 | |
| parent | 54aaa4ae2bb4026ae7acbf3e0aafe8542aaff2a4 (diff) | |
| download | flashrom-57794ac1580fc5efee3ba01a0c3e4539bb58d088.tar.gz flashrom-57794ac1580fc5efee3ba01a0c3e4539bb58d088.tar.bz2 flashrom-57794ac1580fc5efee3ba01a0c3e4539bb58d088.zip | |
Add support for Atmel's AT25F series of SPI flash chips
This adds support for the following chips:
 - AT25F512, AT25F512A, AT25F512B
 - AT25F1024, AT25F1024A
 - AT25F2048
 - AT25F4096
Besides the definitions of the the chips in flashchips.c this includes
- a dedicated probing method (probe_spi_at25f)
- pretty printing methods (spi_prettyprint_status_register_at25f*), and
- unlocking methods (spi_disable_blockprotect_at25f*)
Corresponding to flashrom svn r1637.
Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
| -rw-r--r-- | chipdrivers.h | 7 | ||||
| -rw-r--r-- | flashchips.c | 148 | ||||
| -rw-r--r-- | flashchips.h | 11 | ||||
| -rw-r--r-- | spi.h | 8 | ||||
| -rw-r--r-- | spi25.c | 22 | ||||
| -rw-r--r-- | spi25_statusreg.c | 64 | 
6 files changed, 250 insertions, 10 deletions
| diff --git a/chipdrivers.h b/chipdrivers.h index 04ffda63..f0223ae5 100644 --- a/chipdrivers.h +++ b/chipdrivers.h @@ -38,6 +38,7 @@ int probe_spi_rdid4(struct flashctx *flash);  int probe_spi_rems(struct flashctx *flash);  int probe_spi_res1(struct flashctx *flash);  int probe_spi_res2(struct flashctx *flash); +int probe_spi_at25f(struct flashctx *flash);  int spi_write_enable(struct flashctx *flash);  int spi_write_disable(struct flashctx *flash);  int spi_block_erase_20(struct flashctx *flash, unsigned int addr, unsigned int blocklen); @@ -68,13 +69,19 @@ int spi_disable_blockprotect(struct flashctx *flash);  int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash);  int spi_prettyprint_status_register_at25df(struct flashctx *flash);  int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash); +int spi_prettyprint_status_register_at25f(struct flashctx *flash); +int spi_prettyprint_status_register_at25f512a(struct flashctx *flash);  int spi_prettyprint_status_register_at25f512b(struct flashctx *flash); +int spi_prettyprint_status_register_at25f4096(struct flashctx *flash);  int spi_prettyprint_status_register_at25fs010(struct flashctx *flash);  int spi_prettyprint_status_register_at25fs040(struct flashctx *flash);  int spi_prettyprint_status_register_at26df081a(struct flashctx *flash);  int spi_disable_blockprotect_at25df(struct flashctx *flash);  int spi_disable_blockprotect_at25df_sec(struct flashctx *flash); +int spi_disable_blockprotect_at25f(struct flashctx *flash); +int spi_disable_blockprotect_at25f512a(struct flashctx *flash);  int spi_disable_blockprotect_at25f512b(struct flashctx *flash); +int spi_disable_blockprotect_at25f4096(struct flashctx *flash);  int spi_disable_blockprotect_at25fs010(struct flashctx *flash);  int spi_disable_blockprotect_at25fs040(struct flashctx *flash);  int spi_prettyprint_status_register_s33(struct flashctx *flash); diff --git a/flashchips.c b/flashchips.c index 9dd045eb..9767c00c 100644 --- a/flashchips.c +++ b/flashchips.c @@ -1667,6 +1667,65 @@ const struct flashchip flashchips[] = {  	{  		.vendor		= "Atmel", +		.name		= "AT25F512", +		.bustype	= BUS_SPI, +		.manufacture_id	= ATMEL_ID, +		.model_id	= ATMEL_AT25F512, +		.total_size	= 64, +		.page_size	= 256, +		.feature_bits	= FEATURE_WRSR_WREN, +		.tested		= TEST_UNTESTED, +		.probe		= probe_spi_at25f, +		.probe_timing	= TIMING_ZERO, +		.block_erasers	= +		{ +			{ +				.eraseblocks = { {32 * 1024, 2} }, +				.block_erase = spi_block_erase_52, +			}, { +				.eraseblocks = { {64 * 1024, 1} }, +				.block_erase = spi_block_erase_62, +			} +		}, +		.printlock	= spi_prettyprint_status_register_at25f, +		.unlock		= spi_disable_blockprotect_at25f, +		.write		= spi_chip_write_256, +		.read		= spi_chip_read, +		.voltage	= {2700, 3600}, +	}, + +	{ +		.vendor		= "Atmel", +		.name		= "AT25F512A", +		.bustype	= BUS_SPI, +		.manufacture_id	= ATMEL_ID, +		.model_id	= ATMEL_AT25F512A, +		.total_size	= 64, +		.page_size	= 128, +		.feature_bits	= FEATURE_WRSR_WREN, +		.tested		= TEST_UNTESTED, +		.probe		= probe_spi_at25f, +		.probe_timing	= TIMING_ZERO, +		.block_erasers	= +		{ +			{ +				.eraseblocks = { {32 * 1024, 2} }, +				.block_erase = spi_block_erase_52, +			}, { +				.eraseblocks = { {64 * 1024, 1} }, +				.block_erase = spi_block_erase_62, +			} +		}, +		.printlock	= spi_prettyprint_status_register_at25f512a, +		/* FIXME: It is not correct to use this one, because the BP1 bit is N/A. */ +		.unlock		= spi_disable_blockprotect_at25f512a, +		.write		= spi_chip_write_256, +		.read		= spi_chip_read, +		.voltage	= {2700, 3600}, +	}, + +	{ +		.vendor		= "Atmel",  		.name		= "AT25F512B",  		.bustype	= BUS_SPI,  		.manufacture_id	= ATMEL_ID, @@ -1709,6 +1768,95 @@ const struct flashchip flashchips[] = {  	{  		.vendor		= "Atmel", +		/* The A suffix indicates 33MHz instead of 20MHz clock rate. +		 * All other properties seem to be the same.*/ +		.name		= "AT25F1024(A)", +		.bustype	= BUS_SPI, +		.manufacture_id	= ATMEL_ID, +		.model_id	= ATMEL_AT25F1024, +		.total_size	= 128, +		.page_size	= 256, +		.feature_bits	= FEATURE_WRSR_WREN, +		.tested		= TEST_OK_PREW, +		.probe		= probe_spi_at25f, +		.probe_timing	= TIMING_ZERO, +		.block_erasers	= +		{ +			{ +				.eraseblocks = { {32 * 1024, 4} }, +				.block_erase = spi_block_erase_52, +			}, { +				.eraseblocks = { {128 * 1024, 1} }, +				.block_erase = spi_block_erase_62, +			} +		}, +		.printlock	= spi_prettyprint_status_register_at25f, +		.unlock		= spi_disable_blockprotect_at25f, +		.write		= spi_chip_write_256, +		.read		= spi_chip_read, +		.voltage	= {2700, 3600}, +	}, + +	{ +		.vendor		= "Atmel", +		.name		= "AT25F2048", +		.bustype	= BUS_SPI, +		.manufacture_id	= ATMEL_ID, +		.model_id	= ATMEL_AT25F2048, +		.total_size	= 256, +		.page_size	= 256, +		.feature_bits	= FEATURE_WRSR_WREN, +		.tested		= TEST_UNTESTED, +		.probe		= probe_spi_at25f, +		.probe_timing	= TIMING_ZERO, +		.block_erasers	= +		{ +			{ +				.eraseblocks = { {64 * 1024, 4} }, +				.block_erase = spi_block_erase_52, +			}, { +				.eraseblocks = { {256 * 1024, 1} }, +				.block_erase = spi_block_erase_62, +			} +		}, +		.printlock	= spi_prettyprint_status_register_at25f, +		.unlock		= spi_disable_blockprotect_at25f, +		.write		= spi_chip_write_256, +		.read		= spi_chip_read, +		.voltage	= {2700, 3600}, +	}, + +	{ +		.vendor		= "Atmel", +		.name		= "AT25F4096", +		.bustype	= BUS_SPI, +		.manufacture_id	= ATMEL_ID, +		.model_id	= ATMEL_AT25F4096, +		.total_size	= 512, +		.page_size	= 256, +		.feature_bits	= FEATURE_WRSR_WREN, +		.tested		= TEST_UNTESTED, +		.probe		= probe_spi_at25f, +		.probe_timing	= TIMING_ZERO, +		.block_erasers	= +		{ +			{ +				.eraseblocks = { {64 * 1024, 8} }, +				.block_erase = spi_block_erase_52, +			}, { +				.eraseblocks = { {512 * 1024, 1} }, +				.block_erase = spi_block_erase_62, +			} +		}, +		.printlock	= spi_prettyprint_status_register_at25f4096, +		.unlock		= spi_disable_blockprotect_at25f4096, +		.write		= spi_chip_write_256, +		.read		= spi_chip_read, +		.voltage	= {2700, 3600}, +	}, + +	{ +		.vendor		= "Atmel",  		.name		= "AT25FS010",  		.bustype	= BUS_SPI,  		.manufacture_id	= ATMEL_ID, diff --git a/flashchips.h b/flashchips.h index 073f4eb3..82ed4a7f 100644 --- a/flashchips.h +++ b/flashchips.h @@ -137,13 +137,12 @@  #define ATMEL_AT25DF321A	0x4701  #define ATMEL_AT25DF641		0x4800  #define ATMEL_AT25DQ161		0x8600 -#define ATMEL_AT25F512		/* No device ID found in datasheet. Vendor ID -				 * can be read with AT25F512A_RDID */ -#define ATMEL_AT25F512A		0x65 /* Needs AT25F512A_RDID */ +#define ATMEL_AT25F512		0x65	/* guessed, no device ID in datasheet. Needs AT25F_RDID */ +#define ATMEL_AT25F512A		0x65	/* Needs AT25F_RDID */  #define ATMEL_AT25F512B		0x6500 -#define ATMEL_AT25F1024		/* No device ID found in datasheet. Vendor ID -				 * can be read with AT25F512A_RDID */ -#define ATMEL_AT25F1024A		0x60 /* Needs AT25F512A_RDID */ +#define ATMEL_AT25F1024		0x60	/* Needs AT25F_RDID */ +#define ATMEL_AT25F2048		0x63	/* Needs AT25F_RDID */ +#define ATMEL_AT25F4096		0x64	/* Needs AT25F_RDID */  #define ATMEL_AT25FS010		0x6601  #define ATMEL_AT25FS040		0x6604  #define ATMEL_AT26DF041		0x4400 @@ -30,10 +30,10 @@  /* INSIZE may be 0x04 for some chips*/  #define JEDEC_RDID_INSIZE	0x03 -/* AT25F512A has bit 3 as don't care bit in commands */ -#define AT25F512A_RDID		0x15	/* 0x15 or 0x1d */ -#define AT25F512A_RDID_OUTSIZE	0x01 -#define AT25F512A_RDID_INSIZE	0x02 +/* Some Atmel AT25F* models have bit 3 as don't care bit in commands */ +#define AT25F_RDID		0x15	/* 0x15 or 0x1d */ +#define AT25F_RDID_OUTSIZE	0x01 +#define AT25F_RDID_INSIZE	0x02  /* Read Electronic Manufacturer Signature */  #define JEDEC_REMS		0x90 @@ -279,6 +279,28 @@ int probe_spi_res2(struct flashctx *flash)  	return 1;  } +/* Only used for some Atmel chips. */ +int probe_spi_at25f(struct flashctx *flash) +{ +	static const unsigned char cmd[AT25F_RDID_OUTSIZE] = { AT25F_RDID }; +	unsigned char readarr[AT25F_RDID_INSIZE]; +	uint32_t id1; +	uint32_t id2; + +	if (spi_send_command(flash, sizeof(cmd), sizeof(readarr), cmd, readarr)) +		return 0; + +	id1 = readarr[0]; +	id2 = readarr[1]; + +	msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); + +	if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id) +		return 1; + +	return 0; +} +  int spi_chip_erase_60(struct flashctx *flash)  {  	int result; diff --git a/spi25_statusreg.c b/spi25_statusreg.c index 2e01c06d..c0891576 100644 --- a/spi25_statusreg.c +++ b/spi25_statusreg.c @@ -378,6 +378,40 @@ int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash)  	return spi_prettyprint_status_register_at25df(flash);  } +/* used for AT25F512, AT25F1024(A), AT25F2048 */ +int spi_prettyprint_status_register_at25f(struct flashctx *flash) +{ +	uint8_t status; + +	status = spi_read_status_register(flash); +	spi_prettyprint_status_register_hex(status); + +	spi_prettyprint_status_register_atmel_at25_wpen(status); +	spi_prettyprint_status_register_bit(status, 6); +	spi_prettyprint_status_register_bit(status, 5); +	spi_prettyprint_status_register_bit(status, 4); +	spi_prettyprint_status_register_bp(status, 1); +	spi_prettyprint_status_register_welwip(status); +	return 0; +} + +int spi_prettyprint_status_register_at25f512a(struct flashctx *flash) +{ +	uint8_t status; + +	status = spi_read_status_register(flash); +	spi_prettyprint_status_register_hex(status); + +	spi_prettyprint_status_register_atmel_at25_wpen(status); +	spi_prettyprint_status_register_bit(status, 6); +	spi_prettyprint_status_register_bit(status, 5); +	spi_prettyprint_status_register_bit(status, 4); +	spi_prettyprint_status_register_bit(status, 3); +	spi_prettyprint_status_register_bp(status, 0); +	spi_prettyprint_status_register_welwip(status); +	return 0; +} +  int spi_prettyprint_status_register_at25f512b(struct flashctx *flash)  {  	uint8_t status = spi_read_status_register(flash); @@ -392,6 +426,21 @@ int spi_prettyprint_status_register_at25f512b(struct flashctx *flash)  	return 0;  } +int spi_prettyprint_status_register_at25f4096(struct flashctx *flash) +{ +	uint8_t status; + +	status = spi_read_status_register(flash); +	spi_prettyprint_status_register_hex(status); + +	spi_prettyprint_status_register_atmel_at25_wpen(status); +	spi_prettyprint_status_register_bit(status, 6); +	spi_prettyprint_status_register_bit(status, 5); +	spi_prettyprint_status_register_bp(status, 2); +	spi_prettyprint_status_register_welwip(status); +	return 0; +} +  int spi_prettyprint_status_register_at25fs010(struct flashctx *flash)  {  	uint8_t status = spi_read_status_register(flash); @@ -450,6 +499,16 @@ int spi_disable_blockprotect_at25df_sec(struct flashctx *flash)  	return spi_disable_blockprotect_at25df(flash);  } +int spi_disable_blockprotect_at25f(struct flashctx *flash) +{ +	return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 0); +} + +int spi_disable_blockprotect_at25f512a(struct flashctx *flash) +{ +	return spi_disable_blockprotect_generic(flash, 0x04, 1 << 7, 0); +} +  int spi_disable_blockprotect_at25f512b(struct flashctx *flash)  {  	/* spi_disable_blockprotect_at25df is not really the right way to do @@ -458,6 +517,11 @@ int spi_disable_blockprotect_at25f512b(struct flashctx *flash)  	return spi_disable_blockprotect_at25df(flash);  } +int spi_disable_blockprotect_at25f4096(struct flashctx *flash) +{ +	return spi_disable_blockprotect_generic(flash, 0x1C, 1 << 7, 0); +} +  int spi_disable_blockprotect_at25fs010(struct flashctx *flash)  {  	return spi_disable_blockprotect_generic(flash, 0x6C, 1 << 7, 0); | 
