From bc2e256d6c148cef7b58b89bafc7c5d930a76a4d Mon Sep 17 00:00:00 2001 From: Joris van Vossen Date: Tue, 15 May 2018 15:28:31 +0200 Subject: Grapeboard rescue flash compatibility update diff --git a/board/scalys/grapeboard/PBL_0x33_0x08_800_250_1000_RESCUE_FLASH.bin b/board/scalys/grapeboard/PBL_0x33_0x08_800_250_1000_RESCUE_FLASH.bin new file mode 100644 index 0000000..4348366 Binary files /dev/null and b/board/scalys/grapeboard/PBL_0x33_0x08_800_250_1000_RESCUE_FLASH.bin differ diff --git a/board/scalys/grapeboard/grapeboard.c b/board/scalys/grapeboard/grapeboard.c index 1e3d3eb..50321e8 100644 --- a/board/scalys/grapeboard/grapeboard.c +++ b/board/scalys/grapeboard/grapeboard.c @@ -34,7 +34,8 @@ #include #include -#define RESCUE_FLASH_NAME "s25fs064s" +/* Possible SPI (NOR) flashes used as rescue memory device */ +const char* supported_rescue_flashes[] = {"s25fs064s","sst26wf080b"}; static int recovery_mode_enabled = 0; @@ -153,17 +154,21 @@ int board_init(void) #endif /* Detect and handle grapeboard rescue mode */ - if(strcmp(get_qspi_flash_name(), RESCUE_FLASH_NAME) == 0) { - /* Revert chip select muxing to standard QSPI flash */ - setbits_be32(&pgpio->gpdir, QSPI_MUX_N_MASK); - clrbits_be32(&pgpio->gpdat, QSPI_MUX_N_MASK); - printf("Please release the rescue mode button (S2) to enter the recovery mode\n"); - recovery_mode_enabled = 1; - while(strcmp(get_qspi_flash_name(), RESCUE_FLASH_NAME) == 0) { - udelay(500000); - puts("\033[1A"); /* Overwrite previous line */ + char *current_flash_name = strdup(get_qspi_flash_name()); + for (int index = 0; index < sizeof(supported_rescue_flashes) / sizeof(supported_rescue_flashes[0]); index++) { + if(strcmp(current_flash_name, supported_rescue_flashes[index]) == 0) { + /* Revert chip select muxing to standard QSPI flash */ + setbits_be32(&pgpio->gpdir, QSPI_MUX_N_MASK); + clrbits_be32(&pgpio->gpdat, QSPI_MUX_N_MASK); + printf("Please release the rescue mode button (S2) to enter the recovery mode\n"); + recovery_mode_enabled = 1; + while(strcmp(get_qspi_flash_name(), supported_rescue_flashes[index]) == 0) { + udelay(500000); + puts("\033[1A"); /* Overwrite previous line */ + } } } + free(current_flash_name); #ifdef CONFIG_FSL_CAAM sec_init(); diff --git a/configs/grapeboard_sata_qspi_rescue_flash_defconfig b/configs/grapeboard_sata_qspi_rescue_flash_defconfig new file mode 100644 index 0000000..8e72941 --- /dev/null +++ b/configs/grapeboard_sata_qspi_rescue_flash_defconfig @@ -0,0 +1,59 @@ +CONFIG_ARM=y +CONFIG_TARGET_GRAPEBOARD=y +CONFIG_FSL_LS_PPA=y +CONFIG_QSPI_AHB_INIT=y +CONFIG_DEFAULT_DEVICE_TREE="grapeboard" +CONFIG_SYS_LS_PPA_FW_ADDR=0x40240000 +CONFIG_CONCAT_PBL_UBOOT_IMAGE=y +CONFIG_PBL_BINARY_SRC="board/scalys/grapeboard/PBL_0x33_0x08_800_250_1000_RESCUE_FLASH.bin" + +# CONFIG_SYS_MALLOC_F is not set +CONFIG_FIT_VERBOSE=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_OF_STDOUT_VIA_ALIAS=y +CONFIG_SYS_EXTRA_OPTIONS="QSPI_BOOT" +CONFIG_QSPI_BOOT=y +CONFIG_BOOTDELAY=2 +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="console=ttyS0,115200 earlycon=uart8250,mmio,0x21c0500 quiet lpj=250000 noinitrd" +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_HUSH_PARSER=y +CONFIG_CMD_GREPENV=y +CONFIG_CMD_GPT=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_I2C=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_FAT=y +CONFIG_OF_CONTROL=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_DM=y +# CONFIG_BLK is not set +CONFIG_DM_MMC=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_NETDEVICES=y +CONFIG_E1000=y +CONFIG_FSL_PFE=y +CONFIG_PHYLIB=y +CONFIG_PHY_TI=y +CONFIG_PCI=y +CONFIG_DM_PCI=y +CONFIG_DM_PCI_COMPAT=y +CONFIG_PCIE_LAYERSCAPE=y +CONFIG_SYS_NS16550=y +CONFIG_DM_SPI=y +CONFIG_FSL_DSPI=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DWC3=y +CONFIG_USB_STORAGE=y +CONFIG_DISTRO_DEFAULTS=y \ No newline at end of file diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 955426e..b60be2f 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -89,8 +89,24 @@ enum spi_nor_option_flags { /* SST specific */ #ifdef CONFIG_SPI_FLASH_SST +#define CMD_SST_BP 0x02 /* Byte Program */ +#define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ + +#define SST26_CMD_READ_BPR 0x72 +#define SST26_CMD_WRITE_BPR 0x42 +#define SST26_BPR_8K_NUM 4 +#define SST26_MAX_BPR_REG_LEN (18 + 1) +#define SST26_BOUND_REG_SIZE ((32 + SST26_BPR_8K_NUM * 8) * SZ_1K) + +enum lock_ctl { + SST26_CTL_LOCK, + SST26_CTL_UNLOCK, + SST26_CTL_CHECK +}; + # define CMD_SST_BP 0x02 /* Byte Program */ # define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ +# define CMD_SST_ULBPR 0x98 /* Global Block Protection Unlock */ int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf); @@ -134,6 +150,8 @@ struct spi_flash_info { #define RD_QUADIO BIT(6) /* use Quad IO Read */ #define RD_DUALIO BIT(7) /* use Dual IO Read */ #define ADDR_4B BIT(8) +#define SECT_4K_ONLY BIT(9) /* use only CMD_ERASE_4K */ +#define SST_ULBPR BIT(10) /* use SST unlock block protection */ #define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) }; diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index ba9aee6..3a11955 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include <../drivers/spi/fsl_qspi.h> #include "sf_internal.h" @@ -548,7 +550,174 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, return ret; } + #ifdef CONFIG_SPI_FLASH_SST +static bool sst26_process_bpr(u32 bpr_size, u8 *cmd, u32 bit, enum lock_ctl ctl) +{ + switch (ctl) { + case SST26_CTL_LOCK: + cmd[bpr_size - (bit / 8) - 1] |= BIT(bit % 8); + break; + case SST26_CTL_UNLOCK: + cmd[bpr_size - (bit / 8) - 1] &= ~BIT(bit % 8); + break; + case SST26_CTL_CHECK: + return !!(cmd[bpr_size - (bit / 8) - 1] & BIT(bit % 8)); + } + + return false; +} + +/* + * sst26wf016/sst26wf032/sst26wf064 have next block protection: + * 4x - 8 KByte blocks - read & write protection bits - upper addresses + * 1x - 32 KByte blocks - write protection bits + * rest - 64 KByte blocks - write protection bits + * 1x - 32 KByte blocks - write protection bits + * 4x - 8 KByte blocks - read & write protection bits - lower addresses + * + * We'll support only per 64k lock/unlock so lower and upper 64 KByte region + * will be treated as single block. + */ + +/* + * Lock, unlock or check lock status of the flash region of the flash (depending + * on the lock_ctl value) + */ +static int sst26_lock_ctl(struct spi_flash *flash, u32 ofs, size_t len, enum lock_ctl ctl) +{ + u32 i, bpr_ptr, rptr_64k, lptr_64k, bpr_size; + bool lower_64k = false, upper_64k = false; + u8 cmd, bpr_buff[SST26_MAX_BPR_REG_LEN] = {}; + int ret; + + /* Check length and offset for 64k alignment */ + if ((ofs & (SZ_64K - 1)) || (len & (SZ_64K - 1))) { + printf("Offset or lenght not allighned\n"); + return -EINVAL; + } + + if (ofs + len > flash->size) { + printf("Size exceeding flash size\n"); + return -EINVAL; + } + + /* SST26 family has only 4Mbit, 8Mbit, 16 Mbit, 32 Mbit and 64 Mbit IC */ + if (flash->size != SZ_512K && + flash->size != SZ_1M && + flash->size != SZ_2M && + flash->size != SZ_4M && + flash->size != SZ_8M) + return -EINVAL; + + bpr_size = 2 + (flash->size / SZ_64K / 8); + + cmd = SST26_CMD_READ_BPR; + ret = spi_flash_read_common(flash, &cmd, 1, bpr_buff, bpr_size); + if (ret < 0) { + printf("SF: fail to read block-protection register\n"); + return ret; + } + + rptr_64k = min_t(u32, ofs + len , flash->size - SST26_BOUND_REG_SIZE); + lptr_64k = max_t(u32, ofs, SST26_BOUND_REG_SIZE); + + upper_64k = ((ofs + len) > (flash->size - SST26_BOUND_REG_SIZE)); + lower_64k = (ofs < SST26_BOUND_REG_SIZE); + + /* Lower bits in block-protection register are about 64k region */ + bpr_ptr = lptr_64k / SZ_64K - 1; + + /* Process 64K blocks region */ + while (lptr_64k < rptr_64k) { + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl)) + return EACCES; + + bpr_ptr++; + lptr_64k += SZ_64K; + } + + /* 32K and 8K region bits in BPR are after 64k region bits */ + bpr_ptr = (flash->size - 2 * SST26_BOUND_REG_SIZE) / SZ_64K; + + /* Process lower 32K block region */ + if (lower_64k) + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl)) + return EACCES; + + bpr_ptr++; + + /* Process upper 32K block region */ + if (upper_64k) + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl)) + return EACCES; + + bpr_ptr++; + + /* Process lower 8K block regions */ + for (i = 0; i < SST26_BPR_8K_NUM; i++) { + if (lower_64k) + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl)) + return EACCES; + + /* In 8K area BPR has both read and write protection bits */ + bpr_ptr += 2; + } + + /* Process upper 8K block regions */ + for (i = 0; i < SST26_BPR_8K_NUM; i++) { + if (upper_64k) + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl)) + return EACCES; + + /* In 8K area BPR has both read and write protection bits */ + bpr_ptr += 2; + } + + /* If we check region status we don't need to write BPR back */ + if (ctl == SST26_CTL_CHECK) + return 0; + + cmd = SST26_CMD_WRITE_BPR; + ret = spi_flash_write_common(flash, &cmd, 1, bpr_buff, bpr_size); + if (ret < 0) { + printf("SF: fail to write block-protection register\n"); + return ret; + } + + return 0; +} +#endif + +static int sst26_unlock(struct spi_flash *flash, u32 ofs, size_t len) +{ + return sst26_lock_ctl(flash, ofs, len, SST26_CTL_UNLOCK); +} + + +static int sst26_lock(struct spi_flash *flash, u32 ofs, size_t len) +{ + return sst26_lock_ctl(flash, ofs, len, SST26_CTL_LOCK); +} + +/* + * Returns EACCES (positive value) if region is locked, 0 if region is unlocked, + * and negative on errors. + */ +static int sst26_is_locked(struct spi_flash *flash, u32 ofs, size_t len) +{ + /* + * is_locked function is used for check before reading or erasing flash + * region, so offset and length might be not 64k allighned, so adjust + * them to be 64k allighned as sst26_lock_ctl works only with 64k + * allighned regions. + */ + ofs -= ofs & (SZ_64K - 1); + len = len & (SZ_64K - 1) ? (len & ~(SZ_64K - 1)) + SZ_64K : len; + + return sst26_lock_ctl(flash, ofs, len, SST26_CTL_CHECK); +} + static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) { struct spi_slave *spi = flash->spi; @@ -673,7 +842,7 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, spi_release_bus(spi); return ret; } -#endif + #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, @@ -1039,6 +1208,14 @@ int spi_flash_scan(struct spi_flash *flash) flash->flash_unlock = stm_unlock; flash->flash_is_locked = stm_is_locked; } +/* sst26wf series block protection implementation differs from other series */ +#if defined(CONFIG_SPI_FLASH_SST) + if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST && info->id[1] == 0x26) { + flash->flash_lock = sst26_lock; + flash->flash_unlock = sst26_unlock; + flash->flash_is_locked = sst26_is_locked; +#endif + } #endif /* Compute the flash size */ @@ -1058,6 +1235,12 @@ int spi_flash_scan(struct spi_flash *flash) flash->page_size <<= flash->shift; flash->sector_size = info->sector_size << flash->shift; flash->size = flash->sector_size * info->n_sectors << flash->shift; + + /* update fsl qspi driver LUT for new flash size at runtime */ + if(strcmp(flash->dev->parent->name, "quadspi@1550000") == 0) { + fsl_qspi_update_lut(flash->dev->parent->priv, flash->size); + } + #ifdef CONFIG_SF_DUAL_FLASH if (flash->dual_flash & SF_DUAL_STACKED_FLASH) flash->size <<= 1; @@ -1070,7 +1253,10 @@ int spi_flash_scan(struct spi_flash *flash) flash->erase_size = 4096 << flash->shift; } else #endif - { + if (info->flags & SECT_4K_ONLY) { + flash->erase_cmd = CMD_ERASE_4K; + flash->erase_size = 4096 << flash->shift; + } else { flash->erase_cmd = CMD_ERASE_64K; flash->erase_size = flash->sector_size; } diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c index 374f6b2..c366d99 100644 --- a/drivers/mtd/spi/spi_flash_ids.c +++ b/drivers/mtd/spi/spi_flash_ids.c @@ -150,6 +150,7 @@ const struct spi_flash_info spi_flash_ids[] = { {"sst25wf040", INFO(0xbf2504, 0x0, 64 * 1024, 8, SECT_4K | SST_WR) }, {"sst25wf040b", INFO(0x621613, 0x0, 64 * 1024, 8, SECT_4K) }, {"sst25wf080", INFO(0xbf2505, 0x0, 64 * 1024, 16, SECT_4K | SST_WR) }, + {"sst26wf080b", INFO(0xbf2658, 0x0, 4 * 1024, 256, SECT_4K | SST_ULBPR | RD_FULL) }, #endif #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ {"w25p80", INFO(0xef2014, 0x0, 64 * 1024, 16, 0) }, 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, diff --git a/drivers/spi/fsl_qspi.h b/drivers/spi/fsl_qspi.h index e468eb2..8a4606d 100644 --- a/drivers/spi/fsl_qspi.h +++ b/drivers/spi/fsl_qspi.h @@ -143,4 +143,7 @@ struct fsl_qspi_regs { #define ADDR24BIT 0x18 #define ADDR32BIT 0x20 +struct fsl_qspi_priv; +int fsl_qspi_update_lut(struct fsl_qspi_priv *, u32); + #endif /* _FSL_QSPI_H_ */ diff --git a/include/configs/grapeboard.h b/include/configs/grapeboard.h index ac3a487..426a468 100644 --- a/include/configs/grapeboard.h +++ b/include/configs/grapeboard.h @@ -82,7 +82,6 @@ /* SPI */ #define CONFIG_FSL_DSPI1 #define CONFIG_DEFAULT_SPI_BUS 0 -#define CONFIG_CMD_SPI #define MMAP_DSPI DSPI1_BASE_ADDR #define CONFIG_SYS_DSPI_CTAR0 1 #define CONFIG_SYS_DSPI_CTAR1 1 @@ -172,9 +171,9 @@ #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 0) \ func(USB, usb, 0) \ + func(SCSI, scsi, 0) /*/ func(USB, usb, 1) \ - func(UBIFS, ubifs, 0) \ - func(SCSI, scsi, 0) + func(UBIFS, ubifs, 0)*/ #include #endif @@ -193,7 +192,7 @@ #define COMMON_UBOOT_CONFIG \ "update_tftp_uboot_qspi_nor=" \ "dhcp;" \ - "tftp $load_addr $TFTP_PATH/u-boot-with-pbl.bin;" \ + "tftp $load_addr $update_files_path/u-boot-with-pbl.bin;" \ "if test $? = \"0\"; then " \ "sf probe 0:0;" \ "sf erase u-boot 200000;" \ @@ -201,7 +200,7 @@ "fi\0" \ "update_tftp_ppa_qspi_nor=" \ "dhcp;" \ - "tftp $load_addr $TFTP_PATH/ppa.itb;" \ + "tftp $load_addr $update_files_path/ppa.itb;" \ "if test $? = \"0\"; then " \ "sf probe 0:0;" \ "sf erase ppa 40000;" \ @@ -209,7 +208,7 @@ "fi\0" \ "update_tftp_pfe_qspi_nor=" \ "dhcp;" \ - "tftp $load_addr $TFTP_PATH/pfe_fw_sbl.itb;" \ + "tftp $load_addr $update_files_path/pfe_fw_sbl.itb;" \ "if test $? = \"0\"; then " \ "sf probe 0:0;" \ "sf erase pfe 40000;" \ @@ -284,7 +283,7 @@ "ethprime=pfe_eth0\0" \ "ethaddr=02:00:00:ba:be:01\0" \ "eth1addr=02:00:00:ba:be:02\0" \ - "TFTP_PATH=.\0" \ + "update_files_path=.\0" \ "autoload=no\0" \ COMMON_UBOOT_CONFIG \ BOOTENV \ -- cgit v0.10.2