linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] MTD: spi-nor: add support for sst26wf016, sst26wf032
@ 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 ` [PATCH 2/2] mtd: spi-nor: add support for sst26wf016, sst26wf032 Eugeniy Paltsev
  0 siblings, 2 replies; 4+ 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] 4+ messages in thread

* [PATCH 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops
  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-06 16:34   ` kbuild test robot
  2018-09-04 15:33 ` [PATCH 2/2] mtd: spi-nor: add support for sst26wf016, sst26wf032 Eugeniy Paltsev
  1 sibling, 1 reply; 4+ 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] 4+ messages in thread

* [PATCH 2/2] mtd: spi-nor: add support for sst26wf016, sst26wf032
  2018-09-04 15:33 [PATCH 0/2] MTD: spi-nor: add support for sst26wf016, sst26wf032 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
  1 sibling, 0 replies; 4+ 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] 4+ messages in thread

* Re: [PATCH 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops
  2018-09-04 15:33 ` [PATCH 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops Eugeniy Paltsev
@ 2018-09-06 16:34   ` kbuild test robot
  0 siblings, 0 replies; 4+ 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] 4+ messages in thread

end of thread, other threads:[~2018-09-06 16:35 UTC | newest]

Thread overview: 4+ 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 ` [PATCH 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops Eugeniy Paltsev
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).