openwrtv4/package/boot/uboot-layerscape/patches/0086-driver-spi-add-spansion-s25fs-s-family-protect-unpro.patch
Yutang Jiang 15a14cf166 layerscape: add 64b/32b target for ls1012ardb device
The QorIQ LS1012A processor, optimized for battery-backed or
USB-powered, integrates a single ARM Cortex-A53 core with a hardware
packet forwarding engine and high-speed interfaces to deliver
line-rate networking performance.
QorIQ LS1012A Reference Design System (LS1012ARDB) is a high-performance
development platform, with a complete debugging environment.
The LS1012ARDB board supports the QorIQ LS1012A processor and is
optimized to support the high-bandwidth DDR3L memory and
a full complement of high-speed SerDes ports.

LEDE/OPENWRT will auto strip executable program file while make. So we
need select CONFIG_NO_STRIP=y while make menuconfig to avoid the ppfe network
fiemware be destroyed, then run make to build ls1012ardb firmware.

The fsl-quadspi flash with jffs2 fs is unstable and arise some failed message.
This issue have noticed the IP owner for investigate, hope he can solve it
earlier. So the ls1012ardb now also provide a xx-firmware.ext4.bin as default
firmware, and the uboot bootcmd will run wrtboot_ext4rfs for "rootfstype=ext4"
bootargs.

Signed-off-by: Yutang Jiang <yutang.jiang@nxp.com>
2016-10-31 17:00:10 +01:00

233 lines
6.3 KiB
Diff

