mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
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
5 changed files with 45 additions and 9 deletions
|
@ -54,6 +54,33 @@ SF_DUAL_STACKED_FLASH:
|
|||
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_dual_flash(struct spi_flash *flash, u32 *addr)
|
|||
flash->spi->flags &= ~SPI_XFER_U_PAGE;
|
||||
}
|
||||
break;
|
||||
case SF_DUAL_PARALLEL_FLASH:
|
||||
*addr >>= flash->shift;
|
||||
break;
|
||||
default:
|
||||
debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash);
|
||||
break;
|
||||
|
@ -388,7 +391,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->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 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->dual_flash & SF_DUAL_STACKED_FLASH)
|
||||
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 {
|
||||
|
|
|
@ -40,6 +40,7 @@ enum spi_read_cmds {
|
|||
enum spi_dual_flash {
|
||||
SF_SINGLE_FLASH = 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
|
||||
* @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
|
||||
* @page_size: Write (page) size
|
||||
* @sector_size: Sector size
|
||||
|
@ -96,6 +98,7 @@ struct spi_flash {
|
|||
struct spi_slave *spi;
|
||||
const char *name;
|
||||
u8 dual_flash;
|
||||
u8 shift;
|
||||
|
||||
u32 size;
|
||||
u32 page_size;
|
||||
|
|
Loading…
Reference in a new issue