Commit 056fbc73d54df64adcb93c513cba708acb2683bd
1 parent
f77f469117
Exists in
master
and in
50 other branches
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; |
include/spi.h
... | ... | @@ -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 { |
include/spi_flash.h
... | ... | @@ -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; |