diff options
| -rw-r--r-- | drivers/mtd/spi/atmel.c | 31 | ||||
| -rw-r--r-- | drivers/mtd/spi/eon.c | 48 | ||||
| -rw-r--r-- | drivers/mtd/spi/macronix.c | 48 | ||||
| -rw-r--r-- | drivers/mtd/spi/spansion.c | 41 | ||||
| -rw-r--r-- | drivers/mtd/spi/spi_flash.c | 41 | ||||
| -rw-r--r-- | drivers/mtd/spi/spi_flash_internal.h | 15 | ||||
| -rw-r--r-- | drivers/mtd/spi/sst.c | 41 | ||||
| -rw-r--r-- | drivers/mtd/spi/stmicro.c | 48 | ||||
| -rw-r--r-- | drivers/mtd/spi/winbond.c | 51 | 
9 files changed, 81 insertions, 283 deletions
| diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c index 8d0216956..7827b750f 100644 --- a/drivers/mtd/spi/atmel.c +++ b/drivers/mtd/spi/atmel.c @@ -113,35 +113,8 @@ static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {  static int at45_wait_ready(struct spi_flash *flash, unsigned long timeout)  { -	struct spi_slave *spi = flash->spi; -	unsigned long timebase; -	int ret; -	u8 cmd = CMD_AT45_READ_STATUS; -	u8 status; - -	timebase = get_timer(0); - -	ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); -	if (ret) -		return -1; - -	do { -		ret = spi_xfer(spi, 8, NULL, &status, 0); -		if (ret) -			return -1; - -		if (status & AT45_STATUS_READY) -			break; -	} while (get_timer(timebase) < timeout); - -	/* Deactivate CS */ -	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); - -	if (status & AT45_STATUS_READY) -		return 0; - -	/* Timed out */ -	return -1; +	return spi_flash_cmd_poll_bit(flash, timeout, +		CMD_AT45_READ_STATUS, AT45_STATUS_READY);  }  /* diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c index 02c3bb930..4af1e068c 100644 --- a/drivers/mtd/spi/eon.c +++ b/drivers/mtd/spi/eon.c @@ -25,8 +25,6 @@  #define EON_ID_EN25Q128		0x18 -#define EON_SR_WIP		(1 << 0)	/* Write-in-Progress */ -  struct eon_spi_flash_params {  	u8 idcode1;  	u16 page_size; @@ -58,40 +56,6 @@ static const struct eon_spi_flash_params eon_spi_flash_table[] = {  	},  }; -static int eon_wait_ready(struct spi_flash *flash, unsigned long timeout) -{ -	struct spi_slave *spi = flash->spi; -	unsigned long timebase; -	int ret; -	u8 cmd = CMD_EN25Q128_RDSR; -	u8 status; - -	ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); -	if (ret) { -		debug("SF: Failed to send command %02x: %d\n", cmd, ret); -		return ret; -	} - -	timebase = get_timer(0); -	do { -		ret = spi_xfer(spi, 8, NULL, &status, 0); -		if (ret) -			return -1; - -		if ((status & EON_SR_WIP) == 0) -			break; - -	} while (get_timer(timebase) < timeout); - -	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); - -	if ((status & EON_SR_WIP) == 0) -		return 0; - -	/* Timed out */ -	return -1; -} -  static int eon_read_fast(struct spi_flash *flash,  			 u32 offset, size_t len, void *buf)  { @@ -160,11 +124,9 @@ static int eon_write(struct spi_flash *flash,  			break;  		} -		ret = eon_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); -		if (ret < 0) { -			debug("SF: EON page programming timed out\n"); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); +		if (ret)  			break; -		}  		page_addr++;  		byte_addr = 0; @@ -221,11 +183,9 @@ int eon_erase(struct spi_flash *flash, u32 offset, size_t len)  			break;  		} -		ret = eon_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); -		if (ret < 0) { -			debug("SF: EON page erase timed out\n"); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); +		if (ret)  			break; -		}  	}  	debug("SF: EON: Successfully erased %u bytes @ 0x%x\n", diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c index 76d52841d..291fd17de 100644 --- a/drivers/mtd/spi/macronix.c +++ b/drivers/mtd/spi/macronix.c @@ -49,8 +49,6 @@  #define CMD_MX25XX_DP		0xb9	/* Deep Power-down */  #define CMD_MX25XX_RES		0xab	/* Release from DP, and Read Signature */ -#define MACRONIX_SR_WIP		(1 << 0)	/* Write-in-Progress */ -  struct macronix_spi_flash_params {  	u16 idcode;  	u16 page_size; @@ -114,40 +112,6 @@ static const struct macronix_spi_flash_params macronix_spi_flash_table[] = {  	},  }; -static int macronix_wait_ready(struct spi_flash *flash, unsigned long timeout) -{ -	struct spi_slave *spi = flash->spi; -	unsigned long timebase; -	int ret; -	u8 status; -	u8 cmd = CMD_MX25XX_RDSR; - -	ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); -	if (ret) { -		debug("SF: Failed to send command %02x: %d\n", cmd, ret); -		return ret; -	} - -	timebase = get_timer(0); -	do { -		ret = spi_xfer(spi, 8, NULL, &status, 0); -		if (ret) -			return -1; - -		if ((status & MACRONIX_SR_WIP) == 0) -			break; - -	} while (get_timer(timebase) < timeout); - -	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); - -	if ((status & MACRONIX_SR_WIP) == 0) -		return 0; - -	/* Timed out */ -	return -1; -} -  static int macronix_read_fast(struct spi_flash *flash,  			      u32 offset, size_t len, void *buf)  { @@ -216,11 +180,9 @@ static int macronix_write(struct spi_flash *flash,  			break;  		} -		ret = macronix_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); -		if (ret < 0) { -			debug("SF: Macronix page programming timed out\n"); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); +		if (ret)  			break; -		}  		page_addr++;  		byte_addr = 0; @@ -282,11 +244,9 @@ int macronix_erase(struct spi_flash *flash, u32 offset, size_t len)  			break;  		} -		ret = macronix_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); -		if (ret < 0) { -			debug("SF: Macronix page erase timed out\n"); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); +		if (ret)  			break; -		}  	}  	debug("SF: Macronix: Successfully erased %u bytes @ 0x%x\n", diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index c0900f978..d0f03ffaf 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -54,8 +54,6 @@  #define SPSN_EXT_ID_S25FL128P_64KB	0x0301  #define SPSN_EXT_ID_S25FL032P		0x4d00 -#define SPANSION_SR_WIP		(1 << 0)	/* Write-in-Progress */ -  struct spansion_spi_flash_params {  	u16 idcode1;  	u16 idcode2; @@ -135,32 +133,6 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {  	},  }; -static int spansion_wait_ready(struct spi_flash *flash, unsigned long timeout) -{ -	struct spi_slave *spi = flash->spi; -	unsigned long timebase; -	int ret; -	u8 status; - -	timebase = get_timer(0); -	do { -		ret = spi_flash_cmd(spi, CMD_S25FLXX_RDSR, &status, sizeof(status)); -		if (ret) -			return -1; - -		if ((status & SPANSION_SR_WIP) == 0) -			break; - -	} while (get_timer(timebase) < timeout); - - -	if ((status & SPANSION_SR_WIP) == 0) -		return 0; - -	/* Timed out */ -	return -1; -} -  static int spansion_read_fast(struct spi_flash *flash,  			     u32 offset, size_t len, void *buf)  { @@ -233,11 +205,9 @@ static int spansion_write(struct spi_flash *flash,  			break;  		} -		ret = spansion_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); -		if (ret < 0) { -			debug("SF: SPANSION page programming timed out\n"); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); +		if (ret)  			break; -		}  		page_addr++;  		byte_addr = 0; @@ -297,12 +267,9 @@ int spansion_erase(struct spi_flash *flash, u32 offset, size_t len)  			break;  		} -		/* Up to 2 seconds */ -		ret = spansion_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); -		if (ret < 0) { -			debug("SF: SPANSION page erase timed out\n"); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); +		if (ret)  			break; -		}  	}  	debug("SF: SPANSION: Successfully erased %u bytes @ 0x%x\n", diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 2b7f22c59..e483ce4af 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -69,6 +69,47 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,  	return ret;  } +int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout, +			   u8 cmd, u8 poll_bit) +{ +	struct spi_slave *spi = flash->spi; +	unsigned long timebase; +	int ret; +	u8 status; + +	ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); +	if (ret) { +		debug("SF: Failed to send command %02x: %d\n", cmd, ret); +		return ret; +	} + +	timebase = get_timer(0); +	do { +		ret = spi_xfer(spi, 8, NULL, &status, 0); +		if (ret) +			return -1; + +		if ((status & poll_bit) == 0) +			break; + +	} while (get_timer(timebase) < timeout); + +	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); + +	if ((status & poll_bit) == 0) +		return 0; + +	/* Timed out */ +	debug("SF: time out!\n"); +	return -1; +} + +int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) +{ +	return spi_flash_cmd_poll_bit(flash, timeout, +		CMD_READ_STATUS, STATUS_WIP); +} +  /*   * The following table holds all device probe functions   * diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 68dcffb97..440c044f7 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -19,6 +19,11 @@  #define CMD_READ_ARRAY_FAST		0x0b  #define CMD_READ_ARRAY_LEGACY		0xe8 +#define CMD_READ_STATUS			0x05 + +/* Common status */ +#define STATUS_WIP			0x01 +  /* Send a single-byte command to the device and read the response */  int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); @@ -43,6 +48,16 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,  int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,  		size_t cmd_len, void *data, size_t data_len); +/* Send a command to the device and wait for some bit to clear itself. */ +int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout, +			   u8 cmd, u8 poll_bit); + +/* + * Send the read status command to the device and wait for the wip + * (write-in-progress) bit to clear itself. + */ +int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); +  /* Manufacturer-specific probe functions */  struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode);  struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode); diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c index 25578914c..4a82f8a3a 100644 --- a/drivers/mtd/spi/sst.c +++ b/drivers/mtd/spi/sst.c @@ -90,41 +90,6 @@ static const struct sst_spi_flash_params sst_spi_flash_table[] = {  };  static int -sst_wait_ready(struct spi_flash *flash, unsigned long timeout) -{ -	struct spi_slave *spi = flash->spi; -	unsigned long timebase; -	int ret; -	u8 byte = CMD_SST_RDSR; - -	ret = spi_xfer(spi, sizeof(byte) * 8, &byte, NULL, SPI_XFER_BEGIN); -	if (ret) { -		debug("SF: Failed to send command %02x: %d\n", byte, ret); -		return ret; -	} - -	timebase = get_timer(0); -	do { -		ret = spi_xfer(spi, sizeof(byte) * 8, NULL, &byte, 0); -		if (ret) -			break; - -		if ((byte & SST_SR_WIP) == 0) -			break; - -	} while (get_timer(timebase) < timeout); - -	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); - -	if (!ret && (byte & SST_SR_WIP) != 0) -		ret = -1; - -	if (ret) -		debug("SF: sst wait for ready timed out\n"); -	return ret; -} - -static int  sst_enable_writing(struct spi_flash *flash)  {  	int ret = spi_flash_cmd(flash->spi, CMD_SST_WREN, NULL, 0); @@ -177,7 +142,7 @@ sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)  	if (ret)  		return ret; -	return sst_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); +	return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);  }  static int @@ -224,7 +189,7 @@ sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)  			break;  		} -		ret = sst_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);  		if (ret)  			break; @@ -298,7 +263,7 @@ sst_erase(struct spi_flash *flash, u32 offset, size_t len)  			break;  		} -		ret = sst_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);  		if (ret)  			break;  	} diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index 31340279c..02da8b2fd 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -55,8 +55,6 @@  #define STM_ID_M25P80		0x14  #define STM_ID_M25P128		0x18 -#define STMICRO_SR_WIP		(1 << 0)	/* Write-in-Progress */ -  struct stmicro_spi_flash_params {  	u8 idcode1;  	u16 page_size; @@ -136,40 +134,6 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {  	},  }; -static int stmicro_wait_ready(struct spi_flash *flash, unsigned long timeout) -{ -	struct spi_slave *spi = flash->spi; -	unsigned long timebase; -	int ret; -	u8 cmd = CMD_M25PXX_RDSR; -	u8 status; - -	ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); -	if (ret) { -		debug("SF: Failed to send command %02x: %d\n", cmd, ret); -		return ret; -	} - -	timebase = get_timer(0); -	do { -		ret = spi_xfer(spi, 8, NULL, &status, 0); -		if (ret) -			return -1; - -		if ((status & STMICRO_SR_WIP) == 0) -			break; - -	} while (get_timer(timebase) < timeout); - -	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); - -	if ((status & STMICRO_SR_WIP) == 0) -		return 0; - -	/* Timed out */ -	return -1; -} -  static int stmicro_read_fast(struct spi_flash *flash,  			     u32 offset, size_t len, void *buf)  { @@ -238,11 +202,9 @@ static int stmicro_write(struct spi_flash *flash,  			break;  		} -		ret = stmicro_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); -		if (ret < 0) { -			debug("SF: STMicro page programming timed out\n"); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); +		if (ret)  			break; -		}  		page_addr++;  		byte_addr = 0; @@ -304,11 +266,9 @@ int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)  			break;  		} -		ret = stmicro_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); -		if (ret < 0) { -			debug("SF: STMicro page erase timed out\n"); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); +		if (ret)  			break; -		}  	}  	debug("SF: STMicro: Successfully erased %u bytes @ 0x%x\n", diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index 44523555d..d8c1cb12d 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -24,8 +24,6 @@  #define CMD_W25_DP		0xb9	/* Deep Power-down */  #define CMD_W25_RES		0xab	/* Release from DP, and Read Signature */ -#define WINBOND_SR_WIP		(1 << 0)	/* Write-in-Progress */ -  struct winbond_spi_flash_params {  	uint16_t	id;  	/* Log2 of page size in power-of-two mode */ @@ -107,43 +105,6 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {  	},  }; -static int winbond_wait_ready(struct spi_flash *flash, unsigned long timeout) -{ -	struct spi_slave *spi = flash->spi; -	unsigned long timebase; -	int ret; -	u8 status; -	u8 cmd[4] = { CMD_W25_RDSR, 0xff, 0xff, 0xff }; - -	ret = spi_xfer(spi, 32, &cmd[0], NULL, SPI_XFER_BEGIN); -	if (ret) { -		debug("SF: Failed to send command %02x: %d\n", cmd, ret); -		return ret; -	} - -	timebase = get_timer(0); -	do { -		ret = spi_xfer(spi, 8, NULL, &status, 0); -		if (ret) { -			debug("SF: Failed to get status for cmd %02x: %d\n", cmd, ret); -			return -1; -		} - -		if ((status & WINBOND_SR_WIP) == 0) -			break; - -	} while (get_timer(timebase) < timeout); - -	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); - -	if ((status & WINBOND_SR_WIP) == 0) -		return 0; - -	debug("SF: Timed out on command %02x: %d\n", cmd, ret); -	/* Timed out */ -	return -1; -} -  /*   * Assemble the address part of a command for Winbond devices in   * non-power-of-two page size mode. @@ -230,11 +191,9 @@ static int winbond_write(struct spi_flash *flash,  			goto out;  		} -		ret = winbond_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); -		if (ret < 0) { -			debug("SF: Winbond page programming timed out\n"); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); +		if (ret)  			goto out; -		}  		page_addr++;  		byte_addr = 0; @@ -298,11 +257,9 @@ int winbond_erase(struct spi_flash *flash, u32 offset, size_t len)  			goto out;  		} -		ret = winbond_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); -		if (ret < 0) { -			debug("SF: Winbond sector erase timed out\n"); +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); +		if (ret)  			goto out; -		}  	}  	debug("SF: Winbond: Successfully erased %u bytes @ 0x%x\n", |