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:
parent
f77f469117
commit
056fbc73d5
@ -54,6 +54,33 @@ SF_DUAL_STACKED_FLASH:
|
|||||||
by default, if U_PAGE is unset lower memory should accessible,
|
by default, if U_PAGE is unset lower memory should accessible,
|
||||||
once user wants to access upper memory need to set U_PAGE.
|
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
|
Note: Technically there is only one CS line from the controller, but
|
||||||
zynq qspi controller has an internal hw logic to enable additional CS
|
zynq qspi controller has an internal hw logic to enable additional CS
|
||||||
when controller is configured for dual memories.
|
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;
|
u8 bank_sel;
|
||||||
int ret;
|
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);
|
ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
|
||||||
if (ret) {
|
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;
|
flash->spi->flags &= ~SPI_XFER_U_PAGE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SF_DUAL_PARALLEL_FLASH:
|
||||||
|
*addr >>= flash->shift;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash);
|
debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash);
|
||||||
break;
|
break;
|
||||||
@ -388,7 +391,8 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
|
|||||||
if (bank_sel < 0)
|
if (bank_sel < 0)
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#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)
|
if (len < remain_len)
|
||||||
read_len = len;
|
read_len = len;
|
||||||
else
|
else
|
||||||
|
@ -146,19 +146,20 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
|
|||||||
flash->read = spi_flash_cmd_read_ops;
|
flash->read = spi_flash_cmd_read_ops;
|
||||||
|
|
||||||
/* Compute the flash size */
|
/* Compute the flash size */
|
||||||
flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256;
|
flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
|
||||||
flash->sector_size = params->sector_size;
|
flash->page_size = ((ext_jedec == 0x4d00) ? 512 : 256) << flash->shift;
|
||||||
flash->size = flash->sector_size * params->nr_sectors;
|
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)
|
if (flash->dual_flash & SF_DUAL_STACKED_FLASH)
|
||||||
flash->size <<= 1;
|
flash->size <<= 1;
|
||||||
|
|
||||||
/* Compute erase sector and command */
|
/* Compute erase sector and command */
|
||||||
if (params->flags & SECT_4K) {
|
if (params->flags & SECT_4K) {
|
||||||
flash->erase_cmd = CMD_ERASE_4K;
|
flash->erase_cmd = CMD_ERASE_4K;
|
||||||
flash->erase_size = 4096;
|
flash->erase_size = 4096 << flash->shift;
|
||||||
} else if (params->flags & SECT_32K) {
|
} else if (params->flags & SECT_32K) {
|
||||||
flash->erase_cmd = CMD_ERASE_32K;
|
flash->erase_cmd = CMD_ERASE_32K;
|
||||||
flash->erase_size = 32768;
|
flash->erase_size = 32768 << flash->shift;
|
||||||
} else {
|
} else {
|
||||||
flash->erase_cmd = CMD_ERASE_64K;
|
flash->erase_cmd = CMD_ERASE_64K;
|
||||||
flash->erase_size = flash->sector_size;
|
flash->erase_size = flash->sector_size;
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
/* SPI bus connection options */
|
/* SPI bus connection options */
|
||||||
#define SPI_CONN_DUAL_SHARED 1 << 0
|
#define SPI_CONN_DUAL_SHARED 1 << 0
|
||||||
|
#define SPI_CONN_DUAL_SEPARATED 1 << 1
|
||||||
|
|
||||||
/* Header byte that marks the start of the message */
|
/* Header byte that marks the start of the message */
|
||||||
#define SPI_PREAMBLE_END_BYTE 0xec
|
#define SPI_PREAMBLE_END_BYTE 0xec
|
||||||
@ -66,7 +67,7 @@
|
|||||||
* @max_write_size: If non-zero, the maximum number of bytes which can
|
* @max_write_size: If non-zero, the maximum number of bytes which can
|
||||||
* be written at once, excluding command bytes.
|
* be written at once, excluding command bytes.
|
||||||
* @memory_map: Address of read-only SPI flash access.
|
* @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.
|
* @flags: Indication of SPI flags.
|
||||||
*/
|
*/
|
||||||
struct spi_slave {
|
struct spi_slave {
|
||||||
|
@ -40,6 +40,7 @@ enum spi_read_cmds {
|
|||||||
enum spi_dual_flash {
|
enum spi_dual_flash {
|
||||||
SF_SINGLE_FLASH = 0,
|
SF_SINGLE_FLASH = 0,
|
||||||
SF_DUAL_STACKED_FLASH = 1 << 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
|
* @spi: SPI slave
|
||||||
* @name: Name of SPI flash
|
* @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
|
* @size: Total flash size
|
||||||
* @page_size: Write (page) size
|
* @page_size: Write (page) size
|
||||||
* @sector_size: Sector size
|
* @sector_size: Sector size
|
||||||
@ -96,6 +98,7 @@ struct spi_flash {
|
|||||||
struct spi_slave *spi;
|
struct spi_slave *spi;
|
||||||
const char *name;
|
const char *name;
|
||||||
u8 dual_flash;
|
u8 dual_flash;
|
||||||
|
u8 shift;
|
||||||
|
|
||||||
u32 size;
|
u32 size;
|
||||||
u32 page_size;
|
u32 page_size;
|
||||||
|
Loading…
Reference in New Issue
Block a user