@@ -54,6 +54,33 @@ SF_NRF_DUAL_STACKED:
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_nr_flash(struct spi_flash *flash, u32 *addr)
flash->spi->flags &= ~SPI_XFER_U_PAGE;
}
break;
+ case SF_NRF_DUAL_PARALLEL:
+ *addr >>= flash->shift;
+ break;
default:
debug("SF: Unsupported nr_flash=%d\n", flash->nr_flash);
break;
@@ -387,7 +390,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->nr_flash & SF_NRF_DUAL_PARALLEL) ? 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->nr_flash & SF_NRF_DUAL_STACKED)
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 {
@@ -37,6 +37,7 @@ enum spi_read_cmds {
enum spi_nr_flash {
SF_NRF_SINGLE = 0,
SF_NRF_DUAL_STACKED = 1 << 0,
+ SF_NRF_DUAL_PARALLEL = 1 << 1,
};
/**
@@ -67,7 +68,8 @@ extern const struct spi_flash_params spi_flash_params_table[];
*
* @spi: SPI slave
* @name: Name of SPI flash
- * @nr_flash: Indicates no.of flash memories - dual stacked
+ * @nr_flash: Indicates no.of 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
@@ -93,6 +95,7 @@ struct spi_flash {
struct spi_slave *spi;
const char *name;
u8 nr_flash;
+ u8 shift;
u32 size;
u32 page_size;
This patch added support for accessing dual memories in parallel connection with single chipselect line from controller. For more info - see doc/SPI/README.nr-flash Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com> --- doc/SPI/README.nr-flash | 27 +++++++++++++++++++++++++++ drivers/mtd/spi/sf_ops.c | 8 ++++++-- drivers/mtd/spi/sf_probe.c | 11 ++++++----- include/spi.h | 3 ++- include/spi_flash.h | 5 ++++- 5 files changed, 45 insertions(+), 9 deletions(-)