diff options
| author | Tom Rini <trini@ti.com> | 2013-06-24 16:37:01 -0400 | 
|---|---|---|
| committer | Tom Rini <trini@ti.com> | 2013-06-24 16:37:01 -0400 | 
| commit | f9c1456cf632175afb7d6b27f42f1aab8432be0f (patch) | |
| tree | 8bac21548110dbfdc2d0e571b8cd36be7ccda20c | |
| parent | 348e47f766ac228fb02d1af562b2e9a4c69355db (diff) | |
| parent | b9e31be0f8adc1a55179ae3b45c9e274f4650007 (diff) | |
| download | olio-uboot-2014.01-f9c1456cf632175afb7d6b27f42f1aab8432be0f.tar.xz olio-uboot-2014.01-f9c1456cf632175afb7d6b27f42f1aab8432be0f.zip | |
Merge branch 'master' of git://git.denx.de/u-boot-spi
| -rw-r--r-- | README | 5 | ||||
| -rw-r--r-- | drivers/mtd/spi/spansion.c | 9 | ||||
| -rw-r--r-- | drivers/mtd/spi/spi_flash.c | 376 | ||||
| -rw-r--r-- | drivers/mtd/spi/spi_flash_internal.h | 39 | ||||
| -rw-r--r-- | drivers/mtd/spi/stmicro.c | 28 | ||||
| -rw-r--r-- | drivers/mtd/spi/winbond.c | 24 | ||||
| -rw-r--r-- | drivers/spi/cf_qspi.c | 2 | ||||
| -rw-r--r-- | drivers/spi/mxc_spi.c | 6 | ||||
| -rw-r--r-- | include/spi_flash.h | 10 | 
9 files changed, 360 insertions, 139 deletions
| @@ -2520,6 +2520,11 @@ CBFS (Coreboot Filesystem) support  		Define this option to include a destructive SPI flash  		test ('sf test'). +		CONFIG_SPI_FLASH_BAR		Ban/Extended Addr Reg + +		Define this option to use the Bank addr/Extended addr +		support on SPI flashes which has size > 16Mbytes. +  - SystemACE Support:  		CONFIG_SYSTEMACE diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index b3ef90f13..3ec2151b3 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -101,7 +101,7 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {  		.idcode2 = 0x4d01,  		.pages_per_sector = 256,  		.nr_sectors = 256, -		.name = "S25FL129P_64K/S25FL128S", +		.name = "S25FL129P_64K/S25FL128S_64K",  	},  	{  		.idcode1 = 0x0219, @@ -110,6 +110,13 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {  		.nr_sectors = 512,  		.name = "S25FL256S_64K",  	}, +	{ +		.idcode1 = 0x0220, +		.idcode2 = 0x4d01, +		.pages_per_sector = 256, +		.nr_sectors = 1024, +		.name = "S25FL512S_64K", +	},  };  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 9991d47a4..6a6fe37e0 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -68,17 +68,60 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,  	return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);  } -int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, -		size_t len, const void *buf) +int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)  { -	unsigned long page_addr, byte_addr, page_size; -	size_t chunk_len, actual; +	struct spi_slave *spi = flash->spi; +	unsigned long timebase;  	int ret; -	u8 cmd[4]; +	u8 status; +	u8 check_status = 0x0; +	u8 poll_bit = STATUS_WIP; +	u8 cmd = flash->poll_cmd; -	page_size = flash->page_size; -	page_addr = offset / page_size; -	byte_addr = offset % page_size; +	if (cmd == CMD_FLAG_STATUS) { +		poll_bit = STATUS_PEC; +		check_status = poll_bit; +	} + +	ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); +	if (ret) { +		debug("SF: fail to read %s status register\n", +			cmd == CMD_READ_STATUS ? "read" : "flag"); +		return ret; +	} + +	timebase = get_timer(0); +	do { +		WATCHDOG_RESET(); + +		ret = spi_xfer(spi, 8, NULL, &status, 0); +		if (ret) +			return -1; + +		if ((status & poll_bit) == check_status) +			break; + +	} while (get_timer(timebase) < timeout); + +	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); + +	if ((status & poll_bit) == check_status) +		return 0; + +	/* Timed out */ +	debug("SF: time out!\n"); +	return -1; +} + +int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, +		size_t cmd_len, const void *buf, size_t buf_len) +{ +	struct spi_slave *spi = flash->spi; +	unsigned long timeout = SPI_FLASH_PROG_TIMEOUT; +	int ret; + +	if (buf == NULL) +		timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;  	ret = spi_claim_bus(flash->spi);  	if (ret) { @@ -86,45 +129,122 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,  		return ret;  	} +	ret = spi_flash_cmd_write_enable(flash); +	if (ret < 0) { +		debug("SF: enabling write failed\n"); +		return ret; +	} + +	ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len); +	if (ret < 0) { +		debug("SF: write cmd failed\n"); +		return ret; +	} + +	ret = spi_flash_cmd_wait_ready(flash, timeout); +	if (ret < 0) { +		debug("SF: write %s timed out\n", +			timeout == SPI_FLASH_PROG_TIMEOUT ? +			"program" : "page erase"); +		return ret; +	} + +	spi_release_bus(spi); + +	return ret; +} + +int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) +{ +	u32 erase_size; +	u8 cmd[4]; +	int ret = -1; + +	erase_size = flash->sector_size; +	if (offset % erase_size || len % erase_size) { +		debug("SF: Erase offset/length not multiple of erase size\n"); +		return -1; +	} + +	if (erase_size == 4096) +		cmd[0] = CMD_ERASE_4K; +	else +		cmd[0] = CMD_ERASE_64K; + +	while (len) { +#ifdef CONFIG_SPI_FLASH_BAR +		u8 bank_sel; + +		bank_sel = offset / SPI_FLASH_16MB_BOUN; + +		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); +		if (ret) { +			debug("SF: fail to set bank%d\n", bank_sel); +			return ret; +		} +#endif +		spi_flash_addr(offset, cmd); + +		debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], +		      cmd[2], cmd[3], offset); + +		ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); +		if (ret < 0) { +			debug("SF: erase failed\n"); +			break; +		} + +		offset += erase_size; +		len -= erase_size; +	} + +	return ret; +} + +int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, +		size_t len, const void *buf) +{ +	unsigned long byte_addr, page_size; +	size_t chunk_len, actual; +	u8 cmd[4]; +	int ret = -1; + +	page_size = flash->page_size; +  	cmd[0] = CMD_PAGE_PROGRAM;  	for (actual = 0; actual < len; actual += chunk_len) { +#ifdef CONFIG_SPI_FLASH_BAR +		u8 bank_sel; + +		bank_sel = offset / SPI_FLASH_16MB_BOUN; + +		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); +		if (ret) { +			debug("SF: fail to set bank%d\n", bank_sel); +			return ret; +		} +#endif +		byte_addr = offset % page_size;  		chunk_len = min(len - actual, page_size - byte_addr);  		if (flash->spi->max_write_size)  			chunk_len = min(chunk_len, flash->spi->max_write_size); -		cmd[1] = page_addr >> 8; -		cmd[2] = page_addr; -		cmd[3] = byte_addr; +		spi_flash_addr(offset, cmd);  		debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",  		      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); -		ret = spi_flash_cmd_write_enable(flash); -		if (ret < 0) { -			debug("SF: enabling write failed\n"); -			break; -		} - -		ret = spi_flash_cmd_write(flash->spi, cmd, 4, -					  buf + actual, chunk_len); +		ret = spi_flash_write_common(flash, cmd, sizeof(cmd), +					buf + actual, chunk_len);  		if (ret < 0) {  			debug("SF: write failed\n");  			break;  		} -		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); -		if (ret) -			break; - -		byte_addr += chunk_len; -		if (byte_addr == page_size) { -			page_addr++; -			byte_addr = 0; -		} +		offset += chunk_len;  	} -	spi_release_bus(flash->spi);  	return ret;  } @@ -134,8 +254,18 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,  	struct spi_slave *spi = flash->spi;  	int ret; -	spi_claim_bus(spi); +	ret = spi_claim_bus(flash->spi); +	if (ret) { +		debug("SF: unable to claim SPI bus\n"); +		return ret; +	} +  	ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); +	if (ret < 0) { +		debug("SF: read cmd failed\n"); +		return ret; +	} +  	spi_release_bus(spi);  	return ret; @@ -144,7 +274,9 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,  int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,  		size_t len, void *data)  { -	u8 cmd[5]; +	u8 cmd[5], bank_sel = 0; +	u32 remain_len, read_len; +	int ret = -1;  	/* Handle memory-mapped SPI */  	if (flash->memory_map) { @@ -153,130 +285,114 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,  	}  	cmd[0] = CMD_READ_ARRAY_FAST; -	spi_flash_addr(offset, cmd);  	cmd[4] = 0x00; -	return spi_flash_read_common(flash, cmd, sizeof(cmd), data, len); -} - -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; -	} +	while (len) { +#ifdef CONFIG_SPI_FLASH_BAR +		bank_sel = offset / SPI_FLASH_16MB_BOUN; -	timebase = get_timer(0); -	do { -		WATCHDOG_RESET(); +		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); +		if (ret) { +			debug("SF: fail to set bank%d\n", bank_sel); +			return ret; +		} +#endif +		remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1) - offset); +		if (len < remain_len) +			read_len = len; +		else +			read_len = remain_len; -		ret = spi_xfer(spi, 8, NULL, &status, 0); -		if (ret) -			return -1; +		spi_flash_addr(offset, cmd); -		if ((status & poll_bit) == 0) +		ret = spi_flash_read_common(flash, cmd, sizeof(cmd), +							data, read_len); +		if (ret < 0) { +			debug("SF: read failed\n");  			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; -} +		offset += read_len; +		len -= read_len; +		data += read_len; +	} -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); +	return ret;  } -int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) +int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)  { -	u32 end, erase_size; +	u8 cmd;  	int ret; -	u8 cmd[4]; - -	erase_size = flash->sector_size; -	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"); +	cmd = CMD_WRITE_STATUS; +	ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1); +	if (ret < 0) { +		debug("SF: fail to write status register\n");  		return ret;  	} -	if (erase_size == 4096) -		cmd[0] = CMD_ERASE_4K; -	else -		cmd[0] = CMD_ERASE_64K; -	end = offset + 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_write_enable(flash); -		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; -	} - - out: -	spi_release_bus(flash->spi); -	return ret; +	return 0;  } -int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) +#ifdef CONFIG_SPI_FLASH_BAR +int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)  {  	u8 cmd;  	int ret; -	ret = spi_flash_cmd_write_enable(flash); +	if (flash->bank_curr == bank_sel) { +		debug("SF: not require to enable bank%d\n", bank_sel); +		return 0; +	} + +	cmd = flash->bank_write_cmd; +	ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);  	if (ret < 0) { -		debug("SF: enabling write failed\n"); +		debug("SF: fail to write bank register\n");  		return ret;  	} +	flash->bank_curr = bank_sel; -	cmd = CMD_WRITE_STATUS; -	ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &sr, 1); -	if (ret) { -		debug("SF: fail to write status register\n"); -		return ret; +	return 0; +} + +int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0) +{ +	u8 cmd; +	u8 curr_bank = 0; + +	/* discover bank cmds */ +	switch (idcode0) { +	case SPI_FLASH_SPANSION_IDCODE0: +		flash->bank_read_cmd = CMD_BANKADDR_BRRD; +		flash->bank_write_cmd = CMD_BANKADDR_BRWR; +		break; +	case SPI_FLASH_STMICRO_IDCODE0: +	case SPI_FLASH_WINBOND_IDCODE0: +		flash->bank_read_cmd = CMD_EXTNADDR_RDEAR; +		flash->bank_write_cmd = CMD_EXTNADDR_WREAR; +		break; +	default: +		printf("SF: Unsupported bank commands %02x\n", idcode0); +		return -1;  	} -	ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); -	if (ret < 0) { -		debug("SF: write status register timed out\n"); -		return ret; +	/* read the bank reg - on which bank the flash is in currently */ +	cmd = flash->bank_read_cmd; +	if (flash->size > SPI_FLASH_16MB_BOUN) { +		if (spi_flash_read_common(flash, &cmd, 1, &curr_bank, 1)) { +			debug("SF: fail to read bank addr register\n"); +			return -1; +		} +		flash->bank_curr = curr_bank; +	} else { +		flash->bank_curr = curr_bank;  	}  	return 0;  } +#endif  #ifdef CONFIG_OF_CONTROL  int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) @@ -425,6 +541,13 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,  		goto err_manufacturer_probe;  	} +#ifdef CONFIG_SPI_FLASH_BAR +	/* Configure the BAR - disover bank cmds and read current bank  */ +	ret = spi_flash_bank_config(flash, *idp); +	if (ret < 0) +		goto err_manufacturer_probe; +#endif +  #ifdef CONFIG_OF_CONTROL  	if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {  		debug("SF: FDT decode error\n"); @@ -437,6 +560,12 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,  	if (flash->memory_map)  		printf(", mapped at %p", flash->memory_map);  	puts("\n"); +#ifndef CONFIG_SPI_FLASH_BAR +	if (flash->size > SPI_FLASH_16MB_BOUN) { +		puts("SF: Warning - Only lower 16MiB accessible,"); +		puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); +	} +#endif  	spi_release_bus(spi); @@ -467,6 +596,7 @@ void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi,  	/* Set up some basic fields - caller will sort out sizes */  	flash->spi = spi;  	flash->name = name; +	flash->poll_cmd = CMD_READ_STATUS;  	flash->read = spi_flash_cmd_read_fast;  	flash->write = spi_flash_cmd_write_multi; diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index e0afbc3d8..af1afa96c 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -22,14 +22,31 @@  #define CMD_PAGE_PROGRAM		0x02  #define CMD_WRITE_DISABLE		0x04  #define CMD_READ_STATUS			0x05 +#define CMD_FLAG_STATUS			0x70  #define CMD_WRITE_ENABLE		0x06  #define CMD_ERASE_4K			0x20  #define CMD_ERASE_32K			0x52  #define CMD_ERASE_64K			0xd8  #define CMD_ERASE_CHIP			0xc7 +#define SPI_FLASH_16MB_BOUN		0x1000000 + +/* Manufacture ID's */ +#define SPI_FLASH_SPANSION_IDCODE0	0x01 +#define SPI_FLASH_STMICRO_IDCODE0	0x20 +#define SPI_FLASH_WINBOND_IDCODE0	0xef + +#ifdef CONFIG_SPI_FLASH_BAR +/* Bank addr access commands */ +# define CMD_BANKADDR_BRWR		0x17 +# define CMD_BANKADDR_BRRD		0x16 +# define CMD_EXTNADDR_WREAR		0xC5 +# define CMD_EXTNADDR_RDEAR		0xC8 +#endif +  /* Common status */  #define STATUS_WIP			0x01 +#define STATUS_PEC			0x80  /* 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); @@ -77,16 +94,30 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)  /* Program the status register. */  int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr); +#ifdef CONFIG_SPI_FLASH_BAR +/* Program the bank address register */ +int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel); + +/* Configure the BAR - discover the bank cmds */ +int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0); +#endif +  /*   * Same as spi_flash_cmd_read() except it also claims/releases the SPI   * bus. Used as common part of the ->read() operation.   */  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); +/* + * Used for spi_flash write operation + * - SPI claim + * - spi_flash_cmd_write_enable + * - spi_flash_cmd_write + * - spi_flash_cmd_wait_ready + * - SPI release + */ +int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, +		size_t cmd_len, const void *buf, size_t buf_len);  /*   * Send the read status command to the device and wait for the wip diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index 2a9972bd4..7e41ee132 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -140,6 +140,30 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {  		.nr_sectors = 512,  		.name = "N25Q256A",  	}, +	{ +		.id = 0xba20, +		.pages_per_sector = 256, +		.nr_sectors = 1024, +		.name = "N25Q512", +	}, +	{ +		.id = 0xbb20, +		.pages_per_sector = 256, +		.nr_sectors = 1024, +		.name = "N25Q512A", +	}, +	{ +		.id = 0xba21, +		.pages_per_sector = 256, +		.nr_sectors = 2048, +		.name = "N25Q1024", +	}, +	{ +		.id = 0xbb21, +		.pages_per_sector = 256, +		.nr_sectors = 2048, +		.name = "N25Q1024A", +	},  };  struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) @@ -186,5 +210,9 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)  	flash->sector_size = 256 * params->pages_per_sector;  	flash->size = flash->sector_size * params->nr_sectors; +	/* for >= 512MiB flashes, use flag status instead of read_status */ +	if (flash->size >= 0x4000000) +		flash->poll_cmd = CMD_FLAG_STATUS; +  	return flash;  } diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index 845780849..c399bf14d 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -55,27 +55,27 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {  	{  		.id			= 0x4014,  		.nr_blocks		= 16, -		.name			= "W25Q80BL", +		.name			= "W25Q80BL/W25Q80BV",  	},  	{  		.id			= 0x4015,  		.nr_blocks		= 32, -		.name			= "W25Q16", +		.name			= "W25Q16CL/W25Q16DV",  	},  	{  		.id			= 0x4016,  		.nr_blocks		= 64, -		.name			= "W25Q32", +		.name			= "W25Q32BV/W25Q32FV_SPI",  	},  	{  		.id			= 0x4017,  		.nr_blocks		= 128, -		.name			= "W25Q64", +		.name			= "W25Q64CV/W25Q64FV_SPI",  	},  	{  		.id			= 0x4018,  		.nr_blocks		= 256, -		.name			= "W25Q128", +		.name			= "W25Q128BV/W25Q128FV_SPI",  	},  	{  		.id			= 0x4019, @@ -88,14 +88,24 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {  		.name			= "W25Q80BW",  	},  	{ +		.id			= 0x6015, +		.nr_blocks		= 32, +		.name			= "W25Q16DW", +	}, +	{  		.id			= 0x6016,  		.nr_blocks		= 64, -		.name			= "W25Q32DW", +		.name			= "W25Q32DW/W25Q32FV_QPI",  	},  	{  		.id			= 0x6017,  		.nr_blocks		= 128, -		.name			= "W25Q64DW", +		.name			= "W25Q64DW/W25Q64FV_QPI", +	}, +	{ +		.id			= 0x6018, +		.nr_blocks		= 256, +		.name			= "W25Q128FW/W25Q128FV_QPI",  	},  }; diff --git a/drivers/spi/cf_qspi.c b/drivers/spi/cf_qspi.c index a37ac4e52..06bcf91a4 100644 --- a/drivers/spi/cf_qspi.c +++ b/drivers/spi/cf_qspi.c @@ -171,7 +171,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,  	volatile qspi_t *qspi = dev->regs;  	u8 *txbuf = (u8 *)dout;  	u8 *rxbuf = (u8 *)din; -	u32 count = ((bitlen / 8) + (bitlen % 8 ? 1 : 0)); +	u32 count = DIV_ROUND_UP(bitlen, 8);  	u32 n, i = 0;  	/* Sanitize arguments */ diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index 5bed85878..2ea322833 100644 --- a/drivers/spi/mxc_spi.c +++ b/drivers/spi/mxc_spi.c @@ -224,7 +224,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,  	const u8 *dout, u8 *din, unsigned long flags)  {  	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave); -	int nbytes = (bitlen + 7) / 8; +	int nbytes = DIV_ROUND_UP(bitlen, 8);  	u32 data, cnt, i;  	struct cspi_regs *regs = (struct cspi_regs *)mxcs->base; @@ -294,7 +294,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,  	/* Transfer completed, clear any pending request */  	reg_write(®s->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF); -	nbytes = (bitlen + 7) / 8; +	nbytes = DIV_ROUND_UP(bitlen, 8);  	cnt = nbytes % 32; @@ -330,7 +330,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,  int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,  		void *din, unsigned long flags)  { -	int n_bytes = (bitlen + 7) / 8; +	int n_bytes = DIV_ROUND_UP(bitlen, 8);  	int n_bits;  	int ret;  	u32 blk_size; diff --git a/include/spi_flash.h b/include/spi_flash.h index 3b6a44edc..e80785f55 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -38,6 +38,16 @@ struct spi_flash {  	u32		page_size;  	/* Erase (sector) size */  	u32		sector_size; +#ifdef CONFIG_SPI_FLASH_BAR +	/* Bank read cmd */ +	u8		bank_read_cmd; +	/* Bank write cmd */ +	u8		bank_write_cmd; +	/* Current flash bank */ +	u8		bank_curr; +#endif +	/* Poll cmd - for flash erase/program */ +	u8		poll_cmd;  	void *memory_map;	/* Address of read-only SPI flash access */  	int		(*read)(struct spi_flash *flash, u32 offset, |