* [PATCH 0/2] MTD: spi-nor: add support for sst26wf016, sst26wf032
@ 2018-09-04 15:33 ` Eugeniy Paltsev
0 siblings, 0 replies; 8+ messages in thread
From: Eugeniy Paltsev @ 2018-09-04 15:33 UTC (permalink / raw)
To: linux-mtd
Cc: linux-snps-arc, linux-kernel, Alexey Brodkin, Vineet Gupta,
Marek Vasut, David Woodhouse, Brian Norris, Boris Brezillon,
Richard Weinberger, Eugeniy Paltsev
Add support for the SST sst26wf016 and sst26wf032 flash IC:
sst26wf*** flash series block protection implementation differs from other
SST series, so we add implementation for sst26wf*** lock/unlock/is_locked
functions.
Add sst26wf016 and sst26wf032 flash IC info to spi_flash_ids list.
NOTE:
these patches is basically following mine u-boot commits port:
http://git.denx.de/?p=u-boot.git;a=commitdiff;h=3d4fed87a5fa3ffedf64ff2811cd95c5ac4503ac
http://git.denx.de/?p=u-boot.git;a=commitdiff;h=a19e97157c3721ef9c4b15c68c1773467a3b4a98
Eugeniy Paltsev (2):
mtd: spi-nor: Add support of sst26wf* flash ICs protection ops
mtd: spi-nor: add support for sst26wf016, sst26wf032
drivers/mtd/spi-nor/spi-nor.c | 179 ++++++++++++++++++++++++++++++++++++++++++
include/linux/mtd/spi-nor.h | 4 +
2 files changed, 183 insertions(+)
--
2.14.4
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 0/2] MTD: spi-nor: add support for sst26wf016, sst26wf032
@ 2018-09-04 15:33 ` Eugeniy Paltsev
0 siblings, 0 replies; 8+ messages in thread
From: Eugeniy Paltsev @ 2018-09-04 15:33 UTC (permalink / raw)
To: linux-snps-arc
Add support for the SST sst26wf016 and sst26wf032 flash IC:
sst26wf*** flash series block protection implementation differs from other
SST series, so we add implementation for sst26wf*** lock/unlock/is_locked
functions.
Add sst26wf016 and sst26wf032 flash IC info to spi_flash_ids list.
NOTE:
these patches is basically following mine u-boot commits port:
http://git.denx.de/?p=u-boot.git;a=commitdiff;h=3d4fed87a5fa3ffedf64ff2811cd95c5ac4503ac
http://git.denx.de/?p=u-boot.git;a=commitdiff;h=a19e97157c3721ef9c4b15c68c1773467a3b4a98
Eugeniy Paltsev (2):
mtd: spi-nor: Add support of sst26wf* flash ICs protection ops
mtd: spi-nor: add support for sst26wf016, sst26wf032
drivers/mtd/spi-nor/spi-nor.c | 179 ++++++++++++++++++++++++++++++++++++++++++
include/linux/mtd/spi-nor.h | 4 +
2 files changed, 183 insertions(+)
--
2.14.4
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops
2018-09-04 15:33 ` Eugeniy Paltsev
@ 2018-09-04 15:33 ` Eugeniy Paltsev
-1 siblings, 0 replies; 8+ messages in thread
From: Eugeniy Paltsev @ 2018-09-04 15:33 UTC (permalink / raw)
To: linux-mtd
Cc: linux-snps-arc, linux-kernel, Alexey Brodkin, Vineet Gupta,
Marek Vasut, David Woodhouse, Brian Norris, Boris Brezillon,
Richard Weinberger, Eugeniy Paltsev
sst26wf flash series block protection implementation differs
from other SST series, so add specific implementation
flash_lock/flash_unlock/flash_is_locked functions for sst26wf
flash ICs.
NOTE:
this patch is basically following mine u-boot commit port:
http://git.denx.de/?p=u-boot.git;a=commitdiff;h=3d4fed87a5fa3ffedf64ff2811cd95c5ac4503ac
Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
---
drivers/mtd/spi-nor/spi-nor.c | 177 ++++++++++++++++++++++++++++++++++++++++++
include/linux/mtd/spi-nor.h | 4 +
2 files changed, 181 insertions(+)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index d9c368c44194..6f74c75c9ddc 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -598,6 +598,177 @@ static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
return ((ret & mask) != (status_new & mask)) ? -EIO : 0;
}
+/*
+ * 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.
+ */
+#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
+};
+
+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;
+}
+
+/*
+ * 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_nor *nor, loff_t ofs, uint64_t len, enum lock_ctl ctl)
+{
+ struct mtd_info *mtd = &nor->mtd;
+ u32 i, bpr_ptr, rptr_64k, lptr_64k, bpr_size;
+ bool lower_64k = false, upper_64k = false;
+ u8 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))) {
+ dev_err(nor->dev, "length or offset is not 64KiB allighned\n");
+ return -EINVAL;
+ }
+
+ if (ofs + len > mtd->size) {
+ dev_err(nor->dev, "range is more than device size: %#llx + %#llx > %#llx\n",
+ ofs, len, mtd->size);
+ return -EINVAL;
+ }
+
+ /* SST26 family has only 16 Mbit, 32 Mbit and 64 Mbit IC */
+ if (mtd->size != SZ_2M &&
+ mtd->size != SZ_4M &&
+ mtd->size != SZ_8M)
+ return -EINVAL;
+
+ bpr_size = 2 + (mtd->size / SZ_64K / 8);
+
+ nor->read_reg(nor, SPINOR_OP_READ_BPR, bpr_buff, bpr_size);
+ if (ret < 0) {
+ dev_err(nor->dev, "fail to read block-protection register\n");
+ return ret;
+ }
+
+ rptr_64k = min_t(u32, ofs + len, mtd->size - SST26_BOUND_REG_SIZE);
+ lptr_64k = max_t(u32, ofs, SST26_BOUND_REG_SIZE);
+
+ upper_64k = ((ofs + len) > (mtd->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 = (mtd->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;
+
+ nor->write_reg(nor, SPINOR_OP_WRITE_BPR, bpr_buff, bpr_size);
+ if (ret < 0) {
+ dev_err(nor->dev, "fail to write block-protection register\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int sst26_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
+{
+ return sst26_lock_ctl(nor, ofs, len, SST26_CTL_UNLOCK);
+}
+
+static int sst26_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
+{
+ return sst26_lock_ctl(nor, 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_nor *nor, loff_t ofs, uint64_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(nor, ofs, len, SST26_CTL_CHECK);
+}
+
static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
uint64_t *len)
{
@@ -2872,6 +3043,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
nor->flash_is_locked = stm_is_locked;
}
+ if (JEDEC_MFR(info) == SNOR_MFR_SST && info->id[1] == 0x26) {
+ nor->flash_lock = sst26_lock;
+ nor->flash_unlock = sst26_unlock;
+ nor->flash_is_locked = sst26_is_locked;
+ }
+
if (nor->flash_lock && nor->flash_unlock && nor->flash_is_locked) {
mtd->_lock = spi_nor_lock;
mtd->_unlock = spi_nor_unlock;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index e60da0d34cc1..246014a73f83 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -93,6 +93,10 @@
#define SPINOR_OP_WRDI 0x04 /* Write disable */
#define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */
+/* Used for SST26* flashes only. */
+#define SPINOR_OP_READ_BPR 0x72 /* Read block protection register */
+#define SPINOR_OP_WRITE_BPR 0x42 /* Write block protection register */
+
/* Used for S3AN flashes only */
#define SPINOR_OP_XSE 0x50 /* Sector erase */
#define SPINOR_OP_XPP 0x82 /* Page program */
--
2.14.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops
@ 2018-09-04 15:33 ` Eugeniy Paltsev
0 siblings, 0 replies; 8+ messages in thread
From: Eugeniy Paltsev @ 2018-09-04 15:33 UTC (permalink / raw)
To: linux-snps-arc
sst26wf flash series block protection implementation differs
from other SST series, so add specific implementation
flash_lock/flash_unlock/flash_is_locked functions for sst26wf
flash ICs.
NOTE:
this patch is basically following mine u-boot commit port:
http://git.denx.de/?p=u-boot.git;a=commitdiff;h=3d4fed87a5fa3ffedf64ff2811cd95c5ac4503ac
Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev at synopsys.com>
---
drivers/mtd/spi-nor/spi-nor.c | 177 ++++++++++++++++++++++++++++++++++++++++++
include/linux/mtd/spi-nor.h | 4 +
2 files changed, 181 insertions(+)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index d9c368c44194..6f74c75c9ddc 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -598,6 +598,177 @@ static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
return ((ret & mask) != (status_new & mask)) ? -EIO : 0;
}
+/*
+ * 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.
+ */
+#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
+};
+
+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;
+}
+
+/*
+ * 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_nor *nor, loff_t ofs, uint64_t len, enum lock_ctl ctl)
+{
+ struct mtd_info *mtd = &nor->mtd;
+ u32 i, bpr_ptr, rptr_64k, lptr_64k, bpr_size;
+ bool lower_64k = false, upper_64k = false;
+ u8 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))) {
+ dev_err(nor->dev, "length or offset is not 64KiB allighned\n");
+ return -EINVAL;
+ }
+
+ if (ofs + len > mtd->size) {
+ dev_err(nor->dev, "range is more than device size: %#llx + %#llx > %#llx\n",
+ ofs, len, mtd->size);
+ return -EINVAL;
+ }
+
+ /* SST26 family has only 16 Mbit, 32 Mbit and 64 Mbit IC */
+ if (mtd->size != SZ_2M &&
+ mtd->size != SZ_4M &&
+ mtd->size != SZ_8M)
+ return -EINVAL;
+
+ bpr_size = 2 + (mtd->size / SZ_64K / 8);
+
+ nor->read_reg(nor, SPINOR_OP_READ_BPR, bpr_buff, bpr_size);
+ if (ret < 0) {
+ dev_err(nor->dev, "fail to read block-protection register\n");
+ return ret;
+ }
+
+ rptr_64k = min_t(u32, ofs + len, mtd->size - SST26_BOUND_REG_SIZE);
+ lptr_64k = max_t(u32, ofs, SST26_BOUND_REG_SIZE);
+
+ upper_64k = ((ofs + len) > (mtd->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 = (mtd->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;
+
+ nor->write_reg(nor, SPINOR_OP_WRITE_BPR, bpr_buff, bpr_size);
+ if (ret < 0) {
+ dev_err(nor->dev, "fail to write block-protection register\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int sst26_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
+{
+ return sst26_lock_ctl(nor, ofs, len, SST26_CTL_UNLOCK);
+}
+
+static int sst26_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
+{
+ return sst26_lock_ctl(nor, 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_nor *nor, loff_t ofs, uint64_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(nor, ofs, len, SST26_CTL_CHECK);
+}
+
static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
uint64_t *len)
{
@@ -2872,6 +3043,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
nor->flash_is_locked = stm_is_locked;
}
+ if (JEDEC_MFR(info) == SNOR_MFR_SST && info->id[1] == 0x26) {
+ nor->flash_lock = sst26_lock;
+ nor->flash_unlock = sst26_unlock;
+ nor->flash_is_locked = sst26_is_locked;
+ }
+
if (nor->flash_lock && nor->flash_unlock && nor->flash_is_locked) {
mtd->_lock = spi_nor_lock;
mtd->_unlock = spi_nor_unlock;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index e60da0d34cc1..246014a73f83 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -93,6 +93,10 @@
#define SPINOR_OP_WRDI 0x04 /* Write disable */
#define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */
+/* Used for SST26* flashes only. */
+#define SPINOR_OP_READ_BPR 0x72 /* Read block protection register */
+#define SPINOR_OP_WRITE_BPR 0x42 /* Write block protection register */
+
/* Used for S3AN flashes only */
#define SPINOR_OP_XSE 0x50 /* Sector erase */
#define SPINOR_OP_XPP 0x82 /* Page program */
--
2.14.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] mtd: spi-nor: add support for sst26wf016, sst26wf032
2018-09-04 15:33 ` Eugeniy Paltsev
@ 2018-09-04 15:33 ` Eugeniy Paltsev
-1 siblings, 0 replies; 8+ messages in thread
From: Eugeniy Paltsev @ 2018-09-04 15:33 UTC (permalink / raw)
To: linux-mtd
Cc: linux-snps-arc, linux-kernel, Alexey Brodkin, Vineet Gupta,
Marek Vasut, David Woodhouse, Brian Norris, Boris Brezillon,
Richard Weinberger, Eugeniy Paltsev
This commit adds support for the SST sst26wf016 and sst26wf032
flash IC.
NOTE:
this patch is basically following mine u-boot commit port:
http://git.denx.de/?p=u-boot.git;a=commitdiff;h=a19e97157c3721ef9c4b15c68c1773467a3b4a98
Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
---
drivers/mtd/spi-nor/spi-nor.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 6f74c75c9ddc..e1562363862a 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1333,6 +1333,8 @@ static const struct flash_info spi_nor_ids[] = {
{ "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) },
{ "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
{ "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
+ { "sst26wf016", INFO(0xbf2651, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "sst26wf032", INFO(0xbf2622, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
/* ST Microelectronics -- newer production may have feature updates */
--
2.14.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] mtd: spi-nor: add support for sst26wf016, sst26wf032
@ 2018-09-04 15:33 ` Eugeniy Paltsev
0 siblings, 0 replies; 8+ messages in thread
From: Eugeniy Paltsev @ 2018-09-04 15:33 UTC (permalink / raw)
To: linux-snps-arc
This commit adds support for the SST sst26wf016 and sst26wf032
flash IC.
NOTE:
this patch is basically following mine u-boot commit port:
http://git.denx.de/?p=u-boot.git;a=commitdiff;h=a19e97157c3721ef9c4b15c68c1773467a3b4a98
Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev at synopsys.com>
---
drivers/mtd/spi-nor/spi-nor.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 6f74c75c9ddc..e1562363862a 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1333,6 +1333,8 @@ static const struct flash_info spi_nor_ids[] = {
{ "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) },
{ "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
{ "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
+ { "sst26wf016", INFO(0xbf2651, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "sst26wf032", INFO(0xbf2622, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
/* ST Microelectronics -- newer production may have feature updates */
--
2.14.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops
2018-09-04 15:33 ` Eugeniy Paltsev
@ 2018-09-06 16:34 ` kbuild test robot
-1 siblings, 0 replies; 8+ messages in thread
From: kbuild test robot @ 2018-09-06 16:34 UTC (permalink / raw)
To: Eugeniy Paltsev
Cc: kbuild-all, linux-mtd, linux-snps-arc, linux-kernel,
Alexey Brodkin, Vineet Gupta, Marek Vasut, David Woodhouse,
Brian Norris, Boris Brezillon, Richard Weinberger,
Eugeniy Paltsev
[-- Attachment #1: Type: text/plain, Size: 4819 bytes --]
Hi Eugeniy,
I love your patch! Perhaps something to improve:
[auto build test WARNING on mtd/spi-nor/next]
[also build test WARNING on v4.19-rc2 next-20180906]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Eugeniy-Paltsev/MTD-spi-nor-add-support-for-sst26wf016-sst26wf032/20180907-001236
base: git://git.infradead.org/linux-mtd.git spi-nor/next
config: x86_64-randconfig-x015-201835 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
Note: it may well be a FALSE warning. FWIW you are at least aware of it now.
http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings
All warnings (new ones prefixed by >>):
drivers/mtd/spi-nor/spi-nor.c: In function 'sst26_lock_ctl':
>> drivers/mtd/spi-nor/spi-nor.c:671:5: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized]
if (ret < 0) {
^
vim +/ret +671 drivers/mtd/spi-nor/spi-nor.c
637
638 /*
639 * Lock, unlock or check lock status of the flash region of the flash (depending
640 * on the lock_ctl value)
641 */
642 static int sst26_lock_ctl(struct spi_nor *nor, loff_t ofs, uint64_t len, enum lock_ctl ctl)
643 {
644 struct mtd_info *mtd = &nor->mtd;
645 u32 i, bpr_ptr, rptr_64k, lptr_64k, bpr_size;
646 bool lower_64k = false, upper_64k = false;
647 u8 bpr_buff[SST26_MAX_BPR_REG_LEN] = {};
648 int ret;
649
650 /* Check length and offset for 64k alignment */
651 if ((ofs & (SZ_64K - 1)) || (len & (SZ_64K - 1))) {
652 dev_err(nor->dev, "length or offset is not 64KiB allighned\n");
653 return -EINVAL;
654 }
655
656 if (ofs + len > mtd->size) {
657 dev_err(nor->dev, "range is more than device size: %#llx + %#llx > %#llx\n",
658 ofs, len, mtd->size);
659 return -EINVAL;
660 }
661
662 /* SST26 family has only 16 Mbit, 32 Mbit and 64 Mbit IC */
663 if (mtd->size != SZ_2M &&
664 mtd->size != SZ_4M &&
665 mtd->size != SZ_8M)
666 return -EINVAL;
667
668 bpr_size = 2 + (mtd->size / SZ_64K / 8);
669
670 nor->read_reg(nor, SPINOR_OP_READ_BPR, bpr_buff, bpr_size);
> 671 if (ret < 0) {
672 dev_err(nor->dev, "fail to read block-protection register\n");
673 return ret;
674 }
675
676 rptr_64k = min_t(u32, ofs + len, mtd->size - SST26_BOUND_REG_SIZE);
677 lptr_64k = max_t(u32, ofs, SST26_BOUND_REG_SIZE);
678
679 upper_64k = ((ofs + len) > (mtd->size - SST26_BOUND_REG_SIZE));
680 lower_64k = (ofs < SST26_BOUND_REG_SIZE);
681
682 /* Lower bits in block-protection register are about 64k region */
683 bpr_ptr = lptr_64k / SZ_64K - 1;
684
685 /* Process 64K blocks region */
686 while (lptr_64k < rptr_64k) {
687 if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
688 return EACCES;
689
690 bpr_ptr++;
691 lptr_64k += SZ_64K;
692 }
693
694 /* 32K and 8K region bits in BPR are after 64k region bits */
695 bpr_ptr = (mtd->size - 2 * SST26_BOUND_REG_SIZE) / SZ_64K;
696
697 /* Process lower 32K block region */
698 if (lower_64k)
699 if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
700 return EACCES;
701
702 bpr_ptr++;
703
704 /* Process upper 32K block region */
705 if (upper_64k)
706 if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
707 return EACCES;
708
709 bpr_ptr++;
710
711 /* Process lower 8K block regions */
712 for (i = 0; i < SST26_BPR_8K_NUM; i++) {
713 if (lower_64k)
714 if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
715 return EACCES;
716
717 /* In 8K area BPR has both read and write protection bits */
718 bpr_ptr += 2;
719 }
720
721 /* Process upper 8K block regions */
722 for (i = 0; i < SST26_BPR_8K_NUM; i++) {
723 if (upper_64k)
724 if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
725 return EACCES;
726
727 /* In 8K area BPR has both read and write protection bits */
728 bpr_ptr += 2;
729 }
730
731 /* If we check region status we don't need to write BPR back */
732 if (ctl == SST26_CTL_CHECK)
733 return 0;
734
735 nor->write_reg(nor, SPINOR_OP_WRITE_BPR, bpr_buff, bpr_size);
736 if (ret < 0) {
737 dev_err(nor->dev, "fail to write block-protection register\n");
738 return ret;
739 }
740
741 return 0;
742 }
743
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29652 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops
@ 2018-09-06 16:34 ` kbuild test robot
0 siblings, 0 replies; 8+ messages in thread
From: kbuild test robot @ 2018-09-06 16:34 UTC (permalink / raw)
To: linux-snps-arc
Hi Eugeniy,
I love your patch! Perhaps something to improve:
[auto build test WARNING on mtd/spi-nor/next]
[also build test WARNING on v4.19-rc2 next-20180906]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Eugeniy-Paltsev/MTD-spi-nor-add-support-for-sst26wf016-sst26wf032/20180907-001236
base: git://git.infradead.org/linux-mtd.git spi-nor/next
config: x86_64-randconfig-x015-201835 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
Note: it may well be a FALSE warning. FWIW you are at least aware of it now.
http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings
All warnings (new ones prefixed by >>):
drivers/mtd/spi-nor/spi-nor.c: In function 'sst26_lock_ctl':
>> drivers/mtd/spi-nor/spi-nor.c:671:5: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized]
if (ret < 0) {
^
vim +/ret +671 drivers/mtd/spi-nor/spi-nor.c
637
638 /*
639 * Lock, unlock or check lock status of the flash region of the flash (depending
640 * on the lock_ctl value)
641 */
642 static int sst26_lock_ctl(struct spi_nor *nor, loff_t ofs, uint64_t len, enum lock_ctl ctl)
643 {
644 struct mtd_info *mtd = &nor->mtd;
645 u32 i, bpr_ptr, rptr_64k, lptr_64k, bpr_size;
646 bool lower_64k = false, upper_64k = false;
647 u8 bpr_buff[SST26_MAX_BPR_REG_LEN] = {};
648 int ret;
649
650 /* Check length and offset for 64k alignment */
651 if ((ofs & (SZ_64K - 1)) || (len & (SZ_64K - 1))) {
652 dev_err(nor->dev, "length or offset is not 64KiB allighned\n");
653 return -EINVAL;
654 }
655
656 if (ofs + len > mtd->size) {
657 dev_err(nor->dev, "range is more than device size: %#llx + %#llx > %#llx\n",
658 ofs, len, mtd->size);
659 return -EINVAL;
660 }
661
662 /* SST26 family has only 16 Mbit, 32 Mbit and 64 Mbit IC */
663 if (mtd->size != SZ_2M &&
664 mtd->size != SZ_4M &&
665 mtd->size != SZ_8M)
666 return -EINVAL;
667
668 bpr_size = 2 + (mtd->size / SZ_64K / 8);
669
670 nor->read_reg(nor, SPINOR_OP_READ_BPR, bpr_buff, bpr_size);
> 671 if (ret < 0) {
672 dev_err(nor->dev, "fail to read block-protection register\n");
673 return ret;
674 }
675
676 rptr_64k = min_t(u32, ofs + len, mtd->size - SST26_BOUND_REG_SIZE);
677 lptr_64k = max_t(u32, ofs, SST26_BOUND_REG_SIZE);
678
679 upper_64k = ((ofs + len) > (mtd->size - SST26_BOUND_REG_SIZE));
680 lower_64k = (ofs < SST26_BOUND_REG_SIZE);
681
682 /* Lower bits in block-protection register are about 64k region */
683 bpr_ptr = lptr_64k / SZ_64K - 1;
684
685 /* Process 64K blocks region */
686 while (lptr_64k < rptr_64k) {
687 if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
688 return EACCES;
689
690 bpr_ptr++;
691 lptr_64k += SZ_64K;
692 }
693
694 /* 32K and 8K region bits in BPR are after 64k region bits */
695 bpr_ptr = (mtd->size - 2 * SST26_BOUND_REG_SIZE) / SZ_64K;
696
697 /* Process lower 32K block region */
698 if (lower_64k)
699 if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
700 return EACCES;
701
702 bpr_ptr++;
703
704 /* Process upper 32K block region */
705 if (upper_64k)
706 if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
707 return EACCES;
708
709 bpr_ptr++;
710
711 /* Process lower 8K block regions */
712 for (i = 0; i < SST26_BPR_8K_NUM; i++) {
713 if (lower_64k)
714 if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
715 return EACCES;
716
717 /* In 8K area BPR has both read and write protection bits */
718 bpr_ptr += 2;
719 }
720
721 /* Process upper 8K block regions */
722 for (i = 0; i < SST26_BPR_8K_NUM; i++) {
723 if (upper_64k)
724 if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
725 return EACCES;
726
727 /* In 8K area BPR has both read and write protection bits */
728 bpr_ptr += 2;
729 }
730
731 /* If we check region status we don't need to write BPR back */
732 if (ctl == SST26_CTL_CHECK)
733 return 0;
734
735 nor->write_reg(nor, SPINOR_OP_WRITE_BPR, bpr_buff, bpr_size);
736 if (ret < 0) {
737 dev_err(nor->dev, "fail to write block-protection register\n");
738 return ret;
739 }
740
741 return 0;
742 }
743
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 29652 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-snps-arc/attachments/20180907/f91ab379/attachment-0001.gz>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2018-09-06 16:35 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-04 15:33 [PATCH 0/2] MTD: spi-nor: add support for sst26wf016, sst26wf032 Eugeniy Paltsev
2018-09-04 15:33 ` Eugeniy Paltsev
2018-09-04 15:33 ` [PATCH 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops Eugeniy Paltsev
2018-09-04 15:33 ` Eugeniy Paltsev
2018-09-06 16:34 ` kbuild test robot
2018-09-06 16:34 ` kbuild test robot
2018-09-04 15:33 ` [PATCH 2/2] mtd: spi-nor: add support for sst26wf016, sst26wf032 Eugeniy Paltsev
2018-09-04 15:33 ` Eugeniy Paltsev
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.