Commit f77f469117ab3184ac45683a50dc446265be28cc

Authored by Jagannadha Sutradharudu Teki
1 parent ab92224f45

sf: Add dual memories support - DUAL_STACKED

This patch added support for accessing dual memories in
stacked 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 6 changed files with 138 additions and 11 deletions Side-by-side Diff

doc/SPI/README.dual-flash
  1 +SPI/QSPI Dual flash connection modes:
  2 +=====================================
  3 +
  4 +This describes how SPI/QSPI flash memories are connected to a given
  5 +controller in a single chip select line.
  6 +
  7 +Current spi_flash framework supports, single flash memory connected
  8 +to a given controller with single chip select line, but there are some
  9 +hw logics(ex: xilinx zynq qspi) that describes two/dual memories are
  10 +connected with a single chip select line from a controller.
  11 +
  12 +"dual_flash" from include/spi.h describes these types of connection mode
  13 +
  14 +Possible connections:
  15 +--------------------
  16 +SF_SINGLE_FLASH:
  17 + - single spi flash memory connected with single chip select line.
  18 +
  19 + +------------+ CS +---------------+
  20 + | |----------------------->| |
  21 + | Controller | I0[3:0] | Flash memory |
  22 + | SPI/QSPI |<======================>| (SPI/QSPI) |
  23 + | | CLK | |
  24 + | |----------------------->| |
  25 + +------------+ +---------------+
  26 +
  27 +SF_DUAL_STACKED_FLASH:
  28 + - dual spi/qspi flash memories are connected with a single chipselect
  29 + line and these two memories are operating stacked fasion with shared buses.
  30 + - xilinx zynq qspi controller has implemented this feature [1]
  31 +
  32 + +------------+ CS +---------------+
  33 + | |---------------------->| |
  34 + | | I0[3:0] | Upper Flash |
  35 + | | +=========>| memory |
  36 + | | | CLK | (SPI/QSPI) |
  37 + | | | +---->| |
  38 + | Controller | CS | | +---------------+
  39 + | SPI/QSPI |------------|----|---->| |
  40 + | | I0[3:0] | | | Lower Flash |
  41 + | |<===========+====|====>| memory |
  42 + | | CLK | | (SPI/QSPI) |
  43 + | |-----------------+---->| |
  44 + +------------+ +---------------+
  45 +
  46 + - two memory flash devices should has same hw part attributes (like size,
  47 + vendor..etc)
  48 + - Configurations:
  49 + on LQSPI_CFG register, Enable TWO_MEM[BIT:30] on LQSPI_CFG
  50 + Enable U_PAGE[BIT:28] if U_PAGE flag set - upper memory
  51 + Disable U_PAGE[BIT:28] if U_PAGE flag unset - lower memory
  52 + - Operation:
  53 + accessing memories serially like one after another.
  54 + by default, if U_PAGE is unset lower memory should accessible,
  55 + once user wants to access upper memory need to set U_PAGE.
  56 +
  57 +Note: Technically there is only one CS line from the controller, but
  58 +zynq qspi controller has an internal hw logic to enable additional CS
  59 +when controller is configured for dual memories.
  60 +
  61 +[1] http://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf
  62 +
  63 +--
  64 +Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
  65 +05-01-2014.
drivers/mtd/spi/sf.c
... ... @@ -18,6 +18,9 @@
18 18 unsigned long flags = SPI_XFER_BEGIN;
19 19 int ret;
20 20  
  21 + if (spi->flags & SPI_XFER_U_PAGE)
  22 + flags |= SPI_XFER_U_PAGE;
  23 +
21 24 if (data_len == 0)
22 25 flags |= SPI_XFER_END;
23 26  
drivers/mtd/spi/sf_ops.c
... ... @@ -131,10 +131,28 @@
131 131 }
132 132 #endif
133 133  
  134 +static void spi_flash_dual_flash(struct spi_flash *flash, u32 *addr)
  135 +{
  136 + switch (flash->dual_flash) {
  137 + case SF_DUAL_STACKED_FLASH:
  138 + if (*addr >= (flash->size >> 1)) {
  139 + *addr -= flash->size >> 1;
  140 + flash->spi->flags |= SPI_XFER_U_PAGE;
  141 + } else {
  142 + flash->spi->flags &= ~SPI_XFER_U_PAGE;
  143 + }
  144 + break;
  145 + default:
  146 + debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash);
  147 + break;
  148 + }
  149 +}
  150 +