From 986172ece10eee928ce66597d76f3f40ac3d25f7 Mon Sep 17 00:00:00 2001
From: Yunhui Cui <yunhui.cui@nxp.com>
Date: Mon, 8 Aug 2016 14:24:13 +0800
Subject: [PATCH 86/93] driver: spi: add spansion s25fs-s family
protect/unprotect
In order to support spansion s25fs512s flash protect/unprotect:
[1] Fill callbak flash->lock/unlock/is_locked by spansion_lock/
unlock/is_locked.
[2] Achieve protect/unprotected by operating sr1nv, cr1nv.
Signed-off-by: Yunhui Cui <yunhui.cui@nxp.com>
---
drivers/mtd/spi/spi_flash.c | 194 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 194 insertions(+)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index e04bd55..87a92e9 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -877,6 +877,193 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len)
}
#endif
+#if defined(CONFIG_SPI_FLASH_SPANSION)
+/*
+ * Return 1 if the entire region is locked, 0 otherwise
+ */
+static int spansion_is_locked_sr(struct spi_flash *flash, u32 ofs, u32 len,
+ u8 sr)
+{
+ loff_t lock_offs;
+ u32 lock_len;
+
+ stm_get_locked_range(flash, sr, &lock_offs, &lock_len);
+
+ return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs);
+}
+
+/*
+ * Check if a region of the flash is (completely) locked. See spansion_lock() for
+ * more info.
+ *
+ * Returns 1 if entire region is locked, 0 if any portion is unlocked, and
+ * negative on errors.
+ */
+int spansion_is_locked(struct spi_flash *flash, u32 ofs, size_t len)
+{
+ u8 cmd[4];
+ u32 sr1nv_offset = 0x0;
+ u8 sr1nv;
+ int ret;
+
+ cmd[0] = CMD_SPANSION_RDAR;
+ cmd[1] = sr1nv_offset >> 16;
+ cmd[2] = sr1nv_offset >> 8;
+ cmd[3] = sr1nv_offset >> 0;
+
+ ret = spi_flash_cmd_read(flash->spi, cmd, 4, &sr1nv, 1);
+ if (ret)
+ return -EIO;
+
+ return spansion_is_locked_sr(flash, ofs, len, sr1nv);
+}
+
+/*
+ * Lock a region of the flash. Compatible with Spansion s25fs-s family flash.
+ * Supports only the block protection bits BP{0,1,2} in the Status Register-1
+ * Non-Volatile(SR1NV).
+ *
+ * Sample table portion for 64MB flash (S25FS512S):
+ * Configuration Register-1 Non-Volatile(CR1NV[5])== 0
+ *
+ * | BP2 | BP1 | BP0 | Prot Length | Protected Portion
+ * ------------------------------------------------------------
+ * | 0 | 0 | 0 | NONE | NONE
+ * | 0 | 0 | 1 | 1 MB | Upper 1/64
+ * | 0 | 1 | 0 | 2 MB | Upper 1/32
+ * | 0 | 1 | 1 | 4 MB | Upper 1/16
+ * | 1 | 0 | 0 | 8 MB | Upper 1/8
+ * | 1 | 0 | 1 | 16 MB | Upper 1/4
+ * | 1 | 1 | 0 | 32 MB | Upper 1/2
+ * | 1 | 1 | 1 | 64 MB | ALL
+ *
+ * When CR1NV[5] == 1, the Lower memory array are protected.
+ *
+ * Returns negative on errors, 0 on success.
+ */
+int spansion_lock(struct spi_flash *flash, u32 ofs, size_t len)
+{
+ u8 status_old, status_new;
+ u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
+ u8 shift = ffs(mask) - 1, pow, val;
+ int ret;
+ u8 cmd[4];
+ u32 sr1nv_offset = 0x0;
+ u8 sr1nv;
+
+ cmd[0] = CMD_SPANSION_RDAR;
+ cmd[1] = sr1nv_offset >> 16;
+ cmd[2] = sr1nv_offset >> 8;
+ cmd[3] = sr1nv_offset >> 0;
+
+ ret = spi_flash_cmd_read(flash->spi, cmd, 4, &sr1nv, 1);
+ if (ret)
+ return -EIO;
+ status_old = sr1nv;
+
+ /* SPI NOR always locks to the end */
+ if (ofs + len != flash->size) {
+ /* Does combined region extend to end? */
+ if (!stm_is_locked_sr(flash, ofs + len, flash->size - ofs - len,
+ status_old))
+ return -EINVAL;
+ len = flash->size - ofs;
+ }
+
+ /*
+ * Need smallest pow such that:
+ *
+ * 1 / (2^pow) <= (len / size)
+ *
+ * so (assuming power-of-2 size) we do:
+ *
+ * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len))
+ */
+ pow = ilog2(flash->size) - ilog2(len);
+ val = mask - (pow << shift);
+ if (val & ~mask)
+ return -EINVAL;
+
+ /* Don't "lock" with no region! */
+ if (!(val & mask))
+ return -EINVAL;
+
+ status_new = (status_old & ~mask) | val;
+
+ /* Only modify protection if it will not unlock other areas */
+ if ((status_new & mask) <= (status_old & mask))
+ return -EINVAL;
+
+ cmd[0] = CMD_SPANSION_WRAR;
+ ret = spi_flash_cmd_write(flash->spi, cmd, 4, &status_new, 1);
+ if (ret)
+ return -EIO;
+
+ return 0;
+}
+
+/*
+ * Unlock a region of the flash. See spansion_lock() for more info
+ *
+ * Returns negative on errors, 0 on success.
+ */
+int spansion_unlock(struct spi_flash *flash, u32 ofs, size_t len)
+{
+ uint8_t status_old, status_new;
+ u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
+ u8 shift = ffs(mask) - 1, pow, val;
+ int ret;
+
+ u8 cmd[4];
+ u32 sr1nv_offset = 0x0;
+ u8 sr1nv;
+
+ cmd[0] = CMD_SPANSION_RDAR;
+ cmd[1] = sr1nv_offset >> 16;
+ cmd[2] = sr1nv_offset >> 8;
+ cmd[3] = sr1nv_offset >> 0;
+
+ ret = spi_flash_cmd_read(flash->spi, cmd, 4, &sr1nv, 1);
+ if (ret)
+ return -EIO;
+ status_old = sr1nv;
+
+ /* Cannot unlock; would unlock larger region than requested */
+ if (spansion_is_locked_sr(flash, ofs - flash->erase_size, flash->erase_size,
+ status_old))
+ return -EINVAL;
+ /*
+ * Need largest pow such that:
+ *
+ * 1 / (2^pow) >= (len / size)
+ *
+ * so (assuming power-of-2 size) we do:
+ *
+ * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len))
+ */
+ pow = ilog2(flash->size) - order_base_2(flash->size - (ofs + len));
+ if (ofs + len == flash->size) {
+ val = 0; /* fully unlocked */
+ } else {
+ val = mask - (pow << shift);
+ /* Some power-of-two sizes are not supported */
+ if (val & ~mask)
+ return -EINVAL;
+ }
+ status_new = (status_old & ~mask) | val;
+
+ /* Only modify protection if it will not lock other areas */
+ if ((status_new & mask) >= (status_old & mask))
+ return -EINVAL;
+
+ cmd[0] = CMD_SPANSION_WRAR;
+ ret = spi_flash_cmd_write(flash->spi, cmd, 4, &status_new, 1);
+ if (ret)
+ return -EIO;
+
+ return 0;
+}
+#endif
#ifdef CONFIG_SPI_FLASH_MACRONIX
static int spi_flash_set_qeb_mxic(struct spi_flash *flash)
@@ -1132,6 +1319,13 @@ int spi_flash_scan(struct spi_flash *flash)
flash->flash_is_locked = stm_is_locked;
#endif
break;
+#if defined(CONFIG_SPI_FLASH_SPANSION)
+ case SPI_FLASH_CFI_MFR_SPANSION:
+ flash->flash_lock = spansion_lock;
+ flash->flash_unlock = spansion_unlock;
+ flash->flash_is_locked = spansion_is_locked;
+#endif
+ break;
default:
debug("SF: Lock ops not supported for %02x flash\n", idcode[0]);
}
--
1.7.9.5