[PATCH 2/4] mtd: spi-nor: add advanced protection and security features support

shiva.linuxworks at gmail.com shiva.linuxworks at gmail.com
Wed Oct 27 03:33:50 PDT 2021


From: Shivamurthy Shastri <sshivamurthy at micron.com>

Added functionalities to support advanced securtiy and protection
features in new SPI NOR flashes.

Signed-off-by: Shivamurthy Shastri <sshivamurthy at micron.com>
---
 drivers/mtd/spi-nor/Makefile     |   2 +-
 drivers/mtd/spi-nor/advprotsec.c | 209 +++++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/core.c       |   2 +
 include/linux/mtd/mtd.h          |  19 +++
 4 files changed, 231 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/spi-nor/advprotsec.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 6b904e439372..8e96e2c65c7a 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
-spi-nor-objs			:= core.o sfdp.o swp.o otp.o sysfs.o
+spi-nor-objs			:= core.o sfdp.o swp.o otp.o advprotsec.o sysfs.o
 spi-nor-objs			+= atmel.o
 spi-nor-objs			+= catalyst.o
 spi-nor-objs			+= eon.o
diff --git a/drivers/mtd/spi-nor/advprotsec.c b/drivers/mtd/spi-nor/advprotsec.c
new file mode 100644
index 000000000000..4dc8e67b16ef
--- /dev/null
+++ b/drivers/mtd/spi-nor/advprotsec.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPI NOR Advanced Sector Protection and Security Features
+ *
+ * Copyright (C) 2021 Micron Technology, Inc.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static int spi_nor_secure_read(struct mtd_info *mtd, size_t len, u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->secure_read(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_secure_write(struct mtd_info *mtd, size_t len, u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->secure_write(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_vlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
+				   u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_vlock_bits(nor, addr, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_write_vlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
+				    u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->write_vlock_bits(nor, addr, len, buf);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_disable(nor);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_nvlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
+				    u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_nvlock_bits(nor, addr, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_write_nvlock_bits(struct mtd_info *mtd, u32 addr)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->write_nvlock_bits(nor, addr);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_disable(nor);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_erase_nvlock_bits(struct mtd_info *mtd)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->erase_nvlock_bits(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_disable(nor);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_global_freeze_bits(struct mtd_info *mtd, size_t len,
+					   u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_global_freeze_bits(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_write_global_freeze_bits(struct mtd_info *mtd, size_t len,
+					    u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->write_global_freeze_bits(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_password(struct mtd_info *mtd, size_t len, u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_password(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+void spi_nor_register_security_ops(struct spi_nor *nor)
+{
+	struct mtd_info *mtd = &nor->mtd;
+
+	if (!nor->params->sec_ops)
+		return;
+
+	mtd->_secure_packet_read = spi_nor_secure_read;
+	mtd->_secure_packet_write = spi_nor_secure_write;
+	mtd->_read_vlock_bits = spi_nor_read_vlock_bits;
+	mtd->_write_vlock_bits = spi_nor_write_vlock_bits;
+	mtd->_read_nvlock_bits = spi_nor_read_nvlock_bits;
+	mtd->_write_nvlock_bits = spi_nor_write_nvlock_bits;
+	mtd->_erase_nvlock_bits = spi_nor_erase_nvlock_bits;
+	mtd->_read_global_freeze_bits = spi_nor_read_global_freeze_bits;
+	mtd->_write_global_freeze_bits = spi_nor_write_global_freeze_bits;
+	mtd->_read_password = spi_nor_read_password;
+}
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index cc08bd707378..864f3c7783b3 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3199,6 +3199,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 
 	spi_nor_register_locking_ops(nor);
 
+	spi_nor_register_security_ops(nor);
+
 	/* Send all the required SPI flash commands to initialize device */
 	ret = spi_nor_init(nor);
 	if (ret)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 88227044fc86..bce358c9fb94 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -360,6 +360,25 @@ struct mtd_info {
 	int (*_get_device) (struct mtd_info *mtd);
 	void (*_put_device) (struct mtd_info *mtd);
 
+	/*
+	 * Security Operations
+	 */
+	int (*_secure_packet_read)(struct mtd_info *mtd, size_t len, u8 *buf);
+	int (*_secure_packet_write)(struct mtd_info *mtd, size_t len, u8 *buf);
+	int (*_read_vlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
+				u8 *buf);
+	int (*_write_vlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
+				 u8 *buf);
+	int (*_read_nvlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
+				 u8 *buf);
+	int (*_write_nvlock_bits)(struct mtd_info *mtd, u32 addr);
+	int (*_erase_nvlock_bits)(struct mtd_info *mtd);
+	int (*_read_global_freeze_bits)(struct mtd_info *mtd, size_t len,
+					u8 *buf);
+	int (*_write_global_freeze_bits)(struct mtd_info *mtd, size_t len,
+					 u8 *buf);
+	int (*_read_password)(struct mtd_info *mtd, size_t len, u8 *buf);
+
 	/*
 	 * flag indicates a panic write, low level drivers can take appropriate
 	 * action if required to ensure writes go through
-- 
2.25.1




More information about the linux-mtd mailing list