summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoris van Vossen <joris.van.vossen@sintecs.nl>2018-05-15 13:28:31 (GMT)
committerJoris van Vossen <joris.van.vossen@sintecs.nl>2018-05-17 12:44:00 (GMT)
commitbc2e256d6c148cef7b58b89bafc7c5d930a76a4d (patch)
tree37e4d1345ab311b4a8f315287c34014281f8388a
parent6e6b99c5fb8575286490c42245062220f173b17f (diff)
downloadu-boot-bc2e256d6c148cef7b58b89bafc7c5d930a76a4d.tar.xz
Grapeboard rescue flash compatibility update
-rw-r--r--board/scalys/grapeboard/PBL_0x33_0x08_800_250_1000_RESCUE_FLASH.binbin0 -> 160 bytes
-rw-r--r--board/scalys/grapeboard/grapeboard.c25
-rw-r--r--configs/grapeboard_sata_qspi_rescue_flash_defconfig59
-rw-r--r--drivers/mtd/spi/sf_internal.h18
-rw-r--r--drivers/mtd/spi/spi_flash.c190
-rw-r--r--drivers/mtd/spi/spi_flash_ids.c1
-rw-r--r--drivers/spi/fsl_qspi.c109
-rw-r--r--drivers/spi/fsl_qspi.h3
-rw-r--r--include/configs/grapeboard.h13
9 files changed, 371 insertions, 47 deletions
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
--- /dev/null
+++ b/board/scalys/grapeboard/PBL_0x33_0x08_800_250_1000_RESCUE_FLASH.bin
Binary files 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 <spi.h>
#include <dm/device-internal.h>
-#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 <spi.h>
#include <spi_flash.h>
#include <linux/log2.h>
+#include <linux/sizes.h>
#include <dma.h>
+#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, &regs->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, &regs->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, &regs->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, &regs->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, &regs->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, &regs->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, &regs->lut[lut_base + 1], 0);
+ qspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+ qspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
/* Lock the LUT */
qspi_write32(priv->flags, &regs->lutkey, LUT_KEY_VALUE);
qspi_write32(priv->flags, &regs->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, &regs->sfa1ad,
- FSL_QSPI_FLASH_SIZE | amba_bases[bus]);
+ fsl_qspi_current_flash_size | amba_bases[bus]);
qspi_write32(qspi->priv.flags, &regs->sfa2ad,
- FSL_QSPI_FLASH_SIZE | amba_bases[bus]);
+ fsl_qspi_current_flash_size | amba_bases[bus]);
qspi_write32(qspi->priv.flags, &regs->sfb1ad,
total_size | amba_bases[bus]);
qspi_write32(qspi->priv.flags, &regs->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 <config_distro_bootcmd.h>
#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 \