[flashrom] [PATCH] Write protection handling for Atmel AT25*

Steven Rosario srosariomd at gmail.com
Wed Jul 28 00:05:49 CEST 2010


Attached as requested: flashrom -p internal:laptop=force_I_want_a_brick -V
using flashrom trunk 1109 patched with latest Rayer patch and Atmel 
write protection patch

On 7/26/10 5:47 PM, Carl-Daniel Hailfinger wrote:
> Next try, with one status register printing corner case fixed and with
> a better changelog.
>
> Add detailed status register printing and unlocking for all ATMEL AT25*
> chips.
>
> Add support for Atmel AT25DF081A and AT25DQ161.
>
> Some chips require EWSR before WRSR, others require WREN before WRSR,
> and some support both variants. Add feature_bits to select the correct
> SPI command, and default to EWSR.
>
> Signed-off-by: Carl-Daniel Hailfinger<c-d.hailfinger.devel.2006 at gmx.net>
>
>   Index: flashrom-writeprotect_atmel_at25/flash.h
> ===================================================================
> --- flashrom-writeprotect_atmel_at25/flash.h	(Revision 1109)
> +++ flashrom-writeprotect_atmel_at25/flash.h	(Arbeitskopie)
> @@ -167,8 +167,9 @@
>
>   /*
>    * How many different erase functions do we have per chip?
> + * Atmel AT25FS010 has 6 different functions.
>    */
> -#define NUM_ERASEFUNCTIONS 5
> +#define NUM_ERASEFUNCTIONS 6
>
>   #define FEATURE_REGISTERMAP	(1<<  0)
>   #define FEATURE_BYTEWRITES	(1<<  1)
> @@ -180,6 +181,9 @@
>   #define FEATURE_ADDR_2AA	(1<<  2)
>   #define FEATURE_ADDR_AAA	(2<<  2)
>   #define FEATURE_ADDR_SHIFTED	(1<<  5)
> +#define FEATURE_WRSR_EWSR	(1<<  6)
> +#define FEATURE_WRSR_WREN	(1<<  7)
> +#define FEATURE_WRSR_EITHER	(FEATURE_WRSR_EWSR | FEATURE_WRSR_WREN)
>
>   struct flashchip {
>   	const char *vendor;
> Index: flashrom-writeprotect_atmel_at25/spi25.c
> ===================================================================
> --- flashrom-writeprotect_atmel_at25/spi25.c	(Revision 1109)
> +++ flashrom-writeprotect_atmel_at25/spi25.c	(Arbeitskopie)
> @@ -311,8 +311,17 @@
>   }
>
>   /* Prettyprint the status register. Common definitions. */
> -void spi_prettyprint_status_register_common(uint8_t status)
> +static void spi_prettyprint_status_register_welwip(uint8_t status)
>   {
> +	msg_cdbg("Chip status register: Write Enable Latch (WEL) is "
> +		     "%sset\n", (status&  (1<<  1)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is "
> +		     "%sset\n", (status&  (1<<  0)) ? "" : "not ");
> +}
> +
> +/* Prettyprint the status register. Common definitions. */
> +static void spi_prettyprint_status_register_common(uint8_t status)
> +{
>   	msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is "
>   		     "%sset\n", (status&  (1<<  5)) ? "" : "not ");
>   	msg_cdbg("Chip status register: Bit 4 / Block Protect 2 (BP2) is "
> @@ -321,10 +330,7 @@
>   		     "%sset\n", (status&  (1<<  3)) ? "" : "not ");
>   	msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is "
>   		     "%sset\n", (status&  (1<<  2)) ? "" : "not ");
> -	msg_cdbg("Chip status register: Write Enable Latch (WEL) is "
> -		     "%sset\n", (status&  (1<<  1)) ? "" : "not ");
> -	msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is "
> -		     "%sset\n", (status&  (1<<  0)) ? "" : "not ");
> +	spi_prettyprint_status_register_welwip(status);
>   }
>
>   /* Prettyprint the status register. Works for
> @@ -337,6 +343,121 @@
>   	spi_prettyprint_status_register_common(status);
>   }
>
> +/* Prettyprint the status register. Common definitions. */
> +static void spi_prettyprint_status_register_at25_srplepewpp(uint8_t status)
> +{
> +	msg_cdbg("Chip status register: Sector Protection Register Lock (SRPL) "
> +		 "is %sset\n", (status&  (1<<  7)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 6 "
> +		 "is %sset\n", (status&  (1<<  6)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Erase/Program Error (EPE) "
> +		 "is %sset\n", (status&  (1<<  5)) ? "" : "not ");
> +	msg_cdbg("Chip status register: WP# pin (WPP) "
> +		 "is %sactive\n", (status&  (1<<  4)) ? "not " : "");
> +}
> +
> +int spi_prettyprint_status_register_at25df(struct flashchip *flash)
> +{
> +	uint8_t status;
> +
> +	status = spi_read_status_register();
> +	msg_cdbg("Chip status register is %02x\n", status);
> +
> +	spi_prettyprint_status_register_at25_srplepewpp(status);
> +	msg_cdbg("Chip status register: Software Protection Status (SWP): ");
> +	switch (status&  (3<<  2)) {
> +	case 0x0<<  2:
> +		msg_cdbg("no sectors are protected\n");
> +		break;
> +	case 0x1<<  2:
> +		msg_cdbg("some sectors are protected\n");
> +		/* FIXME: Read individual Sector Protection Registers. */
> +		break;
> +	case 0x3<<  2:
> +		msg_cdbg("all sectors are protected\n");
> +		break;
> +	default:
> +		msg_cdbg("reserved for future use\n");
> +		break;
> +	}
> +	spi_prettyprint_status_register_welwip(status);
> +	return 0;
> +}
> +
> +int spi_prettyprint_status_register_at25df_sec(struct flashchip *flash)
> +{
> +	/* FIXME: We should check the security lockdown. */
> +	msg_cdbg("Ignoring security lockdown (if present)\n");
> +	msg_cdbg("Ignoring status register byte 2\n");
> +	return spi_prettyprint_status_register_at25df(flash);
> +}
> +
> +int spi_prettyprint_status_register_at25f(struct flashchip *flash)
> +{
> +	uint8_t status;
> +
> +	status = spi_read_status_register();
> +	msg_cdbg("Chip status register is %02x\n", status);
> +
> +	spi_prettyprint_status_register_at25_srplepewpp(status);
> +	msg_cdbg("Chip status register: Bit 3 "
> +		 "is %sset\n", (status&  (1<<  3)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Block Protect 0 (BP0) is "
> +		 "%sset, %s sectors are protected\n",
> +		 (status&  (1<<  2)) ? "" : "not ",
> +		 (status&  (1<<  2)) ? "all" : "no");
> +	spi_prettyprint_status_register_welwip(status);
> +	return 0;
> +}
> +
> +int spi_prettyprint_status_register_at25fs010(struct flashchip *flash)
> +{
> +	uint8_t status;
> +
> +	status = spi_read_status_register();
> +	msg_cdbg("Chip status register is %02x\n", status);
> +
> +	msg_cdbg("Chip status register: Status Register Write Protect (WPEN) "
> +		 "is %sset\n", (status&  (1<<  7)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is "
> +		 "%sset\n", (status&  (1<<  6)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is "
> +		 "%sset\n", (status&  (1<<  5)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 4 is "
> +		 "%sset\n", (status&  (1<<  4)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is "
> +		 "%sset\n", (status&  (1<<  3)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is "
> +		 "%sset\n", (status&  (1<<  2)) ? "" : "not ");
> +	/* FIXME: Pretty-print detailed sector protection status. */
> +	spi_prettyprint_status_register_welwip(status);
> +	return 0;
> +}
> +
> +int spi_prettyprint_status_register_at25fs040(struct flashchip *flash)
> +{
> +	uint8_t status;
> +
> +	status = spi_read_status_register();
> +	msg_cdbg("Chip status register is %02x\n", status);
> +
> +	msg_cdbg("Chip status register: Status Register Write Protect (WPEN) "
> +		 "is %sset\n", (status&  (1<<  7)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is "
> +		 "%sset\n", (status&  (1<<  6)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is "
> +		 "%sset\n", (status&  (1<<  5)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 4 / Block Protect 2 (BP2) is "
> +		 "%sset\n", (status&  (1<<  4)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is "
> +		 "%sset\n", (status&  (1<<  3)) ? "" : "not ");
> +	msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is "
> +		 "%sset\n", (status&  (1<<  2)) ? "" : "not ");
> +	/* FIXME: Pretty-print detailed sector protection status. */
> +	spi_prettyprint_status_register_welwip(status);
> +	return 0;
> +}
> +
>   /* Prettyprint the status register. Works for
>    * ST M25P series
>    * MX MX25L series
> @@ -731,12 +852,12 @@
>    * This is according the SST25VF016 datasheet, who knows it is more
>    * generic that this...
>    */
> -int spi_write_status_register(int status)
> +static int spi_write_status_register_ewsr(struct flashchip *flash, int status)
>   {
>   	int result;
>   	struct spi_command cmds[] = {
>   	{
> -	/* FIXME: WRSR requires either EWSR or WREN depending on chip type. */
> +	/* WRSR requires either EWSR or WREN depending on chip type. */
>   		.writecnt	= JEDEC_EWSR_OUTSIZE,
>   		.writearr	= (const unsigned char[]){ JEDEC_EWSR },
>   		.readcnt	= 0,
> @@ -758,9 +879,59 @@
>   		msg_cerr("%s failed during command execution\n",
>   			__func__);
>   	}
> +	/* WRSR performs a self-timed erase before the changes take effect. */
> +	programmer_delay(100 * 1000);
>   	return result;
>   }
>
> +static int spi_write_status_register_wren(struct flashchip *flash, int status)
> +{
> +	int result;
> +	struct spi_command cmds[] = {
> +	{
> +	/* WRSR requires either EWSR or WREN depending on chip type. */
> +		.writecnt	= JEDEC_WREN_OUTSIZE,
> +		.writearr	= (const unsigned char[]){ JEDEC_WREN },
> +		.readcnt	= 0,
> +		.readarr	= NULL,
> +	}, {
> +		.writecnt	= JEDEC_WRSR_OUTSIZE,
> +		.writearr	= (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status },
> +		.readcnt	= 0,
> +		.readarr	= NULL,
> +	}, {
> +		.writecnt	= 0,
> +		.writearr	= NULL,
> +		.readcnt	= 0,
> +		.readarr	= NULL,
> +	}};
> +
> +	result = spi_send_multicommand(cmds);
> +	if (result) {
> +		msg_cerr("%s failed during command execution\n",
> +			__func__);
> +	}
> +	/* WRSR performs a self-timed erase before the changes take effect. */
> +	programmer_delay(100 * 1000);
> +	return result;
> +}
> +
> +static int spi_write_status_register(struct flashchip *flash, int status)
> +{
> +	int ret = 1;
> +
> +	if (!(flash->feature_bits&  (FEATURE_WRSR_WREN | FEATURE_WRSR_EWSR))) {
> +		msg_cdbg("Missing status register write definition, assuming "
> +			 "EWSR is needed\n");
> +		flash->feature_bits |= FEATURE_WRSR_EWSR;
> +	}
> +	if (flash->feature_bits&  FEATURE_WRSR_WREN)
> +		ret = spi_write_status_register_wren(flash, status);
> +	if (ret&&  (flash->feature_bits&  FEATURE_WRSR_EWSR))
> +		ret = spi_write_status_register_ewsr(flash, status);
> +	return ret;
> +}
> +
>   int spi_byte_program(int addr, uint8_t databyte)
>   {
>   	int result;
> @@ -843,29 +1014,156 @@
>   	return result;
>   }
>
> +/* A generic brute-force block protection disable works like this:
> + * Write 0x00 to the status register. Check if any locks are still set (that
> + * part is chip specific). Repeat once.
> + */
>   int spi_disable_blockprotect(struct flashchip *flash)
>   {
>   	uint8_t status;
>   	int result;
>
>   	status = spi_read_status_register();
> -	/* If there is block protection in effect, unprotect it first. */
> +	/* If block protection is disabled, stop here. */
> +	if ((status&  0x3c) == 0)
> +		return 0;
> +
> +	msg_cdbg("Some block protection in effect, disabling\n");
> +	result = spi_write_status_register(flash, status&  ~0x3c);
> +	if (result) {
> +		msg_cerr("spi_write_status_register failed\n");
> +		return result;
> +	}
> +	status = spi_read_status_register();
>   	if ((status&  0x3c) != 0) {
> -		msg_cdbg("Some block protection in effect, disabling\n");
> -		result = spi_write_status_register(status&  ~0x3c);
> +		msg_cerr("Block protection could not be disabled!\n");
> +		return 1;
> +	}
> +	return 0;
> +}
> +
> +int spi_disable_blockprotect_at25df(struct flashchip *flash)
> +{
> +	uint8_t status;
> +	int result;
> +
> +	status = spi_read_status_register();
> +	/* If block protection is disabled, stop here. */
> +	if ((status&  (3<<  2)) == 0)
> +		return 0;
> +
> +	msg_cdbg("Some block protection in effect, disabling\n");
> +	if (status&  (1<<  7)) {
> +		msg_cdbg("Need to disable Sector Protection Register Lock\n");
> +		if ((status&  (1<<  4)) == 0) {
> +			msg_cerr("WP# pin is active, disabling "
> +				 "write protection is impossible.\n");
> +			return 1;
> +		}
> +		/* All bits except bit 7 (SPRL) are readonly. */
> +		result = spi_write_status_register(flash, status&  ~(1<<  7));
>   		if (result) {
>   			msg_cerr("spi_write_status_register failed\n");
>   			return result;
>   		}
> -		status = spi_read_status_register();
> -		if ((status&  0x3c) != 0) {
> -			msg_cerr("Block protection could not be disabled!\n");
> -			return 1;
> +		
> +	}
> +	/* Global unprotect. Make sure to mask SPRL as well. */
> +	result = spi_write_status_register(flash, status&  ~0xbc);
> +	if (result) {
> +		msg_cerr("spi_write_status_register failed\n");
> +		return result;
> +	}
> +	status = spi_read_status_register();
> +	if ((status&  (3<<  2)) != 0) {
> +		msg_cerr("Block protection could not be disabled!\n");
> +		return 1;
> +	}
> +	return 0;
> +}
> +
> +int spi_disable_blockprotect_at25df_sec(struct flashchip *flash)
> +{
> +	/* FIXME: We should check the security lockdown. */
> +	msg_cinfo("Ignoring security lockdown (if present)\n");
> +	return spi_disable_blockprotect_at25df(flash);
> +}
> +
> +int spi_disable_blockprotect_at25f(struct flashchip *flash)
> +{
> +	/* spi_disable_blockprotect_at25df is not really the right way to do
> +	 * this, but the side effects of said function work here as well.
> +	 */
> +	return spi_disable_blockprotect_at25df(flash);
> +}
> +
> +int spi_disable_blockprotect_at25fs010(struct flashchip *flash)
> +{
> +	uint8_t status;
> +	int result;
> +
> +	status = spi_read_status_register();
> +	/* If block protection is disabled, stop here. */
> +	if ((status&  0x6c) == 0)
> +		return 0;
> +
> +	msg_cdbg("Some block protection in effect, disabling\n");
> +	if (status&  (1<<  7)) {
> +		msg_cdbg("Need to disable Status Register Write Protect\n");
> +		/* Clear bit 7 (WPEN). */
> +		result = spi_write_status_register(flash, status&  ~(1<<  7));
> +		if (result) {
> +			msg_cerr("spi_write_status_register failed\n");
> +			return result;
>   		}
>   	}
> +	/* Global unprotect. Make sure to mask WPEN as well. */
> +	result = spi_write_status_register(flash, status&  ~0xec);
> +	if (result) {
> +		msg_cerr("spi_write_status_register failed\n");
> +		return result;
> +	}
> +	status = spi_read_status_register();
> +	if ((status&  0x6c) != 0) {
> +		msg_cerr("Block protection could not be disabled!\n");
> +		return 1;
> +	}
>   	return 0;
>   }
> +int spi_disable_blockprotect_at25fs040(struct flashchip *flash)
> +{
> +	uint8_t status;
> +	int result;
>
> +	status = spi_read_status_register();
> +	/* If block protection is disabled, stop here. */
> +	if ((status&  0x7c) == 0)
> +		return 0;
> +
> +	msg_cdbg("Some block protection in effect, disabling\n");
> +	if (status&  (1<<  7)) {
> +		msg_cdbg("Need to disable Status Register Write Protect\n");
> +		/* Clear bit 7 (WPEN). */
> +		result = spi_write_status_register(flash, status&  ~(1<<  7));
> +		if (result) {
> +			msg_cerr("spi_write_status_register failed\n");
> +			return result;
> +		}
> +	}
> +	/* Global unprotect. Make sure to mask WPEN as well. */
> +	result = spi_write_status_register(flash, status&  ~0xfc);
> +	if (result) {
> +		msg_cerr("spi_write_status_register failed\n");
> +		return result;
> +	}
> +	status = spi_read_status_register();
> +	if ((status&  0x7c) != 0) {
> +		msg_cerr("Block protection could not be disabled!\n");
> +		return 1;
> +	}
> +	return 0;
> +}
> +
>   int spi_nbyte_read(int address, uint8_t *bytes, int len)
>   {
>   	const unsigned char cmd[JEDEC_READ_OUTSIZE] = {
> Index: flashrom-writeprotect_atmel_at25/flashchips.c
> ===================================================================
> --- flashrom-writeprotect_atmel_at25/flashchips.c	(Revision 1109)
> +++ flashrom-writeprotect_atmel_at25/flashchips.c	(Arbeitskopie)
> @@ -313,6 +313,7 @@
>   		.model_id	= AT_25DF021,
>   		.total_size	= 256,
>   		.page_size	= 256,
> +		.feature_bits	= FEATURE_WRSR_WREN,
>   		.tested		= TEST_UNTESTED,
>   		.probe		= probe_spi_rdid,
>   		.probe_timing	= TIMING_ZERO,
> @@ -335,7 +336,8 @@
>   				.block_erase = spi_block_erase_c7,
>   			}
>   		},
> -		.unlock		= spi_disable_blockprotect,
> +		.printlock	= spi_prettyprint_status_register_at25df,
> +		.unlock		= spi_disable_blockprotect_at25df,
>   		.write		= spi_chip_write_256,
>   		.read		= spi_chip_read,
>   	},
> @@ -348,6 +350,7 @@
>   		.model_id	= AT_25DF041A,
>   		.total_size	= 512,
>   		.page_size	= 256,
> +		.feature_bits	= FEATURE_WRSR_WREN,
>   		.tested		= TEST_UNTESTED,
>   		.probe		= probe_spi_rdid,
>   		.probe_timing	= TIMING_ZERO,
> @@ -370,7 +373,8 @@
>   				.block_erase = spi_block_erase_c7,
>   			}
>   		},
> -		.unlock		= spi_disable_blockprotect,
> +		.printlock	= spi_prettyprint_status_register_at25df,
> +		.unlock		= spi_disable_blockprotect_at25df,
>   		.write		= spi_chip_write_256,
>   		.read		= spi_chip_read,
>   	},
> @@ -383,6 +387,7 @@
>   		.model_id	= AT_25DF081,
>   		.total_size	= 1024,
>   		.page_size	= 256,
> +		.feature_bits	= FEATURE_WRSR_WREN,
>   		.tested		= TEST_UNTESTED,
>   		.probe		= probe_spi_rdid,
>   		.probe_timing	= TIMING_ZERO,
> @@ -405,19 +410,58 @@
>   				.block_erase = spi_block_erase_c7,
>   			}
>   		},
> -		.unlock		= spi_disable_blockprotect,
> +		.printlock	= spi_prettyprint_status_register_at25df,
> +		.unlock		= spi_disable_blockprotect_at25df,
>   		.write		= spi_chip_write_256,
>   		.read		= spi_chip_read,
>   	},
>
>   	{
>   		.vendor		= "Atmel",
> +		.name		= "AT25DF081A",
> +		.bustype	= CHIP_BUSTYPE_SPI,
> +		.manufacture_id	= ATMEL_ID,
> +		.model_id	= AT_25DF081A,
> +		.total_size	= 1024,
> +		.page_size	= 256,
> +		.feature_bits	= FEATURE_WRSR_WREN,
> +		.tested		= TEST_UNTESTED,
> +		.probe		= probe_spi_rdid,
> +		.probe_timing	= TIMING_ZERO,
> +		.block_erasers	=
> +		{
> +			{
> +				.eraseblocks = { {4 * 1024, 256} },
> +				.block_erase = spi_block_erase_20,
> +			}, {
> +				.eraseblocks = { {32 * 1024, 32} },
> +				.block_erase = spi_block_erase_52,
> +			}, {
> +				.eraseblocks = { {64 * 1024, 16} },
> +				.block_erase = spi_block_erase_d8,
> +			}, {
> +				.eraseblocks = { {1024 * 1024, 1} },
> +				.block_erase = spi_block_erase_60,
> +			}, {
> +				.eraseblocks = { {1024 * 1024, 1} },
> +				.block_erase = spi_block_erase_c7,
> +			}
> +		},
> +		.printlock	= spi_prettyprint_status_register_at25df_sec,
> +		.unlock		= spi_disable_blockprotect_at25df_sec,
> +		.write		= spi_chip_write_256,
> +		.read		= spi_chip_read,
> +	},
> +
> +	{
> +		.vendor		= "Atmel",
>   		.name		= "AT25DF161",
>   		.bustype	= CHIP_BUSTYPE_SPI,
>   		.manufacture_id	= ATMEL_ID,
>   		.model_id	= AT_25DF161,
>   		.total_size	= 2048,
>   		.page_size	= 256,
> +		.feature_bits	= FEATURE_WRSR_WREN,
>   		.tested		= TEST_UNTESTED,
>   		.probe		= probe_spi_rdid,
>   		.probe_timing	= TIMING_ZERO,
> @@ -440,7 +484,8 @@
>   				.block_erase = spi_block_erase_c7,
>   			}
>   		},
> -		.unlock		= spi_disable_blockprotect,
> +		.printlock	= spi_prettyprint_status_register_at25df_sec,
> +		.unlock		= spi_disable_blockprotect_at25df_sec,
>   		.write		= spi_chip_write_256,
>   		.read		= spi_chip_read,
>   	},
> @@ -453,6 +498,7 @@
>   		.model_id	= AT_25DF321,
>   		.total_size	= 4096,
>   		.page_size	= 256,
> +		.feature_bits	= FEATURE_WRSR_WREN,
>   		.tested		= TEST_OK_PRW,
>   		.probe		= probe_spi_rdid,
>   		.probe_timing	= TIMING_ZERO,
> @@ -475,7 +521,8 @@
>   				.block_erase = spi_block_erase_c7,
>   			}
>   		},
> -		.unlock		= spi_disable_blockprotect,
> +		.printlock	= spi_prettyprint_status_register_at25df,
> +		.unlock		= spi_disable_blockprotect_at25df,
>   		.write		= spi_chip_write_256,
>   		.read		= spi_chip_read,
>   	},
> @@ -488,6 +535,7 @@
>   		.model_id	= AT_25DF321A,
>   		.total_size	= 4096,
>   		.page_size	= 256,
> +		.feature_bits	= FEATURE_WRSR_WREN,
>   		.tested		= TEST_UNTESTED,
>   		.probe		= probe_spi_rdid,
>   		.probe_timing	= TIMING_ZERO,
> @@ -510,7 +558,8 @@
>   				.block_erase = spi_block_erase_c7,
>   			}
>   		},
> -		.unlock		= spi_disable_blockprotect,
> +		.printlock	= spi_prettyprint_status_register_at25df_sec,
> +		.unlock		= spi_disable_blockprotect_at25df_sec,
>   		.write		= spi_chip_write_256,
>   		.read		= spi_chip_read,
>   	},
> @@ -523,6 +572,7 @@
>   		.model_id	= AT_25DF641,
>   		.total_size	= 8192,
>   		.page_size	= 256,
> +		.feature_bits	= FEATURE_WRSR_WREN,
>   		.tested		= TEST_UNTESTED,
>   		.probe		= probe_spi_rdid,
>   		.probe_timing	= TIMING_ZERO,
> @@ -545,19 +595,58 @@
>   				.block_erase = spi_block_erase_c7,
>   			}
>   		},
> -		.unlock		= spi_disable_blockprotect,
> +		.printlock	= spi_prettyprint_status_register_at25df_sec,
> +		.unlock		= spi_disable_blockprotect_at25df_sec,
>   		.write		= spi_chip_write_256,
>   		.read		= spi_chip_read,
>   	},
>
>   	{
>   		.vendor		= "Atmel",
> +		.name		= "AT25DQ161",
> +		.bustype	= CHIP_BUSTYPE_SPI,
> +		.manufacture_id	= ATMEL_ID,
> +		.model_id	= AT_25DQ161,
> +		.total_size	= 2048,
> +		.page_size	= 256,
> +		.feature_bits	= FEATURE_WRSR_WREN,
> +		.tested		= TEST_UNTESTED,
> +		.probe		= probe_spi_rdid,
> +		.probe_timing	= TIMING_ZERO,
> +		.block_erasers	=
> +		{
> +			{
> +				.eraseblocks = { {4 * 1024, 512} },
> +				.block_erase = spi_block_erase_20,
> +			}, {
> +				.eraseblocks = { {32 * 1024, 64} },
> +				.block_erase = spi_block_erase_52,
> +			}, {
> +				.eraseblocks = { {64 * 1024, 32} },
> +				.block_erase = spi_block_erase_d8,
> +			}, {
> +				.eraseblocks = { {2 * 1024 * 1024, 1} },
> +				.block_erase = spi_block_erase_60,
> +			}, {
> +				.eraseblocks = { {2 * 1024 * 1024, 1} },
> +				.block_erase = spi_block_erase_c7,
> +			}
> +		},
> +		.printlock	= spi_prettyprint_status_register_at25df_sec,
> +		.unlock		= spi_disable_blockprotect_at25df_sec,
> +		.write		= spi_chip_write_256,
> +		.read		= spi_chip_read,
> +	},
> +
> +	{
> +		.vendor		= "Atmel",
>   		.name		= "AT25F512B",
>   		.bustype	= CHIP_BUSTYPE_SPI,
>   		.manufacture_id	= ATMEL_ID,
>   		.model_id	= AT_25F512B,
>   		.total_size	= 64,
>   		.page_size	= 256,
> +		.feature_bits	= FEATURE_WRSR_WREN,
>   		.tested		= TEST_UNTESTED,
>   		.probe		= probe_spi_rdid,
>   		.probe_timing	= TIMING_ZERO,
> @@ -580,7 +669,8 @@
>   				.block_erase = spi_block_erase_c7,
>   			}
>   		},
> -		.unlock		= spi_disable_blockprotect,
> +		.printlock	= spi_prettyprint_status_register_at25f,
> +		.unlock		= spi_disable_blockprotect_at25f,
>   		.write		= spi_chip_write_256,
>   		.read		= spi_chip_read,
>   	},
> @@ -602,6 +692,9 @@
>   				.eraseblocks = { {4 * 1024, 32} },
>   				.block_erase = spi_block_erase_20,
>   			}, {
> +				.eraseblocks = { {4 * 1024, 32} },
> +				.block_erase = spi_block_erase_d7,
> +			}, {
>   				.eraseblocks = { {32 * 1024, 4} },
>   				.block_erase = spi_block_erase_52,
>   			}, {
> @@ -615,7 +708,8 @@
>   				.block_erase = spi_block_erase_c7,
>   			}
>   		},
> -		.unlock		= spi_disable_blockprotect,
> +		.printlock	= spi_prettyprint_status_register_at25fs010,
> +		.unlock		= spi_disable_blockprotect_at25fs010,
>   		.write		= spi_chip_write_256,
>   		.read		= spi_chip_read,
>   	},
> @@ -650,7 +744,8 @@
>   				.block_erase = spi_block_erase_c7,
>   			}
>   		},
> -		.unlock		= spi_disable_blockprotect,
> +		.printlock	= spi_prettyprint_status_register_at25fs040,
> +		.unlock		= spi_disable_blockprotect_at25fs040,
>   		.write		= spi_chip_write_256,
>   		.read		= spi_chip_read,
>   	},
> Index: flashrom-writeprotect_atmel_at25/flashchips.h
> ===================================================================
> --- flashrom-writeprotect_atmel_at25/flashchips.h	(Revision 1109)
> +++ flashrom-writeprotect_atmel_at25/flashchips.h	(Arbeitskopie)
> @@ -110,12 +110,19 @@
>   #define AT_25DF021		0x4300
>   #define AT_25DF041A		0x4401
>   #define AT_25DF081		0x4502
> +#define AT_25DF081A		0x4501	/* Yes, 81A has a lower number than 81 */
>   #define AT_25DF161		0x4602
>   #define AT_25DF321		0x4700	/* Same as 26DF321 */
>   #define AT_25DF321A		0x4701
>   #define AT_25DF641		0x4800
> -#define AT_25F512A		0x65 /* Needs special RDID. AT25F512A_RDID 15 1d */
> +#define AT_25DQ161		0x8600
> +#define AT25F512		/* No device ID found in datasheet. Vendor ID
> +				 * can be read with AT25F512A_RDID */
> +#define AT_25F512A		0x65 /* Needs AT25F512A_RDID */
>   #define AT_25F512B		0x6500
> +#define AT25F1024		/* No device ID found in datasheet. Vendor ID
> +				 * can be read with AT25F512A_RDID */
> +#define AT_25F1024A		0x60 /* Needs AT25F512A_RDID */
>   #define AT_25FS010		0x6601
>   #define AT_25FS040		0x6604
>   #define AT_26DF041		0x4400
> Index: flashrom-writeprotect_atmel_at25/spi.c
> ===================================================================
> --- flashrom-writeprotect_atmel_at25/spi.c	(Revision 1109)
> +++ flashrom-writeprotect_atmel_at25/spi.c	(Arbeitskopie)
> @@ -29,8 +29,6 @@
>
>   enum spi_controller spi_controller = SPI_CONTROLLER_NONE;
>
> -void spi_prettyprint_status_register(struct flashchip *flash);
> -
>   const struct spi_programmer spi_programmer[] = {
>   	{ /* SPI_CONTROLLER_NONE */
>   		.command = NULL,
> Index: flashrom-writeprotect_atmel_at25/spi.h
> ===================================================================
> --- flashrom-writeprotect_atmel_at25/spi.h	(Revision 1109)
> +++ flashrom-writeprotect_atmel_at25/spi.h	(Arbeitskopie)
> @@ -31,7 +31,7 @@
>   #define JEDEC_RDID_INSIZE	0x03
>
>   /* AT25F512A has bit 3 as don't care bit in commands */
> -#define AT25F512A_RDID		0x15
> +#define AT25F512A_RDID		0x15	/* 0x15 or 0x1d */
>   #define AT25F512A_RDID_OUTSIZE	0x01
>   #define AT25F512A_RDID_INSIZE	0x02
>
> @@ -123,5 +123,6 @@
>   #define SPI_INVALID_OPCODE	-2
>   #define SPI_INVALID_ADDRESS	-3
>   #define SPI_INVALID_LENGTH	-4
> +#define SPI_FLASHROM_BUG	-5
>
>   #endif		/* !__SPI_H__ */
> Index: flashrom-writeprotect_atmel_at25/chipdrivers.h
> ===================================================================
> --- flashrom-writeprotect_atmel_at25/chipdrivers.h	(Revision 1109)
> +++ flashrom-writeprotect_atmel_at25/chipdrivers.h	(Arbeitskopie)
> @@ -47,7 +47,17 @@
>   int spi_chip_write_256_new(struct flashchip *flash, uint8_t *buf, int start, int len);
>   int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len);
>   uint8_t spi_read_status_register(void);
> +int spi_prettyprint_status_register_at25df(struct flashchip *flash);
> +int spi_prettyprint_status_register_at25df_sec(struct flashchip *flash);
> +int spi_prettyprint_status_register_at25f(struct flashchip *flash);
> +int spi_prettyprint_status_register_at25fs010(struct flashchip *flash);
> +int spi_prettyprint_status_register_at25fs040(struct flashchip *flash);
>   int spi_disable_blockprotect(struct flashchip *flash);
> +int spi_disable_blockprotect_at25df(struct flashchip *flash);
> +int spi_disable_blockprotect_at25df_sec(struct flashchip *flash);
> +int spi_disable_blockprotect_at25f(struct flashchip *flash);
> +int spi_disable_blockprotect_at25fs010(struct flashchip *flash);
> +int spi_disable_blockprotect_at25fs040(struct flashchip *flash);
>   int spi_byte_program(int addr, uint8_t databyte);
>   int spi_nbyte_program(int addr, uint8_t *bytes, int len);
>   int spi_nbyte_read(int addr, uint8_t *bytes, int len);
>
>
>    
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: flashrom-latest.log
URL: <http://www.flashrom.org/pipermail/flashrom/attachments/20100727/6310b921/attachment.log>


More information about the flashrom mailing list