sf: Add dual memories support - DUAL_PARALLEL
This patch added support for accessing dual memories in parallel connection with single chipselect line from controller. For more info - see doc/SPI/README.dual-flash Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
This commit is contained in:
		
							parent
							
								
									f77f469117
								
							
						
					
					
						commit
						056fbc73d5
					
				|  | @ -54,6 +54,33 @@ SF_DUAL_STACKED_FLASH: | |||
|                by default, if U_PAGE is unset lower memory should accessible, | ||||
|                once user wants to access upper memory need to set U_PAGE. | ||||
| 
 | ||||
| SPI_FLASH_CONN_DUALPARALLEL: | ||||
| 	- dual spi/qspi flash memories are connected with a single chipselect | ||||
| 	  line and these two memories are operating parallel with separate buses. | ||||
| 	- xilinx zynq qspi controller has implemented this feature [1] | ||||
| 
 | ||||
|   +-------------+           CS		+---------------+ | ||||
|   |		|---------------------->|		| | ||||
|   | 		|        I0[3:0]	| Upper Flash	| | ||||
|   | 		|<=====================>| memory	| | ||||
|   |		|	   CLK		| (SPI/QSPI)	| | ||||
|   |		|---------------------->|		| | ||||
|   | Controller	|	    CS		+---------------+ | ||||
|   | SPI/QSPI	|---------------------->|		| | ||||
|   | 		|        I0[3:0]	| Lower Flash	| | ||||
|   | 		|<=====================>| memory	| | ||||
|   |		|	   CLK		| (SPI/QSPI)	| | ||||
|   |		|---------------------->|		| | ||||
|   +-------------+			+---------------+ | ||||
| 
 | ||||
| 	- two memory flash devices should has same hw part attributes (like size, | ||||
| 	  vendor..etc) | ||||
| 	- Configurations: | ||||
| 		Need to enable SEP_BUS[BIT:29],TWO_MEM[BIT:30] on LQSPI_CFG register. | ||||
| 	- Operation: | ||||
| 		Even bits, i.e. bit 0, 2, 4 ., of a data word is located in the lower memory | ||||
| 		and odd bits, i.e. bit 1, 3, 5, ., of a data word is located in the upper memory. | ||||
| 
 | ||||
| Note: Technically there is only one CS line from the controller, but | ||||
| zynq qspi controller has an internal hw logic to enable additional CS | ||||
| when controller is configured for dual memories. | ||||
|  |  | |||
|  | @ -119,7 +119,7 @@ static int spi_flash_bank(struct spi_flash *flash, u32 offset) | |||
| 	u8 bank_sel; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	bank_sel = offset / SPI_FLASH_16MB_BOUN; | ||||
| 	bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift); | ||||
| 
 | ||||
| 	ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); | ||||
| 	if (ret) { | ||||
|  | @ -142,6 +142,9 @@ static void spi_flash_dual_flash(struct spi_flash *flash, u32 *addr) | |||
| 			flash->spi->flags &= ~SPI_XFER_U_PAGE; | ||||
| 		} | ||||
| 		break; | ||||
| 	case SF_DUAL_PARALLEL_FLASH: | ||||
| 		*addr >>= flash->shift; | ||||
| 		break; | ||||
| 	default: | ||||
| 		debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash); | ||||
| 		break; | ||||
|  | @ -388,7 +391,8 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, | |||
| 		if (bank_sel < 0) | ||||
| 			return ret; | ||||
| #endif | ||||
| 		remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1)) - offset; | ||||
| 		remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) * | ||||
| 				(bank_sel + 1)) - offset; | ||||
| 		if (len < remain_len) | ||||
| 			read_len = len; | ||||
| 		else | ||||
|  |  | |||
|  | @ -146,19 +146,20 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi, | |||
| 	flash->read = spi_flash_cmd_read_ops; | ||||
| 
 | ||||
| 	/* Compute the flash size */ | ||||
| 	flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256; | ||||
| 	flash->sector_size = params->sector_size; | ||||
| 	flash->size = flash->sector_size * params->nr_sectors; | ||||
| 	flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0; | ||||
| 	flash->page_size = ((ext_jedec == 0x4d00) ? 512 : 256) << flash->shift; | ||||
| 	flash->sector_size = params->sector_size << flash->shift; | ||||
| 	flash->size = flash->sector_size * params->nr_sectors << flash->shift; | ||||
| 	if (flash->dual_flash & SF_DUAL_STACKED_FLASH) | ||||
| 		flash->size <<= 1; | ||||
| 
 | ||||
| 	/* Compute erase sector and command */ | ||||
| 	if (params->flags & SECT_4K) { | ||||
| 		flash->erase_cmd = CMD_ERASE_4K; | ||||
| 		flash->erase_size = 4096; | ||||
| 		flash->erase_size = 4096 << flash->shift; | ||||
| 	} else if (params->flags & SECT_32K) { | ||||
| 		flash->erase_cmd = CMD_ERASE_32K; | ||||
| 		flash->erase_size = 32768; | ||||
| 		flash->erase_size = 32768 << flash->shift; | ||||
| 	} else { | ||||
| 		flash->erase_cmd = CMD_ERASE_64K; | ||||
| 		flash->erase_size = flash->sector_size; | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ | |||
| 
 | ||||
| /* SPI bus connection options */ | ||||
| #define SPI_CONN_DUAL_SHARED	1 << 0 | ||||
| #define SPI_CONN_DUAL_SEPARATED	1 << 1 | ||||
| 
 | ||||
| /* Header byte that marks the start of the message */ | ||||
| #define SPI_PREAMBLE_END_BYTE	0xec | ||||
|  | @ -66,7 +67,7 @@ | |||
|  * @max_write_size:	If non-zero, the maximum number of bytes which can | ||||
|  *			be written at once, excluding command bytes. | ||||
|  * @memory_map:		Address of read-only SPI flash access. | ||||
|  * @option:		Varies SPI bus options - separate bus. | ||||
|  * @option:		Varies SPI bus options - separate, shared bus. | ||||
|  * @flags:		Indication of SPI flags. | ||||
|  */ | ||||
| struct spi_slave { | ||||
|  |  | |||
|  | @ -40,6 +40,7 @@ enum spi_read_cmds { | |||
| enum spi_dual_flash { | ||||
| 	SF_SINGLE_FLASH = 0, | ||||
| 	SF_DUAL_STACKED_FLASH = 1 << 0, | ||||
| 	SF_DUAL_PARALLEL_FLASH = 1 << 1, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -70,7 +71,8 @@ extern const struct spi_flash_params spi_flash_params_table[]; | |||
|  * | ||||
|  * @spi:		SPI slave | ||||
|  * @name:		Name of SPI flash | ||||
|  * @dual_flash:		Indicates dual flash memories - dual stacked | ||||
|  * @dual_flash:		Indicates dual flash memories - dual stacked, parallel | ||||
|  * @shift:		Flash shift useful in dual parallel | ||||
|  * @size:		Total flash size | ||||
|  * @page_size:		Write (page) size | ||||
|  * @sector_size:	Sector size | ||||
|  | @ -96,6 +98,7 @@ struct spi_flash { | |||
| 	struct spi_slave *spi; | ||||
| 	const char *name; | ||||
| 	u8 dual_flash; | ||||
| 	u8 shift; | ||||
| 
 | ||||
| 	u32 size; | ||||
| 	u32 page_size; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue