[U-Boot] [PATCH v7 76/87] mtd: spi-nor: Move opcode handling in m25p80

Jagan Teki jteki at openedev.com
Tue Mar 22 08:38:28 CET 2016


It's required to handling opcode in spi drivers
interface layer, m25p80 from spi-nor, becuase some
spi-nor controller drivers like fsl_qspi have separate
opcode's to handling the same operations.

Cc: Simon Glass <sjg at chromium.org>
Cc: Bin Meng <bmeng.cn at gmail.com>
Cc: Mugunthan V N <mugunthanvnm at ti.com>
Cc: Michal Simek <michal.simek at xilinx.com>
Cc: Siva Durga Prasad Paladugu <sivadur at xilinx.com>
Signed-off-by: Jagan Teki <jteki at openedev.com>
---
 drivers/mtd/spi-nor/m25p80.c  | 53 ++++++++++++++++++++++++++++--------
 drivers/mtd/spi-nor/spi-nor.c | 62 +++++++------------------------------------
 include/linux/mtd/spi-nor.h   | 10 +++----
 3 files changed, 56 insertions(+), 69 deletions(-)

diff --git a/drivers/mtd/spi-nor/m25p80.c b/drivers/mtd/spi-nor/m25p80.c
index cf27ba0..560e5b2 100644
--- a/drivers/mtd/spi-nor/m25p80.c
+++ b/drivers/mtd/spi-nor/m25p80.c
@@ -17,14 +17,24 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/spi-nor.h>
 
+#define MAX_CMD_SIZE		6
 struct m25p {
 	struct spi_slave	*spi;
 	struct spi_nor		spi_nor;
 #ifndef CONFIG_DM_MTD_SPI_NOR
 	struct mtd_info		mtd;
 #endif
+	u8			command[MAX_CMD_SIZE];
 };
 
+static void spi_nor_addr(u32 addr, u8 *cmd)
+{
+	/* cmd[0] is actual command */
+	cmd[1] = addr >> 16;
+	cmd[2] = addr >> 8;
+	cmd[3] = addr >> 0;
+}
+
 static int m25p80_read_reg(struct spi_nor *nor, u8 cmd, u8 *val, int len)
 {
 	struct m25p *flash = nor->priv;
@@ -112,8 +122,8 @@ static int m25p80_read_mmap(struct spi_nor *nor, void *data,
 	return ret;
 }
 
-static int m25p80_read(struct spi_nor *nor, const u8 *cmd, size_t cmd_len,
-				void *data, size_t data_len)
+static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
+		       u_char *buf)
 {
 	struct m25p *flash = nor->priv;
 	struct spi_slave *spi = flash->spi;
@@ -125,12 +135,16 @@ static int m25p80_read(struct spi_nor *nor, const u8 *cmd, size_t cmd_len,
 		return ret;
 	}
 
+	flash->command[0] = nor->read_opcode;
+	spi_nor_addr(from, flash->command);
+
 	if (nor->flags & SNOR_F_U_PAGE)
 		spi->flags |= SPI_XFER_U_PAGE;
 
-	ret = spi_write_then_read(spi, cmd, cmd_len, NULL, data, data_len);
+	ret = spi_write_then_read(spi, flash->command, 4 + nor->read_dummy,
+				  NULL, buf, len);
 	if (ret < 0) {
-		debug("m25p80: error %d reading %x\n", ret, *cmd);
+		debug("m25p80: error %d reading %x\n", ret, flash->command[0]);
 		return ret;
 	}
 
@@ -139,11 +153,12 @@ static int m25p80_read(struct spi_nor *nor, const u8 *cmd, size_t cmd_len,
 	return ret;
 }
 
-static int m25p80_write(struct spi_nor *nor, const u8 *cmd, size_t cmd_len,
-				const void *data, size_t data_len)
+static int m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
+			const u_char *buf)
 {
 	struct m25p *flash = nor->priv;
 	struct spi_slave *spi = flash->spi;
+	int cmd_sz = 4;
 	int ret;
 
 	ret = spi_claim_bus(spi);
@@ -152,12 +167,22 @@ static int m25p80_write(struct spi_nor *nor, const u8 *cmd, size_t cmd_len,
 		return ret;
 	}
 
+	if (nor->program_opcode == SNOR_OP_AAI_WP)
+		cmd_sz = 1;
+
+	flash->command[0] = nor->program_opcode;
+	spi_nor_addr(to, flash->command);
+
 	if (nor->flags & SNOR_F_U_PAGE)
 		spi->flags |= SPI_XFER_U_PAGE;
 
-	ret = spi_write_then_read(spi, cmd, cmd_len, data, NULL, data_len);
+	debug("m25p80: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
+	       buf, flash->command[0], flash->command[1], flash->command[2],
+	       flash->command[3], len);
+
+	ret = spi_write_then_read(spi, flash->command, cmd_sz, buf, NULL, len);
 	if (ret < 0) {
-		debug("m25p80: error %d writing %x\n", ret, *cmd);
+		debug("m25p80: error %d writing %x\n", ret, flash->command[0]);
 		return ret;
 	}
 
@@ -166,7 +191,7 @@ static int m25p80_write(struct spi_nor *nor, const u8 *cmd, size_t cmd_len,
 	return ret;
 }
 
-static int m25p80_erase(struct spi_nor *nor, const u8 *cmd, size_t cmd_len)
+static int m25p80_erase(struct spi_nor *nor, loff_t offset)
 {
 	struct m25p *flash = nor->priv;
 	struct spi_slave *spi = flash->spi;
@@ -178,12 +203,18 @@ static int m25p80_erase(struct spi_nor *nor, const u8 *cmd, size_t cmd_len)
 		return ret;
 	}
 
+	flash->command[0] = nor->erase_opcode;
+	spi_nor_addr(offset, flash->command);
+
 	if (nor->flags & SNOR_F_U_PAGE)
 		spi->flags |= SPI_XFER_U_PAGE;
 
-	ret = spi_write_then_read(spi, cmd, cmd_len, NULL, NULL, 0);
+	debug("m25p80: erase %2x %2x %2x %2x (%llx)\n", flash->command[0],
+	       flash->command[1], flash->command[2], flash->command[3], offset);
+
+	ret = spi_write_then_read(spi, flash->command, 4, NULL, NULL, 0);
 	if (ret < 0) {
-		debug("m25p80: error %d writing %x\n", ret, *cmd);
+		debug("m25p80: error %d writing %x\n", ret, flash->command[0]);
 		return ret;
 	}
 
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 97f5eaa..cb9ab21 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -32,14 +32,6 @@ static inline int write_disable(struct spi_nor *nor)
 	return nor->write_reg(nor, SNOR_OP_WRDI, NULL, 0);
 }
 
