diff options
| -rw-r--r-- | README | 5 | ||||
| -rw-r--r-- | board/ifm/ac14xx/ac14xx.c | 50 | ||||
| -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/configs/ac14xx.h | 28 | ||||
| -rw-r--r-- | include/spi_flash.h | 10 | 
11 files changed, 398 insertions, 179 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/board/ifm/ac14xx/ac14xx.c b/board/ifm/ac14xx/ac14xx.c index 74425912d..dc2aff099 100644 --- a/board/ifm/ac14xx/ac14xx.c +++ b/board/ifm/ac14xx/ac14xx.c @@ -23,6 +23,10 @@  #include <i2c.h>  #endif +static int eeprom_diag; +static int mac_diag; +static int gpio_diag; +  DECLARE_GLOBAL_DATA_PTR;  static void gpio_configure(void) @@ -37,7 +41,7 @@ static void gpio_configure(void)  	/*  	 * out_be32(&gpioregs->gpdir, 0xC2293020); -	 * workaround for a hardware affect: configure direction in pieces, +	 * workaround for a hardware effect: configure direction in pieces,  	 * setting all outputs at once drops the reset line too low and  	 * makes us lose the MII connection (breaks ethernet for us)  	 */ @@ -126,8 +130,6 @@ static u32 gpio_querykbd(void)  /* excerpt from the recovery's hw_info.h */ -static int eeprom_diag = 1; -  struct __attribute__ ((__packed__)) eeprom_layout {  	char	magic[3];	/** 'ifm' */  	u8	len[2];		/** content length without magic/len fields */ @@ -209,6 +211,7 @@ static int read_eeprom(void)  int mac_read_from_eeprom(void)  {  	const u8 *mac; +	const char *mac_txt;  	if (read_eeprom()) {  		printf("I2C EEPROM read failed.\n"); @@ -230,8 +233,13 @@ int mac_read_from_eeprom(void)  	if (mac && is_valid_ether_addr(mac)) {  		eth_setenv_enetaddr("ethaddr", mac); -		printf("DIAG: %s() MAC value [%s]\n", -			__func__, getenv("ethaddr")); +		if (mac_diag) { +			mac_txt = getenv("ethaddr"); +			if (mac_txt) +				printf("DIAG: MAC value [%s]\n", mac_txt); +			else +				printf("DIAG: failed to setup MAC env\n"); +		}  	}  	return 0; @@ -326,42 +334,38 @@ int misc_init_r(void)  	gpio_configure();  	/* -	 * check the GPIO keyboard, -	 * enforced start of the recovery when +	 * enforce the start of the recovery system when  	 * - the appropriate keys were pressed -	 * - a previous installation was aborted or has failed  	 * - "some" external software told us to +	 * - a previous installation was aborted or has failed  	 */  	want_recovery = 0;  	keys = gpio_querykbd(); -	printf("GPIO keyboard status [0x%08X]\n", keys); -	/* XXX insist in the _exact_ combination? */ +	if (gpio_diag) +		printf("GPIO keyboard status [0x%02X]\n", keys);  	if ((keys & GPIOKEY_BITS_RECOVERY) == GPIOKEY_BITS_RECOVERY) { -		printf("GPIO keyboard requested RECOVERY\n"); -		/* XXX TODO -		 * refine the logic to detect the first keypress, and -		 * wait to recheck IF it was the recovery combination? -		 */ +		printf("detected recovery request (keyboard)\n");  		want_recovery = 1;  	} -	s = getenv("install_in_progress"); +	s = getenv("want_recovery");  	if ((s != NULL) && (*s != '\0')) { -		printf("previous installation aborted, running RECOVERY\n"); +		printf("detected recovery request (environment)\n");  		want_recovery = 1;  	} -	s = getenv("install_failed"); +	s = getenv("install_in_progress");  	if ((s != NULL) && (*s != '\0')) { -		printf("previous installation FAILED, running RECOVERY\n"); +		printf("previous installation has not completed\n");  		want_recovery = 1;  	} -	s = getenv("want_recovery"); +	s = getenv("install_failed");  	if ((s != NULL) && (*s != '\0')) { -		printf("running RECOVERY according to the request\n"); +		printf("previous installation has failed\n");  		want_recovery = 1;  	} - -	if (want_recovery) +	if (want_recovery) { +		printf("enforced start of the recovery system\n");  		setenv("bootcmd", "run recovery"); +	}  	/*  	 * boot the recovery system without waiting; boot the 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/configs/ac14xx.h b/include/configs/ac14xx.h index 7cb10fb01..381bcdda0 100644 --- a/include/configs/ac14xx.h +++ b/include/configs/ac14xx.h @@ -72,7 +72,7 @@  #define CONFIG_SYS_MAX_RAM_SIZE		0x20000000  /* - * DDR Controller Configuration XXX TODO + * DDR Controller Configuration   *   * SYS_CFG:   *	[31:31]	MDDRC Soft Reset:	Diabled @@ -265,7 +265,6 @@  /*   * CS related parameters - * TODO document these   */  /* CS0 Flash */  #define CONFIG_SYS_CS0_CFG		0x00031110 @@ -331,8 +330,6 @@  #endif  #define CONFIG_BAUDRATE			115200	/* ... at 115200 bps */ -#define CONFIG_SYS_BAUDRATE_TABLE  \ -	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 115200}  #define CONSOLE_FIFO_TX_SIZE		FIFOC_PSC3_TX_SIZE  #define CONSOLE_FIFO_TX_ADDR		FIFOC_PSC3_TX_ADDR @@ -497,30 +494,26 @@  #define CONFIG_ENV_OVERWRITE  #define CONFIG_TIMESTAMP -#define CONFIG_HOSTNAME		ac14xx -#define CONFIG_BOOTFILE		"ac14xx/uImage" -#define CONFIG_ROOTPATH		"/opt/eldk/ppc_6xx" -  /* default load addr for tftp and bootm */  #define CONFIG_LOADADDR		400000  #define CONFIG_BOOTDELAY	2	/* -1 disables auto-boot */ -/* XXX TODO need to specify the builtin environment */ +/* the builtin environment and standard greeting */  #define CONFIG_PREBOOT	"echo;"	\  	"echo Type \\\"run flash_nfs\\\" to mount root filesystem over NFS;" \  	"echo"  #define CONFIG_EXTRA_ENV_SETTINGS_DEVEL					\ -	"muster_nr=00\0"						\ +	"muster_nr=-00\0"						\  	"fromram=run ramargs addip addtty; "				\ -		"tftp ${fdt_addr_r} k6m2/ac14xx.dtb-${muster_nr}; "	\ -		"tftp ${kernel_addr_r} k6m2/uImage-${muster_nr}; "	\ -		"tftp ${ramdisk_addr_r} k6m2/uFS-${muster_nr}; "	\ +		"tftp ${fdt_addr_r} ac14xx/ac14xx.dtb${muster_nr}; "	\ +		"tftp ${kernel_addr_r} ac14xx/uImage${muster_nr}; "	\ +		"tftp ${ramdisk_addr_r} ac14xx/uFS${muster_nr}; "	\  		"bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}\0" \  	"fromnfs=run nfsargs addip addtty; "				\ -		"tftp ${fdt_addr_r} k6m2/ac14xx.dtb-${muster_nr}; "	\ -		"tftp ${kernel_addr_r} k6m2/uImage-${muster_nr}; "	\ +		"tftp ${fdt_addr_r} ac14xx/ac14xx.dtb${muster_nr}; "	\ +		"tftp ${kernel_addr_r} ac14xx/uImage${muster_nr}; "	\  		"bootm ${kernel_addr_r} - ${fdt_addr_r}\0"		\  	"fromflash=run nfsargs addip addtty; "				\  		"bootm fc020000 - fc000000\0"				\ @@ -548,12 +541,11 @@  	"u-boot=ac14xx/u-boot.bin\0"					\  	"bootfile=ac14xx/uImage\0"					\  	"fdtfile=ac14xx/ac14xx.dtb\0"					\ -	"rootpath=/opt/eldk/ppc_6xx\n"					\  	"netdev=eth0\0"							\  	"consdev=ttyPSC0\0"						\  	"hostname=ac14xx\0"						\  	"nfsargs=setenv bootargs root=/dev/nfs rw "			\ -		"nfsroot=${serverip}:${rootpath}-${muster_nr}\0"	\ +		"nfsroot=${serverip}:${rootpath}${muster_nr}\0"	\  	"ramargs=setenv bootargs root=/dev/ram rw\0"			\  	"addip=setenv bootargs ${bootargs} "				\  		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}"	\ @@ -583,6 +575,8 @@  #define CONFIG_BOOTCOMMAND	"run production" +#define CONFIG_ARP_TIMEOUT	200UL +  #define CONFIG_FIT		1  #define CONFIG_OF_LIBFDT	1  #define CONFIG_OF_BOARD_SETUP	1 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, |