Commit 056fbc73d54df64adcb93c513cba708acb2683bd

Authored by Jagannadha Sutradharudu Teki
1 parent f77f469117

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>

Showing 5 changed files with 45 additions and 9 deletions Side-by-side Diff

doc/SPI/README.dual-flash
... ... @@ -54,6 +54,33 @@
54 54 by default, if U_PAGE is unset lower memory should accessible,
55 55 once user wants to access upper memory need to set U_PAGE.
56 56  
  57 +SPI_FLASH_CONN_DUALPARALLEL:
  58 + - dual spi/qspi flash memories are connected with a single chipselect
  59 + line and these two memories are operating parallel with separate buses.
  60 + - xilinx zynq qspi controller has implemented this feature [1]
  61 +
  62 + +-------------+ CS +---------------+
  63 + | |---------------------->| |
  64 + | | I0[3:0] | Upper Flash |
  65 + | |<=====================>| memory |
  66 + | | CLK | (SPI/QSPI) |
  67 + | |---------------------->| |
  68 + | Controller | CS +---------------+
  69 + | SPI/QSPI |---------------------->| |
  70 + | | I0[3:0] | Lower Flash |
  71 + | |<=====================>| memory |
  72 + | | CLK | (SPI/QSPI) |
  73 + | |---------------------->| |
  74 + +-------------+ +---------------+
  75 +
  76 + - two memory flash devices should has same hw part attributes (like size,
  77 + vendor..etc)
  78 + - Configurations:
  79 + Need to enable SEP_BUS[BIT:29],TWO_MEM[BIT:30] on LQSPI_CFG register.
  80 + - Operation:
  81 + Even bits, i.e. bit 0, 2, 4 ., of a data word is located in the lower memory
  82 + and odd bits, i.e. bit 1, 3, 5, ., of a data word is located in the upper memory.
  83 +
57 84 Note: Technically there is only one CS line from the controller, but
58 85 zynq qspi controller has an internal hw logic to enable additional CS
59 86 when controller is configured for dual memories.
drivers/mtd/spi/sf_ops.c
... ... @@ -119,7 +119,7 @@
119 119 u8 bank_sel;
120 120 int ret;
121 121  
122   - bank_sel = offset / SPI_FLASH_16MB_BOUN;
  122 + bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift);
123 123  
124 124 ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
125 125 if (ret) {
... ... @@ -142,6 +142,9 @@
142 142 flash->spi->flags &= ~SPI_XFER_U_PAGE;
143 143 }
144 144 break;
  145 + case SF_DUAL_PARALLEL_FLASH:
  146 + *addr >>= flash->shift;
  147 + break;
145 148 default:
146 149 debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash);
147 150 break;
... ... @@ -388,7 +391,8 @@
388 391 if (bank_sel < 0)
389 392 return ret;
390 393 #endif
391   - remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1)) - offset;
  394 + remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
  395 + (bank_sel + 1)) - offset;
392 396 if (len < remain_len)
393 397 read_len = len;
394 398 else
drivers/mtd/spi/sf_probe.c
... ... @@ -146,19 +146,20 @@
146 146 flash->read = spi_flash_cmd_read_ops;
147 147  
148 148 /* Compute the flash size */
149   - flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256;
150   - flash->sector_size = params->sector_size;
151   - flash->size = flash->sector_size * params->nr_sectors;
  149 + flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
  150 + flash->page_size = ((ext_jedec == 0x4d00) ? 512 : 256) << flash->shift;
  151 + flash->sector_size = params->sector_size << flash->shift;
  152 + flash->size = flash->sector_size * params->nr_sectors << flash->shift;
152 153 if (flash->dual_flash & SF_DUAL_STACKED_FLASH)
153 154 flash->size <<= 1;
154 155  
155 156 /* Compute erase sector and command */
156 157 if (params->flags & SECT_4K) {
157 158 flash->erase_cmd = CMD_ERASE_4K;
158   - flash->erase_size = 4096;
  159 + flash->erase_size = 4096 << flash->shift;
159 160 } else if (params->flags & SECT_32K) {
160 161 flash->erase_cmd = CMD_ERASE_32K;
161   - flash->erase_size = 32768;
  162 + flash->erase_size = 32768 << flash->shift;
162 163 } else {
163 164 flash->erase_cmd = CMD_ERASE_64K;
164 165 flash->erase_size = flash->sector_size;
... ... @@ -47,6 +47,7 @@
47 47  
48 48 /* SPI bus connection options */
49 49 #define SPI_CONN_DUAL_SHARED 1 << 0
  50 +#define SPI_CONN_DUAL_SEPARATED 1 << 1
50 51  
51 52 /* Header byte that marks the start of the message */
52 53 #define SPI_PREAMBLE_END_BYTE 0xec
... ... @@ -66,7 +67,7 @@
66 67 * @max_write_size: If non-zero, the maximum number of bytes which can
67 68 * be written at once, excluding command bytes.
68 69 * @memory_map: Address of read-only SPI flash access.
69   - * @option: Varies SPI bus options - separate bus.
  70 + * @option: Varies SPI bus options - separate, shared bus.
70 71 * @flags: Indication of SPI flags.
71 72 */
72 73 struct spi_slave {
... ... @@ -40,6 +40,7 @@
40 40 enum spi_dual_flash {
41 41 SF_SINGLE_FLASH = 0,
42 42 SF_DUAL_STACKED_FLASH = 1 << 0,
  43 + SF_DUAL_PARALLEL_FLASH = 1 << 1,
43 44 };
44 45  
45 46 /**
... ... @@ -70,7 +71,8 @@
70 71 *
71 72 * @spi: SPI slave
72 73 * @name: Name of SPI flash
73   - * @dual_flash: Indicates dual flash memories - dual stacked
  74 + * @dual_flash: Indicates dual flash memories - dual stacked, parallel
  75 + * @shift: Flash shift useful in dual parallel
74 76 * @size: Total flash size
75 77 * @page_size: Write (page) size
76 78 * @sector_size: Sector size
... ... @@ -96,6 +98,7 @@
96 98 struct spi_slave *spi;
97 99 const char *name;
98 100 u8 dual_flash;
  101 + u8 shift;
99 102  
100 103 u32 size;
101 104 u32 page_size;