diff options
Diffstat (limited to 'drivers/spi/fsl_qspi.c')
-rw-r--r-- | drivers/spi/fsl_qspi.c | 109 |
1 files changed, 81 insertions, 28 deletions
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 22bb61f..ec915b0 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -19,6 +19,10 @@ DECLARE_GLOBAL_DATA_PTR; +/* Size of flash device should be determined at runtime to support multiple types */ +static int fsl_qspi_current_flash_size = FSL_QSPI_FLASH_SIZE; +static int current_offset_bits_mask = GENMASK(27, 0); + #define RX_BUFFER_SIZE 0x80 #ifdef CONFIG_MX6SX #define TX_BUFFER_SIZE 0x200 @@ -26,29 +30,30 @@ DECLARE_GLOBAL_DATA_PTR; #define TX_BUFFER_SIZE 0x40 #endif -#define OFFSET_BITS_MASK ((FSL_QSPI_FLASH_SIZE > SZ_16M) ? \ - GENMASK(27, 0) : GENMASK(23, 0)) - #define FLASH_STATUS_WEL 0x02 /* SEQID */ -#define SEQID_WREN 1 -#define SEQID_FAST_READ 2 -#define SEQID_RDSR 3 -#define SEQID_SE 4 -#define SEQID_CHIP_ERASE 5 -#define SEQID_PP 6 -#define SEQID_RDID 7 -#define SEQID_BE_4K 8 +enum FSL_QSPI_SEDIDS { + SEQID_WREN = 1, + SEQID_FAST_READ, + SEQID_RDSR, + SEQID_SE, + SEQID_CHIP_ERASE, + SEQID_PP, + SEQID_RDID, + SEQID_BE_4K, #ifdef CONFIG_SPI_FLASH_BAR -#define SEQID_BRRD 9 -#define SEQID_BRWR 10 -#define SEQID_RDEAR 11 -#define SEQID_WREAR 12 + SEQID_BRRD, + SEQID_BRWR, + SEQID_RDEAR, + SEQID_WREAR, #endif -#define SEQID_WRAR 13 -#define SEQID_RDAR 14 + SEQID_WRAR, + SEQID_RDAR, + SEQID_WBPR, + SEQID_RBPR, +}; /* QSPI CMD */ #define QSPI_CMD_PP 0x02 /* Page program (up to 256 bytes) */ @@ -77,6 +82,13 @@ DECLARE_GLOBAL_DATA_PTR; #define QSPI_CMD_PP_4B 0x12 /* Page program (up to 256 bytes) */ #define QSPI_CMD_SE_4B 0xdc /* Sector erase (usually 64KiB) */ +/* protection regisers used on Microchip SST26 flashes */ +#define QSPI_CMD_WBPR 0x42 /* Write Block-Protection Register (WBPR) */ +#define QSPI_CMD_RBPR 0x72 /* Read Block-Protection Register (RBPR) */ +#define QSPI_CMD_ULBPR 0x98 /* Global Block Protetion Unlock (ULBPR) */ + + + /* fsl_qspi_platdata flags */ #define QSPI_FLAG_REGMAP_ENDIAN_BIG BIT(0) @@ -193,7 +205,7 @@ static void qspi_set_lut(struct fsl_qspi_priv *priv) INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #else - if (FSL_QSPI_FLASH_SIZE <= SZ_16M) + if (fsl_qspi_current_flash_size <= SZ_16M) qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_FAST_READ) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | @@ -228,7 +240,7 @@ static void qspi_set_lut(struct fsl_qspi_priv *priv) PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #else - if (FSL_QSPI_FLASH_SIZE <= SZ_16M) + if (fsl_qspi_current_flash_size <= SZ_16M) qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_SE) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | @@ -259,7 +271,7 @@ static void qspi_set_lut(struct fsl_qspi_priv *priv) PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #else - if (FSL_QSPI_FLASH_SIZE <= SZ_16M) + if (fsl_qspi_current_flash_size <= SZ_16M) qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_PP) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | @@ -353,6 +365,21 @@ static void qspi_set_lut(struct fsl_qspi_priv *priv) qspi_write32(priv->flags, ®s->lut[lut_base + 1], OPRND0(1) | PAD0(LUT_PAD1) | INSTR0(LUT_WRITE)); + /* Write Block protection status (SST26 Flashes) */ + lut_base = SEQID_WBPR * 4; + qspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(QSPI_CMD_WBPR) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | + OPRND1(3) | PAD1(LUT_PAD1) | INSTR1(LUT_WRITE)); + + /* Read Block protection status (SST26 Flashes)*/ + lut_base = SEQID_RBPR * 4; + qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_RBPR) | + PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(8) | + PAD1(LUT_PAD1) | INSTR1(LUT_READ)); + qspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + qspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + qspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + /* Lock the LUT */ qspi_write32(priv->flags, ®s->lutkey, LUT_KEY_VALUE); qspi_write32(priv->flags, ®s->lckcr, QSPI_LCKCR_LOCK); @@ -563,6 +590,8 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len) if (priv->cur_seqid == QSPI_CMD_RDAR) seqid = SEQID_RDAR; + else if (priv->cur_seqid == QSPI_CMD_RBPR) + seqid = SEQID_RBPR; else seqid = SEQID_FAST_READ; @@ -652,6 +681,9 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len) seqid = SEQID_PP; if (priv->cur_seqid == QSPI_CMD_WRAR) seqid = SEQID_WRAR; + else if (priv->cur_seqid == QSPI_CMD_WBPR) { + seqid = SEQID_WBPR; + } #ifdef CONFIG_SPI_FLASH_BAR if (priv->cur_seqid == QSPI_CMD_BRWR) seqid = SEQID_BRWR; @@ -784,7 +816,7 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen, if (dout) { if (flags & SPI_XFER_BEGIN) { priv->cur_seqid = *(u8 *)dout; - if (FSL_QSPI_FLASH_SIZE > SZ_16M && bytes > 4) + if (fsl_qspi_current_flash_size > SZ_16M && bytes > 4) memcpy(&txbuf, dout + 1, 4); else memcpy(&txbuf, dout, 4); @@ -798,19 +830,23 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen, if (priv->cur_seqid == QSPI_CMD_FAST_READ || priv->cur_seqid == QSPI_CMD_RDAR) { - priv->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK; + priv->sf_addr = swab32(txbuf) & current_offset_bits_mask; } else if ((priv->cur_seqid == QSPI_CMD_SE) || (priv->cur_seqid == QSPI_CMD_BE_4K)) { - priv->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK; + priv->sf_addr = swab32(txbuf) & current_offset_bits_mask; qspi_op_erase(priv); } else if (priv->cur_seqid == QSPI_CMD_PP || priv->cur_seqid == QSPI_CMD_WRAR) { - wr_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK; + wr_sfaddr = swab32(txbuf) & current_offset_bits_mask; } else if ((priv->cur_seqid == QSPI_CMD_BRWR) || (priv->cur_seqid == QSPI_CMD_WREAR)) { #ifdef CONFIG_SPI_FLASH_BAR wr_sfaddr = 0; #endif + } else if (priv->cur_seqid == QSPI_CMD_ULBPR || + priv->cur_seqid == QSPI_CMD_WBPR + ) { + qspi_op_write(priv, &(((u8 *)dout)[1]), bytes); } } @@ -834,6 +870,9 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen, qspi_op_rdbank(priv, din, bytes); } #endif + else if (priv->cur_seqid == QSPI_CMD_RBPR) { + qspi_op_read(priv, din, bytes); + } } #ifdef CONFIG_SYS_FSL_QSPI_AHB @@ -920,7 +959,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, * If not, only one flash device is used even if passing * different cs using `sf probe` */ - qspi->priv.cur_amba_base = amba_bases[bus] + cs * FSL_QSPI_FLASH_SIZE; + qspi->priv.cur_amba_base = amba_bases[bus] + cs * fsl_qspi_current_flash_size; qspi->slave.max_write_size = TX_BUFFER_SIZE; @@ -933,7 +972,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, ~(QSPI_SMPR_FSDLY_MASK | QSPI_SMPR_DDRSMP_MASK | QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK), 0); - total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM; + total_size = fsl_qspi_current_flash_size * FSL_QSPI_FLASH_NUM; /* * Any read access to non-implemented addresses will provide * undefined results. @@ -945,9 +984,9 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, * that the complete memory map is assigned to only one flash device. */ qspi_write32(qspi->priv.flags, ®s->sfa1ad, - FSL_QSPI_FLASH_SIZE | amba_bases[bus]); + fsl_qspi_current_flash_size | amba_bases[bus]); qspi_write32(qspi->priv.flags, ®s->sfa2ad, - FSL_QSPI_FLASH_SIZE | amba_bases[bus]); + fsl_qspi_current_flash_size | amba_bases[bus]); qspi_write32(qspi->priv.flags, ®s->sfb1ad, total_size | amba_bases[bus]); qspi_write32(qspi->priv.flags, ®s->sfb2ad, @@ -1236,6 +1275,20 @@ static int fsl_qspi_set_mode(struct udevice *bus, uint mode) return 0; } +int fsl_qspi_update_lut(struct fsl_qspi_priv *priv, u32 flash_size) +{ + fsl_qspi_current_flash_size = flash_size; + current_offset_bits_mask = ((fsl_qspi_current_flash_size > SZ_16M) ? \ + GENMASK(27, 0) : GENMASK(23, 0)); + + /* Update LUTs in fsl_qspi driver */ + qspi_module_disable(priv, 1); + qspi_set_lut(priv); + qspi_module_disable(priv, 0); + + return 0; +} + static const struct dm_spi_ops fsl_qspi_ops = { .claim_bus = fsl_qspi_claim_bus, .release_bus = fsl_qspi_release_bus, |