mirror of
				https://github.com/linux-sunxi/u-boot-sunxi.git
				synced 2024-02-12 11:16:03 +08:00 
			
		
		
		
	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:
		@ -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;
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user