134 151 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
135 152 {
136 153 struct spi_slave *spi = flash->spi;
137 154 unsigned long timebase;
  155 + unsigned long flags = SPI_XFER_BEGIN;
138 156 int ret;
139 157 u8 status;
140 158 u8 check_status = 0x0;
... ... @@ -146,7 +164,10 @@
146 164 check_status = poll_bit;
147 165 }
148 166  
149   - ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
  167 + if (spi->flags & SPI_XFER_U_PAGE)
  168 + flags |= SPI_XFER_U_PAGE;
  169 +
  170 + ret = spi_xfer(spi, 8, &cmd, NULL, flags);
150 171 if (ret) {
151 172 debug("SF: fail to read %s status register\n",
152 173 cmd == CMD_READ_STATUS ? "read" : "flag");
... ... @@ -219,7 +240,7 @@
219 240  
220 241 int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
221 242 {
222   - u32 erase_size;
  243 + u32 erase_size, erase_addr;
223 244 u8 cmd[SPI_FLASH_CMD_LEN];
224 245 int ret = -1;
225 246  
226 247  
227 248  
228 249  
... ... @@ -231,15 +252,20 @@
231 252  
232 253 cmd[0] = flash->erase_cmd;
233 254 while (len) {
  255 + erase_addr = offset;
  256 +
  257 + if (flash->dual_flash > SF_SINGLE_FLASH)
  258 + spi_flash_dual_flash(flash, &erase_addr);
  259 +
234 260 #ifdef CONFIG_SPI_FLASH_BAR
235   - ret = spi_flash_bank(flash, offset);
  261 + ret = spi_flash_bank(flash, erase_addr);
236 262 if (ret < 0)
237 263 return ret;
238 264 #endif
239   - spi_flash_addr(offset, cmd);
  265 + spi_flash_addr(erase_addr, cmd);
240 266  
241 267 debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
242   - cmd[2], cmd[3], offset);
  268 + cmd[2], cmd[3], erase_addr);
243 269  
244 270 ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
245 271 if (ret < 0) {
... ... @@ -258,6 +284,7 @@
258 284 size_t len, const void *buf)
259 285 {
260 286 unsigned long byte_addr, page_size;
  287 + u32 write_addr;
261 288 size_t chunk_len, actual;
262 289 u8 cmd[SPI_FLASH_CMD_LEN];
263 290 int ret = -1;
264 291  
... ... @@ -266,8 +293,13 @@
266 293  
267 294 cmd[0] = flash->write_cmd;
268 295 for (actual = 0; actual < len; actual += chunk_len) {
  296 + write_addr = offset;
  297 +
  298 + if (flash->dual_flash > SF_SINGLE_FLASH)
  299 + spi_flash_dual_flash(flash, &write_addr);
  300 +
269 301 #ifdef CONFIG_SPI_FLASH_BAR
270   - ret = spi_flash_bank(flash, offset);
  302 + ret = spi_flash_bank(flash, write_addr);
271 303 if (ret < 0)
272 304 return ret;
273 305 #endif
... ... @@ -277,7 +309,7 @@
277 309 if (flash->spi->max_write_size)
278 310 chunk_len = min(chunk_len, flash->spi->max_write_size);
279 311  
280   - spi_flash_addr(offset, cmd);
  312 + spi_flash_addr(write_addr, cmd);
281 313  
282 314 debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
283 315 buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
... ... @@ -322,7 +354,7 @@
322 354 size_t len, void *data)
323 355 {
324 356 u8 *cmd, cmdsz;
325   - u32 remain_len, read_len;
  357 + u32 remain_len, read_len, read_addr;
326 358 int bank_sel = 0;
327 359 int ret = -1;
328 360  
329 361  
... ... @@ -346,8 +378,13 @@
346 378  
347 379 cmd[0] = flash->read_cmd;
348 380 while (len) {
  381 + read_addr = offset;
  382 +
  383 + if (flash->dual_flash > SF_SINGLE_FLASH)
  384 + spi_flash_dual_flash(flash, &read_addr);
  385 +
349 386 #ifdef CONFIG_SPI_FLASH_BAR
350   - bank_sel = spi_flash_bank(flash, offset);
  387 + bank_sel = spi_flash_bank(flash, read_addr);
351 388 if (bank_sel < 0)
352 389 return ret;
353 390 #endif
... ... @@ -357,7 +394,7 @@
357 394 else
358 395 read_len = remain_len;
359 396  
360   - spi_flash_addr(offset, cmd);
  397 + spi_flash_addr(read_addr, cmd);
361 398  
362 399 ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
363 400 if (ret < 0) {
drivers/mtd/spi/sf_probe.c
... ... @@ -134,6 +134,7 @@
134 134 flash->spi = spi;
135 135 flash->name = params->name;
136 136 flash->memory_map = spi->memory_map;
  137 + flash->dual_flash = flash->spi->option;
137 138  
138 139 /* Assign spi_flash ops */
139 140 flash->write = spi_flash_cmd_write_ops;
... ... @@ -148,6 +149,8 @@
148 149 flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256;
149 150 flash->sector_size = params->sector_size;
150 151 flash->size = flash->sector_size * params->nr_sectors;
  152 + if (flash->dual_flash & SF_DUAL_STACKED_FLASH)
  153 + flash->size <<= 1;
151 154  
152 155 /* Compute erase sector and command */
153 156 if (params->flags & SECT_4K) {
... ... @@ -324,7 +327,10 @@
324 327 puts("\n");
325 328 #endif
326 329 #ifndef CONFIG_SPI_FLASH_BAR
327   - if (flash->size > SPI_FLASH_16MB_BOUN) {
  330 + if (((flash->dual_flash == SF_SINGLE_FLASH) &&
  331 + (flash->size > SPI_FLASH_16MB_BOUN)) ||
  332 + ((flash->dual_flash > SF_SINGLE_FLASH) &&
  333 + (flash->size > SPI_FLASH_16MB_BOUN << 1))) {
328 334 puts("SF: Warning - Only lower 16MiB accessible,");
329 335 puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
330 336 }
... ... @@ -30,6 +30,7 @@
30 30 #define SPI_XFER_MMAP 0x08 /* Memory Mapped start */
31 31 #define SPI_XFER_MMAP_END 0x10 /* Memory Mapped End */
32 32 #define SPI_XFER_ONCE (SPI_XFER_BEGIN | SPI_XFER_END)
  33 +#define SPI_XFER_U_PAGE (1 << 5)
33 34  
34 35 /* SPI TX operation modes */
35 36 #define SPI_OPM_TX_QPP 1 << 0
... ... @@ -44,6 +45,9 @@
44 45 SPI_OPM_RX_DIO | SPI_OPM_RX_QOF | \
45 46 SPI_OPM_RX_QIOF
46 47  
  48 +/* SPI bus connection options */
  49 +#define SPI_CONN_DUAL_SHARED 1 << 0
  50 +
47 51 /* Header byte that marks the start of the message */
48 52 #define SPI_PREAMBLE_END_BYTE 0xec
49 53  
... ... @@ -62,6 +66,8 @@
62 66 * @max_write_size: If non-zero, the maximum number of bytes which can
63 67 * be written at once, excluding command bytes.
64 68 * @memory_map: Address of read-only SPI flash access.
  69 + * @option: Varies SPI bus options - separate bus.
  70 + * @flags: Indication of SPI flags.
65 71 */
66 72 struct spi_slave {
67 73 unsigned int bus;
... ... @@ -71,6 +77,8 @@
71 77 unsigned int wordlen;
72 78 unsigned int max_write_size;
73 79 void *memory_map;
  80 + u8 option;
  81 + u8 flags;
74 82 };
75 83  
76 84 /**
... ... @@ -36,6 +36,12 @@
36 36 #define RD_EXTN ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST
37 37 #define RD_FULL RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST
38 38  
  39 +/* Dual SPI flash memories */
  40 +enum spi_dual_flash {
  41 + SF_SINGLE_FLASH = 0,
  42 + SF_DUAL_STACKED_FLASH = 1 << 0,
  43 +};
  44 +
39 45 /**
40 46 * struct spi_flash_params - SPI/QSPI flash device params structure
41 47 *
... ... @@ -64,6 +70,7 @@
64 70 *
65 71 * @spi: SPI slave
66 72 * @name: Name of SPI flash
  73 + * @dual_flash: Indicates dual flash memories - dual stacked
67 74 * @size: Total flash size
68 75 * @page_size: Write (page) size
69 76 * @sector_size: Sector size
... ... @@ -88,6 +95,7 @@
88 95 struct spi_flash {
89 96 struct spi_slave *spi;
90 97 const char *name;
  98 + u8 dual_flash;
91 99  
92 100 u32 size;
93 101 u32 page_size;