mirror of
				https://review.coreboot.org/flashrom.git
				synced 2025-11-04 07:00:39 +01:00 
			
		
		
		
	Add support for two-byte RES probes
Some chips implement the RES (0xab) opcode, but they use a non-standard two byte response instead of the usual one byte response. A two-byte response has the accuracy of REMS and RDID, so don't check for REMS/RDID availability before running a two-byte RES. Corresponding to flashrom svn r1017. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Stefan Reinauer <stepan@coresystems.de>
This commit is contained in:
		@@ -29,7 +29,8 @@
 | 
			
		||||
int probe_spi_rdid(struct flashchip *flash);
 | 
			
		||||
int probe_spi_rdid4(struct flashchip *flash);
 | 
			
		||||
int probe_spi_rems(struct flashchip *flash);
 | 
			
		||||
int probe_spi_res(struct flashchip *flash);
 | 
			
		||||
int probe_spi_res1(struct flashchip *flash);
 | 
			
		||||
int probe_spi_res2(struct flashchip *flash);
 | 
			
		||||
int spi_write_enable(void);
 | 
			
		||||
int spi_write_disable(void);
 | 
			
		||||
int spi_chip_erase_60(struct flashchip *flash);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								flashchips.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								flashchips.c
									
									
									
									
									
								
							@@ -4665,19 +4665,19 @@ struct flashchip flashchips[] = {
 | 
			
		||||
 | 
			
		||||
	/* The ST M25P05 is a bit of a problem. It has the same ID as the
 | 
			
		||||
	 * ST M25P05-A in RES mode, but supports only 128 byte writes instead
 | 
			
		||||
	 * of 256 byte writes. We rely heavily on the fact that probe_spi_res
 | 
			
		||||
	 * of 256 byte writes. We rely heavily on the fact that probe_spi_res1
 | 
			
		||||
	 * only is successful if RDID does not work.
 | 
			
		||||
	 */
 | 
			
		||||
	{
 | 
			
		||||
		.vendor		= "ST",
 | 
			
		||||
		.name		= "M25P05.RES",
 | 
			
		||||
		.bustype	= CHIP_BUSTYPE_SPI,
 | 
			
		||||
		.manufacture_id	= ST_ID,
 | 
			
		||||
		.manufacture_id	= 0, /* Not used. */
 | 
			
		||||
		.model_id	= ST_M25P05_RES,
 | 
			
		||||
		.total_size	= 64,
 | 
			
		||||
		.page_size	= 256,
 | 
			
		||||
		.tested		= TEST_UNTESTED,
 | 
			
		||||
		.probe		= probe_spi_res,
 | 
			
		||||
		.probe		= probe_spi_res1,
 | 
			
		||||
		.probe_timing	= TIMING_ZERO,
 | 
			
		||||
		.block_erasers	=
 | 
			
		||||
		{
 | 
			
		||||
@@ -4723,12 +4723,12 @@ struct flashchip flashchips[] = {
 | 
			
		||||
		.vendor		= "ST",
 | 
			
		||||
		.name		= "M25P10.RES",
 | 
			
		||||
		.bustype	= CHIP_BUSTYPE_SPI,
 | 
			
		||||
		.manufacture_id	= ST_ID,
 | 
			
		||||
		.manufacture_id	= 0, /* Not used. */
 | 
			
		||||
		.model_id	= ST_M25P10_RES,
 | 
			
		||||
		.total_size	= 128,
 | 
			
		||||
		.page_size	= 256,
 | 
			
		||||
		.tested		= TEST_UNTESTED,
 | 
			
		||||
		.probe		= probe_spi_res,
 | 
			
		||||
		.probe		= probe_spi_res1,
 | 
			
		||||
		.probe_timing	= TIMING_ZERO,
 | 
			
		||||
		.block_erasers	=
 | 
			
		||||
		{
 | 
			
		||||
@@ -4798,12 +4798,12 @@ struct flashchip flashchips[] = {
 | 
			
		||||
		.vendor		= "ST",
 | 
			
		||||
		.name		= "M25P40-old",
 | 
			
		||||
		.bustype	= CHIP_BUSTYPE_SPI,
 | 
			
		||||
		.manufacture_id	= ST_ID,
 | 
			
		||||
		.manufacture_id	= 0, /* Not used. */
 | 
			
		||||
		.model_id	= ST_M25P40_RES,
 | 
			
		||||
		.total_size	= 512,
 | 
			
		||||
		.page_size	= 256,
 | 
			
		||||
		.tested		= TEST_UNTESTED,
 | 
			
		||||
		.probe		= probe_spi_res,
 | 
			
		||||
		.probe		= probe_spi_res1,
 | 
			
		||||
		.probe_timing	= TIMING_ZERO,
 | 
			
		||||
		.block_erasers	=
 | 
			
		||||
		{
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								spi.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								spi.h
									
									
									
									
									
								
							@@ -27,6 +27,7 @@
 | 
			
		||||
/* Read Electronic ID */
 | 
			
		||||
#define JEDEC_RDID		0x9f
 | 
			
		||||
#define JEDEC_RDID_OUTSIZE	0x01
 | 
			
		||||
/* INSIZE may be 0x04 for some chips*/
 | 
			
		||||
#define JEDEC_RDID_INSIZE	0x03
 | 
			
		||||
 | 
			
		||||
/* AT25F512A has bit 3 as don't care bit in commands */
 | 
			
		||||
@@ -42,6 +43,7 @@
 | 
			
		||||
/* Read Electronic Signature */
 | 
			
		||||
#define JEDEC_RES		0xab
 | 
			
		||||
#define JEDEC_RES_OUTSIZE	0x04
 | 
			
		||||
/* INSIZE may be 0x02 for some chips*/
 | 
			
		||||
#define JEDEC_RES_INSIZE	0x01
 | 
			
		||||
 | 
			
		||||
/* Write Enable */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								spi25.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								spi25.c
									
									
									
									
									
								
							@@ -67,20 +67,20 @@ static int spi_rems(unsigned char *readarr)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int spi_res(unsigned char *readarr)
 | 
			
		||||
static int spi_res(unsigned char *readarr, int bytes)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 };
 | 
			
		||||
	uint32_t readaddr;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = spi_send_command(sizeof(cmd), JEDEC_RES_INSIZE, cmd, readarr);
 | 
			
		||||
	ret = spi_send_command(sizeof(cmd), bytes, cmd, readarr);
 | 
			
		||||
	if (ret == SPI_INVALID_ADDRESS) {
 | 
			
		||||
		/* Find the lowest even address allowed for reads. */
 | 
			
		||||
		readaddr = (spi_get_valid_read_addr() + 1) & ~1;
 | 
			
		||||
		cmd[1] = (readaddr >> 16) & 0xff,
 | 
			
		||||
		cmd[2] = (readaddr >> 8) & 0xff,
 | 
			
		||||
		cmd[3] = (readaddr >> 0) & 0xff,
 | 
			
		||||
		ret = spi_send_command(sizeof(cmd), JEDEC_RES_INSIZE, cmd, readarr);
 | 
			
		||||
		ret = spi_send_command(sizeof(cmd), bytes, cmd, readarr);
 | 
			
		||||
	}
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
@@ -235,13 +235,15 @@ int probe_spi_rems(struct flashchip *flash)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int probe_spi_res(struct flashchip *flash)
 | 
			
		||||
int probe_spi_res1(struct flashchip *flash)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char readarr[3];
 | 
			
		||||
	uint32_t id2;
 | 
			
		||||
	const unsigned char allff[] = {0xff, 0xff, 0xff};
 | 
			
		||||
	const unsigned char all00[] = {0x00, 0x00, 0x00};
 | 
			
		||||
 | 
			
		||||
	/* We only want one-byte RES if RDID and REMS are unusable. */
 | 
			
		||||
 | 
			
		||||
	/* Check if RDID is usable and does not return 0xff 0xff 0xff or
 | 
			
		||||
	 * 0x00 0x00 0x00. In that case, RES is pointless.
 | 
			
		||||
	 */
 | 
			
		||||
@@ -259,12 +261,13 @@ int probe_spi_res(struct flashchip *flash)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (spi_res(readarr))
 | 
			
		||||
	if (spi_res(readarr, 1))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: Handle the case where RES gives a 2-byte response. */
 | 
			
		||||
	id2 = readarr[0];
 | 
			
		||||
 | 
			
		||||
	msg_cdbg("%s: id 0x%x\n", __func__, id2);
 | 
			
		||||
 | 
			
		||||
	if (id2 != flash->model_id)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
@@ -275,6 +278,29 @@ int probe_spi_res(struct flashchip *flash)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int probe_spi_res2(struct flashchip *flash)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char readarr[2];
 | 
			
		||||
	uint32_t id1, id2;
 | 
			
		||||
 | 
			
		||||
	if (spi_res(readarr, 2))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	id1 = readarr[0];
 | 
			
		||||
	id2 = readarr[1];
 | 
			
		||||
 | 
			
		||||
	msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
 | 
			
		||||
 | 
			
		||||
	if (id1 != flash->manufacture_id || id2 != flash->model_id)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* Print the status register to tell the
 | 
			
		||||
	 * user about possible write protection.
 | 
			
		||||
	 */
 | 
			
		||||
	spi_prettyprint_status_register(flash);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t spi_read_status_register(void)
 | 
			
		||||
{
 | 
			
		||||
	const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR };
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user