diff options
| -rw-r--r-- | drivers/mtd/spi/eon.c | 55 | ||||
| -rw-r--r-- | drivers/mtd/spi/macronix.c | 60 | ||||
| -rw-r--r-- | drivers/mtd/spi/spansion.c | 57 | ||||
| -rw-r--r-- | drivers/mtd/spi/spi_flash.c | 58 | ||||
| -rw-r--r-- | drivers/mtd/spi/spi_flash_internal.h | 5 | ||||
| -rw-r--r-- | drivers/mtd/spi/sst.c | 63 | ||||
| -rw-r--r-- | drivers/mtd/spi/stmicro.c | 59 | ||||
| -rw-r--r-- | drivers/mtd/spi/winbond.c | 61 | 
8 files changed, 83 insertions, 335 deletions
| diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c index 4af1e068c..0c0b05f01 100644 --- a/drivers/mtd/spi/eon.c +++ b/drivers/mtd/spi/eon.c @@ -141,58 +141,11 @@ static int eon_write(struct spi_flash *flash,  int eon_erase(struct spi_flash *flash, u32 offset, size_t len)  { -	/* block erase */  	struct eon_spi_flash *eon = to_eon_spi_flash(flash); -	unsigned long block_size; -	size_t actual; -	int ret; -	u8 cmd[4]; - - -	block_size = eon->params->page_size * eon->params->pages_per_sector -	       * eon->params->sectors_per_block; - -	if (offset % block_size || len % block_size) { -		debug("SF: Erase offset/length not multiple of block size\n"); -		return -1; -	} - -	len /= block_size; -	cmd[0] = CMD_EN25Q128_BE; -	cmd[2] = 0x00; -	cmd[3] = 0x00; - -	ret = spi_claim_bus(flash->spi); -	if (ret) { -		debug("SF: Unable to claim SPI bus\n"); -		return ret; -	} - -	ret = 0; -	for (actual = 0; actual < len; actual++) { -		cmd[1] = (offset / block_size) + actual; -		ret = spi_flash_cmd(flash->spi, CMD_EN25Q128_WREN, NULL, 0); -		if (ret < 0) { -			debug("SF: Enabling Write failed\n"); -			break; -		} - -		ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0); -		if (ret < 0) { -			debug("SF: EON page erase failed\n"); -			break; -		} - -		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", -	      len * block_size, offset); - -	spi_release_bus(flash->spi); -	return ret; +	return spi_flash_cmd_erase(flash, CMD_EN25Q128_BE, +		eon->params->page_size * eon->params->pages_per_sector * +			eon->params->sectors_per_block; +		offset, len);  }  struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c index 291fd17de..573e1dba7 100644 --- a/drivers/mtd/spi/macronix.c +++ b/drivers/mtd/spi/macronix.c @@ -198,62 +198,10 @@ static int macronix_write(struct spi_flash *flash,  int macronix_erase(struct spi_flash *flash, u32 offset, size_t len)  {  	struct macronix_spi_flash *mcx = to_macronix_spi_flash(flash); -	unsigned long sector_size; -	size_t actual; -	int ret; -	u8 cmd[4]; - -	/* -	 * This function currently uses sector erase only. -	 * probably speed things up by using bulk erase -	 * when possible. -	 */ - -	sector_size = mcx->params->page_size * mcx->params->pages_per_sector -			* mcx->params->sectors_per_block; - -	if (offset % sector_size || len % sector_size) { -		debug("SF: Erase offset/length not multiple of sector size\n"); -		return -1; -	} - -	len /= sector_size; -	cmd[0] = CMD_MX25XX_BE; -	cmd[2] = 0x00; -	cmd[3] = 0x00; - -	ret = spi_claim_bus(flash->spi); -	if (ret) { -		debug("SF: Unable to claim SPI bus\n"); -		return ret; -	} - -	ret = 0; -	for (actual = 0; actual < len; actual++) { -		cmd[1] = (offset / sector_size) + actual; - -		ret = spi_flash_cmd(flash->spi, CMD_MX25XX_WREN, NULL, 0); -		if (ret < 0) { -			debug("SF: Enabling Write failed\n"); -			break; -		} - -		ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0); -		if (ret < 0) { -			debug("SF: Macronix page erase failed\n"); -			break; -		} - -		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", -	      len * sector_size, offset); - -	spi_release_bus(flash->spi); -	return ret; +	return spi_flash_cmd_erase(flash, CMD_MX25XX_BE, +		mcx->params->page_size * mcx->params->pages_per_sector * +			mcx->params->sectors_per_block, +		offset, len);  }  struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode) diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index d0f03ffaf..be4fc67ef 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -223,60 +223,9 @@ static int spansion_write(struct spi_flash *flash,  int spansion_erase(struct spi_flash *flash, u32 offset, size_t len)  {  	struct spansion_spi_flash *spsn = to_spansion_spi_flash(flash); -	unsigned long sector_size; -	size_t actual; -	int ret; -	u8 cmd[4]; - -	/* -	 * This function currently uses sector erase only. -	 * probably speed things up by using bulk erase -	 * when possible. -	 */ - -	sector_size = spsn->params->page_size * spsn->params->pages_per_sector; - -	if (offset % sector_size || len % sector_size) { -		debug("SF: Erase offset/length not multiple of sector size\n"); -		return -1; -	} - -	cmd[0] = CMD_S25FLXX_SE; -	cmd[2] = 0x00; -	cmd[3] = 0x00; - -	ret = spi_claim_bus(flash->spi); -	if (ret) { -		debug("SF: Unable to claim SPI bus\n"); -		return ret; -	} - -	ret = 0; -	for (actual = 0; actual < len; actual += sector_size) { -		cmd[1] = (offset + actual) >> 16; - -		ret = spi_flash_cmd(flash->spi, CMD_S25FLXX_WREN, NULL, 0); -		if (ret < 0) { -			debug("SF: Enabling Write failed\n"); -			break; -		} - -		ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0); -		if (ret < 0) { -			debug("SF: SPANSION page erase failed\n"); -			break; -		} - -		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", -	      len, offset); - -	spi_release_bus(flash->spi); -	return ret; +	return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE, +		spsn->params->page_size * spsn->params->pages_per_sector, +		offset, len);  }  struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index e483ce4af..ca4bbb206 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -14,6 +14,14 @@  #include "spi_flash_internal.h" +static void spi_flash_addr(u32 addr, u8 *cmd) +{ +	/* cmd[0] is actual command */ +	cmd[1] = addr >> 16; +	cmd[2] = addr >> 8; +	cmd[3] = addr >> 0; +} +  static int spi_flash_read_write(struct spi_slave *spi,  				const u8 *cmd, size_t cmd_len,  				const u8 *data_out, u8 *data_in, @@ -110,6 +118,56 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)  		CMD_READ_STATUS, STATUS_WIP);  } +int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, +			u32 erase_size, u32 offset, size_t len) +{ +	u32 start, end; +	int ret; +	u8 cmd[4]; + +	if (offset % erase_size || len % erase_size) { +		debug("SF: Erase offset/length not multiple of erase size\n"); +		return -1; +	} + +	ret = spi_claim_bus(flash->spi); +	if (ret) { +		debug("SF: Unable to claim SPI bus\n"); +		return ret; +	} + +	cmd[0] = erase_cmd; +	start = offset; +	end = start + len; + +	while (offset < end) { +		spi_flash_addr(offset, cmd); +		offset += erase_size; + +		debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], +		      cmd[2], cmd[3], offset); + +		ret = spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); +		if (ret) +			goto out; + +		ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), NULL, 0); +		if (ret) +			goto out; + +		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); +		if (ret) +			goto out; +	} + +	debug("SF: Successfully erased %lu bytes @ %#x\n", +	      len * erase_size, start); + + out: +	spi_release_bus(flash->spi); +	return ret; +} +  /*   * 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 440c044f7..114b63459 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -20,6 +20,7 @@  #define CMD_READ_ARRAY_LEGACY		0xe8  #define CMD_READ_STATUS			0x05 +#define CMD_WRITE_ENABLE		0x06  /* Common status */  #define STATUS_WIP			0x01 @@ -58,6 +59,10 @@ int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,   */  int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); +/* Erase sectors. */ +int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, +			u32 erase_size, u32 offset, size_t len); +  /* 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 4a82f8a3a..d55055035 100644 --- a/drivers/mtd/spi/sst.c +++ b/drivers/mtd/spi/sst.c @@ -212,67 +212,10 @@ sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)  	return ret;  } -int -sst_erase(struct spi_flash *flash, u32 offset, size_t len) +int sst_erase(struct spi_flash *flash, u32 offset, size_t len)  { -	unsigned long sector_size; -	u32 start, end; -	int ret; -	u8 cmd[4]; - -	/* -	 * This function currently uses sector erase only. -	 * Probably speed things up by using bulk erase -	 * when possible. -	 */ - -	sector_size = SST_SECTOR_SIZE; - -	if (offset % sector_size) { -		debug("SF: Erase offset not multiple of sector size\n"); -		return -1; -	} - -	ret = spi_claim_bus(flash->spi); -	if (ret) { -		debug("SF: Unable to claim SPI bus\n"); -		return ret; -	} - -	cmd[0] = CMD_SST_SE; -	cmd[3] = 0; -	start = offset; -	end = start + len; - -	ret = 0; -	while (offset < end) { -		cmd[1] = offset >> 16; -		cmd[2] = offset >> 8; -		offset += sector_size; - -		debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], -		      cmd[2], cmd[3], offset); - -		ret = sst_enable_writing(flash); -		if (ret) -			break; - -		ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), NULL, 0); -		if (ret) { -			debug("SF: sst page erase failed\n"); -			break; -		} - -		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); -		if (ret) -			break; -	} - -	debug("SF: sst: Successfully erased %lu bytes @ 0x%x\n", -	      len * sector_size, start); - -	spi_release_bus(flash->spi); -	return ret; +	return spi_flash_cmd_erase(flash, CMD_SST_SE, SST_SECTOR_SIZE, +		offset, len);  }  static int diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index 02da8b2fd..494005c4a 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -220,62 +220,9 @@ static int stmicro_write(struct spi_flash *flash,  int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)  {  	struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash); -	unsigned long sector_size; -	size_t actual; -	int ret; -	u8 cmd[4]; - -	/* -	 * This function currently uses sector erase only. -	 * probably speed things up by using bulk erase -	 * when possible. -	 */ - -	sector_size = stm->params->page_size * stm->params->pages_per_sector; - -	if (offset % sector_size || len % sector_size) { -		debug("SF: Erase offset/length not multiple of sector size\n"); -		return -1; -	} - -	len /= sector_size; -	cmd[0] = CMD_M25PXX_SE; -	cmd[2] = 0x00; -	cmd[3] = 0x00; - -	ret = spi_claim_bus(flash->spi); -	if (ret) { -		debug("SF: Unable to claim SPI bus\n"); -		return ret; -	} - -	ret = 0; -	for (actual = 0; actual < len; actual++) { -		cmd[1] = offset >> 16; -		offset += sector_size; - -		ret = spi_flash_cmd(flash->spi, CMD_M25PXX_WREN, NULL, 0); -		if (ret < 0) { -			debug("SF: Enabling Write failed\n"); -			break; -		} - -		ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0); -		if (ret < 0) { -			debug("SF: STMicro page erase failed\n"); -			break; -		} - -		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", -	      len * sector_size, offset); - -	spi_release_bus(flash->spi); -	return ret; +	return spi_flash_cmd_erase(flash, CMD_M25PXX_SE, +		stm->params->page_size * stm->params->pages_per_sector, +		offset, len);  }  struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index d8c1cb12d..8470a826b 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -211,64 +211,9 @@ out:  int winbond_erase(struct spi_flash *flash, u32 offset, size_t len)  {  	struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); -	unsigned long sector_size; -	unsigned int page_shift; -	size_t actual; -	int ret; -	u8 cmd[4]; - -	/* -	 * This function currently uses sector erase only. -	 * probably speed things up by using bulk erase -	 * when possible. -	 */ - -	page_shift = stm->params->l2_page_size; -	sector_size = (1 << page_shift) * stm->params->pages_per_sector; - -	if (offset % sector_size || len % sector_size) { -		debug("SF: Erase offset/length not multiple of sector size\n"); -		return -1; -	} - -	len /= sector_size; -	cmd[0] = CMD_W25_SE; - -	ret = spi_claim_bus(flash->spi); -	if (ret) { -		debug("SF: Unable to claim SPI bus\n"); -		return ret; -	} - -	for (actual = 0; actual < len; actual++) { -		winbond_build_address(stm, &cmd[1], offset + actual * sector_size); -		printf("Erase: %02x %02x %02x %02x\n", -				cmd[0], cmd[1], cmd[2], cmd[3]); - -		ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0); -		if (ret < 0) { -			debug("SF: Enabling Write failed\n"); -			goto out; -		} - -		ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0); -		if (ret < 0) { -			debug("SF: Winbond sector erase failed\n"); -			goto out; -		} - -		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", -			len * sector_size, offset); -	ret = 0; - -out: -	spi_release_bus(flash->spi); -	return ret; +	return spi_flash_cmd_erase(flash, CMD_W25_SE, +		(1 << stm->params->l2_page_size) * stm->params->pages_per_sector, +		offset, len);  }  struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) |