-static void spi_nor_addr(u32 addr, u8 *cmd)
-{
-	/* cmd[0] is actual command */
-	cmd[1] = addr >> 16;
-	cmd[2] = addr >> 8;
-	cmd[3] = addr >> 0;
-}
-
 static int read_sr(struct spi_nor *nor)
 {
 	u8 sr;
@@ -487,7 +479,6 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
 	struct spi_nor *nor = mtd->priv;
 	u32 addr, len, erase_addr;
-	u8 cmd[SNOR_MAX_CMD_SIZE];
 	uint32_t rem;
 	int ret = -1;
 
@@ -506,7 +497,6 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 		}
 	}
 
-	cmd[0] = nor->erase_opcode;
 	while (len) {
 		erase_addr = addr;
 
@@ -519,14 +509,9 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 		if (ret < 0)
 			return ret;
 #endif
-		spi_nor_addr(erase_addr, cmd);
-
-		debug("spi-nor: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
-		      cmd[2], cmd[3], erase_addr);
-
 		write_enable(nor);
 
-		ret = nor->erase(nor, cmd, sizeof(cmd));
+		ret = nor->erase(nor, erase_addr);
 		if (ret < 0)
 			goto erase_err;
 
@@ -556,7 +541,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t offset, size_t len,
 	struct spi_nor *nor = mtd->priv;
 	u32 byte_addr, page_size, write_addr;
 	size_t chunk_len, actual;
-	u8 cmd[SNOR_MAX_CMD_SIZE];
 	int ret = -1;
 
 	if (mtd->_is_locked) {
@@ -569,7 +553,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t offset, size_t len,
 
 	page_size = nor->page_size;
 
-	cmd[0] = nor->program_opcode;
 	for (actual = 0; actual < len; actual += chunk_len) {
 		write_addr = offset;
 
@@ -589,15 +572,9 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t offset, size_t len,
 			chunk_len = min(chunk_len,
 					(size_t)nor->max_write_size);
 
-		spi_nor_addr(write_addr, cmd);
-
-		debug("spi-nor: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
-		      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
-
 		write_enable(nor);
 
-		ret = nor->write(nor, cmd, sizeof(cmd),
-				 buf + actual, chunk_len);
+		ret = nor->write(nor, write_addr, chunk_len, buf + actual);
 		if (ret < 0)
 			break;
 
@@ -617,7 +594,6 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
 {
 	struct spi_nor *nor = mtd->priv;
 	u32 remain_len, read_len, read_addr;
-	u8 cmd[SNOR_MAX_CMD_SIZE], cmdsz;
 	int bank_sel = 0;
 	int ret = -1;
 
@@ -632,8 +608,6 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
 		return ret;
 	}
 
-	cmdsz = SNOR_MAX_CMD_SIZE + nor->read_dummy;
-	cmd[0] = nor->read_opcode;
 	while (len) {
 		read_addr = from;
 
@@ -654,9 +628,7 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
 		else
 			read_len = remain_len;
 
-		spi_nor_addr(read_addr, cmd);
-
-		ret = nor->read(nor, cmd, cmdsz, buf, read_len);
+		ret = nor->read(nor, read_addr, read_len, buf);
 		if (ret < 0)
 			break;
 
@@ -674,21 +646,14 @@ static int sst_byte_write(struct spi_nor *nor, u32 offset,
 			  const void *buf, size_t *retlen)
 {
 	int ret;
-	u8 cmd[4] = {
-		SNOR_OP_BP,
-		offset >> 16,
-		offset >> 8,
-		offset,
-	};
-
-	debug("spi-nor: 0x%p => cmd = { 0x%02x 0x%06x }\n",
-	      buf, cmd[0], offset);
 
 	ret = write_enable(nor);
 	if (ret)
 		return ret;
 
-	ret = nor->write(nor, cmd, sizeof(cmd), buf, 1);
+	nor->program_opcode = SNOR_OP_BP;
+
+	ret = nor->write(nor, offset, 1, buf);
 	if (ret)
 		return ret;
 
@@ -701,9 +666,8 @@ static int sst_write_wp(struct mtd_info *mtd, loff_t offset, size_t len,
 			size_t *retlen, const u_char *buf)
 {
 	struct spi_nor *nor = mtd->priv;
-	size_t actual, cmd_len;
+	size_t actual;
 	int ret;
-	u8 cmd[4];
 
 	/* If the data is not word aligned, write out leading single byte */
 	actual = offset % 2;
@@ -718,17 +682,10 @@ static int sst_write_wp(struct mtd_info *mtd, loff_t offset, size_t len,
 	if (ret)
 		goto done;
 
-	cmd_len = 4;
-	cmd[0] = SNOR_OP_AAI_WP;
-	cmd[1] = offset >> 16;
-	cmd[2] = offset >> 8;
-	cmd[3] = offset;
-
 	for (; actual < len - 1; actual += 2) {
-		debug("spi-nor: 0x%p => cmd = { 0x%02x 0x%06llx }\n",
-		      buf + actual, cmd[0], offset);
+		nor->program_opcode = SNOR_OP_AAI_WP;
 
-		ret = nor->write(nor, cmd, cmd_len, buf + actual, 2);
+		ret = nor->write(nor, offset, 2, buf + actual);
 		if (ret) {
 			debug("spi-nor: sst word program failed\n");
 			break;
@@ -738,7 +695,6 @@ static int sst_write_wp(struct mtd_info *mtd, loff_t offset, size_t len,
 		if (ret)
 			break;
 
-		cmd_len = 1;
 		offset += 2;
 		*retlen += 2;
 	}
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 4749ff4..19a5dd0 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -224,11 +224,11 @@ struct spi_nor {
 
 	int (*read_mmap)(struct spi_nor *nor, void *data, void *offset,
 			size_t len);
-	int (*read)(struct spi_nor *nor, const u8 *opcode, size_t cmd_len,
-			void *data, size_t data_len);
-	int (*write)(struct spi_nor *nor, const u8 *cmd, size_t cmd_len,
-			const void *data, size_t data_len);
-	int (*erase)(struct spi_nor *nor, const u8 *cmd, size_t cmd_len);
+	int (*read)(struct spi_nor *nor, loff_t from, size_t len,
+		    u_char *read_buf);
+	int (*write)(struct spi_nor *nor, loff_t to, size_t len,
+		     const u_char *write_buf);
+	int (*erase)(struct spi_nor *nor, loff_t offs);
 
 	int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
 	int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
-- 
1.9.1



More information about the U-Boot mailing list