All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 09/18] sf: add hooks to handle register read and write operations
Date: Tue, 15 Mar 2016 19:12:31 +0100	[thread overview]
Message-ID: <54eb8c8c404be5cd4215345d52557c54d1a4eee1.1458063638.git.cyrille.pitchen@atmel.com> (raw)
In-Reply-To: <cover.1458063638.git.cyrille.pitchen@atmel.com>

This patch finalizes the split of internal register and memory data SPI
commands. Indeed some (Q)SPI controllers such as the Atmel QSPI controller
need to make the difference between register read/write SPI commands and
data read/write/erase SPI commands.

It follows an interface close to the one used by the spi-nor.c driver in
Linux:
- read_reg:   read out the register
- write_reg:  write data to the register
- read:       read data from the SPI flash
- write:      write data into the SPI flash
- erase:      erase sectors of the SPI flash

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
 drivers/mtd/spi/sf-uclass.c   | 11 +++++++
 drivers/mtd/spi/sf_internal.h | 13 ++++++--
 drivers/mtd/spi/sf_probe.c    | 18 +++++++++++
 drivers/mtd/spi/spi_flash.c   | 70 ++++++++++++++++++++++++-------------------
 include/spi_flash.h           | 58 +++++++++++++++++++++++++++++++++++
 5 files changed, 137 insertions(+), 33 deletions(-)

diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
index 19de964e6121..ebae9b1edb15 100644
--- a/drivers/mtd/spi/sf-uclass.c
+++ b/drivers/mtd/spi/sf-uclass.c
@@ -13,6 +13,17 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+int spi_flash_read_reg_dm(struct udevice *dev, u8 opcode, size_t len, void *buf)
+{
+	return sf_get_ops(dev)->read_reg(dev, opcode, len, buf);
+}
+
+int spi_flash_write_reg_dm(struct udevice *dev, u8 opcode, size_t len,
+			   const void *buf)
+{
+	return sf_get_ops(dev)->write_reg(dev, opcode, len, buf);
+}
+
 int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf)
 {
 	return sf_get_ops(dev)->read(dev, offset, len, buf);
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 569863a31684..15a5fa9c2afd 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -12,6 +12,7 @@
 
 #include <linux/types.h>
 #include <linux/compiler.h>
+#include <spi_flash.h>
 
 /* Dual SPI flash memories - see SPI_COMM_DUAL_... */
 enum spi_dual_flash {
@@ -185,13 +186,13 @@ int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len);
 /* Enable writing on the SPI flash */
 static inline int spi_flash_cmd_write_enable(struct spi_flash *flash)
 {
-	return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0);
+	return spi_flash_write_reg(flash, CMD_WRITE_ENABLE, 0, NULL);
 }
 
 /* Disable writing on the SPI flash */
 static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)
 {
-	return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0);
+	return spi_flash_write_reg(flash, CMD_WRITE_DISABLE, 0, NULL);
 }
 
 /* Wait for Busy/Write in Progress flag to be cleared */
@@ -206,6 +207,10 @@ int spi_flash_wait_ready(struct spi_flash *flash);
 int spi_flash_update_reg(struct spi_flash *flash, u8 opcode, size_t len,
 			 const void *buf);
 
+/* Flash write register operation */
+int spi_flash_cmd_write_reg_ops(struct spi_flash *flash, u8 opcode, size_t len,
+				const void *buf);
+
 /*
  * Flash write operation, support all possible write commands.
  * Write the requested data out breaking it up into multiple write
@@ -219,6 +224,10 @@ typedef int (*spi_flash_write_fn)(struct spi_flash *, u32, size_t,
 int spi_flash_write_alg(struct spi_flash *flash, u32 offset, size_t len,
 			const void *buf, spi_flash_write_fn write_fn);
 
+/* Flash read register operation */
+int spi_flash_cmd_read_reg_ops(struct spi_flash *flash, u8 opcode, size_t len,
+			       void *buf);
+
 /* Flash read operation, support all possible read commands */
 int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		size_t len, void *data);
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 7b296378d2be..fbd7d4740b51 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -111,6 +111,22 @@ void spi_flash_free(struct spi_flash *flash)
 
 #else /* defined CONFIG_DM_SPI_FLASH */
 
+static int spi_flash_std_read_reg(struct udevice *dev, u8 opcode, size_t len,
+				  void *buf)
+{
+	struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+	return spi_flash_cmd_read_reg_ops(flash, opcode, len, buf);
+}
+
+static int spi_flash_std_write_reg(struct udevice *dev, u8 opcode, size_t len,
+				   const void *buf)
+{
+	struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+	return spi_flash_cmd_write_reg_ops(flash, opcode, len, buf);
+}
+
 static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
 			      void *buf)
 {
@@ -157,6 +173,8 @@ static int spi_flash_std_probe(struct udevice *dev)
 }
 
 static const struct dm_spi_flash_ops spi_flash_std_ops = {
+	.read_reg = spi_flash_std_read_reg,
+	.write_reg = spi_flash_std_write_reg,
 	.read = spi_flash_std_read,
 	.write = spi_flash_std_write,
 	.erase = spi_flash_std_erase,
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 4be99ea0b424..4f269eacc591 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -32,12 +32,9 @@ static void spi_flash_addr(u32 addr, u8 *cmd)
 
 static int read_sr(struct spi_flash *flash, u8 *rs)
 {
-	struct spi_slave *spi = flash->spi;
 	int ret;
-	u8 cmd;
 
-	cmd = CMD_READ_STATUS;
-	ret = spi_flash_cmd_read(spi, &cmd, 1, rs, 1);
+	ret = spi_flash_read_reg(flash, CMD_READ_STATUS, 1, rs);
 	if (ret < 0) {
 		debug("SF: fail to read status register\n");
 		return ret;
@@ -48,11 +45,9 @@ static int read_sr(struct spi_flash *flash, u8 *rs)
 
 static int read_fsr(struct spi_flash *flash, u8 *fsr)
 {
-	struct spi_slave *spi = flash->spi;
 	int ret;
-	const u8 cmd = CMD_FLAG_STATUS;
 
-	ret = spi_flash_cmd_read(spi, &cmd, 1, fsr, 1);
+	ret = spi_flash_read_reg(flash, CMD_FLAG_STATUS, 1, fsr);
 	if (ret < 0) {
 		debug("SF: fail to read flag status register\n");
 		return ret;
@@ -77,12 +72,9 @@ static int write_sr(struct spi_flash *flash, u8 ws)
 #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
 static int read_cr(struct spi_flash *flash, u8 *rc)
 {
-	struct spi_slave *spi = flash->spi;
 	int ret;
-	u8 cmd;
 
-	cmd = CMD_READ_CONFIG;
-	ret = spi_flash_cmd_read(spi, &cmd, 1, rc, 1);
+	ret = spi_flash_read_reg(flash, CMD_READ_CONFIG, 1, rc);
 	if (ret < 0) {
 		debug("SF: fail to read config register\n");
 		return ret;
@@ -134,7 +126,6 @@ bar_end:
 
 static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0)
 {
-	struct spi_slave *spi = flash->spi;
 	u8 curr_bank = 0;
 	int ret;
 
@@ -151,7 +142,7 @@ static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0)
 		flash->bank_write_cmd = CMD_EXTNADDR_WREAR;
 	}
 
-	ret = spi_flash_cmd_read(spi, &flash->bank_read_cmd, 1, &curr_bank, 1);
+	ret = spi_flash_read_reg(flash, flash->bank_read_cmd, &curr_bank, 1);
 	if (ret) {
 		debug("SF: fail to read bank addr register\n");
 		return ret;
@@ -257,7 +248,6 @@ int spi_flash_wait_ready(struct spi_flash *flash)
 int spi_flash_update_reg(struct spi_flash *flash, u8 opcode,
 			 size_t len, const void *buf)
 {
-	struct spi_slave *spi = flash->spi;
 	int ret;
 
 	ret = spi_flash_cmd_write_enable(flash);
@@ -266,7 +256,7 @@ int spi_flash_update_reg(struct spi_flash *flash, u8 opcode,
 		return ret;
 	}
 
-	ret = spi_flash_cmd_write(spi, &opcode, 1, buf, len);
+	ret = spi_flash_write_reg(flash, opcode, len, buf);
 	if (ret < 0) {
 		debug("SF: write cmd failed\n");
 		return ret;
@@ -281,6 +271,14 @@ int spi_flash_update_reg(struct spi_flash *flash, u8 opcode,
 	return 0;
 }
 
+int spi_flash_cmd_write_reg_ops(struct spi_flash *flash, u8 opcode, size_t len,
+				const void *buf)
+{
+	struct spi_slave *spi = flash->spi;
+
+	return spi_flash_cmd_write(spi, &opcode, 1, buf, len);
+}
+
 int spi_flash_erase_alg(struct spi_flash *flash, u32 offset, size_t len,
 			spi_flash_erase_fn erase_fn)
 {
@@ -460,6 +458,14 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 				   spi_flash_write_impl);
 }
 
+int spi_flash_cmd_read_reg_ops(struct spi_flash *flash, u8 opcode,
+			       size_t len, void *buf)
+{
+	struct spi_slave *spi = flash->spi;
+
+	return spi_flash_cmd_read(spi, &opcode, 1, buf, len);
+}
+
 /*
  * TODO: remove the weak after all the other spi_flash_copy_mmap
  * implementations removed from drivers
@@ -982,8 +988,25 @@ int spi_flash_scan(struct spi_flash *flash)
 		CMD_READ_DUAL_IO_FAST,
 		CMD_READ_QUAD_IO_FAST };
 
+	/* Assign spi_flash ops */
+#ifndef CONFIG_DM_SPI_FLASH
+	flash->read_reg = spi_flash_cmd_read_reg_ops;
+	flash->write_reg = spi_flash_cmd_write_reg_ops;
+	flash->write = spi_flash_cmd_write_ops;
+#if defined(CONFIG_SPI_FLASH_SST)
+	if (flash->flags & SNOR_F_SST_WR) {
+		if (spi->mode & SPI_TX_BYTE)
+			flash->write = sst_write_bp;
+		else
+			flash->write = sst_write_wp;
+	}
+#endif
+	flash->erase = spi_flash_cmd_erase_ops;
+	flash->read = spi_flash_cmd_read_ops;
+#endif
+
 	/* Read the ID codes */
-	ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
+	ret = spi_flash_read_reg(flash, CMD_READ_ID, sizeof(idcode), idcode);
 	if (ret) {
 		printf("SF: Failed to get idcodes\n");
 		return ret;
@@ -1032,21 +1055,6 @@ int spi_flash_scan(struct spi_flash *flash)
 	if (params->flags & SST_WR)
 		flash->flags |= SNOR_F_SST_WR;
 
-	/* Assign spi_flash ops */
-#ifndef CONFIG_DM_SPI_FLASH
-	flash->write = spi_flash_cmd_write_ops;
-#if defined(CONFIG_SPI_FLASH_SST)
-	if (flash->flags & SNOR_F_SST_WR) {
-		if (spi->mode & SPI_TX_BYTE)
-			flash->write = sst_write_bp;
-		else
-			flash->write = sst_write_wp;
-	}
-#endif
-	flash->erase = spi_flash_cmd_erase_ops;
-	flash->read = spi_flash_cmd_read_ops;
-#endif
-
 	/* lock hooks are flash specific - assign them based on idcode0 */
 	switch (idcode[0]) {
 #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
diff --git a/include/spi_flash.h b/include/spi_flash.h
index d0ce9e721ad0..31d11e55571d 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -52,6 +52,9 @@ struct spi_slave;
  * @flash_lock:		lock a region of the SPI Flash
  * @flash_unlock:	unlock a region of the SPI Flash
  * @flash_is_locked:	check if a region of the SPI Flash is completely locked
+ * @read_reg:		Flash read_reg ops: Send cmd to read len bytes into buf
+ * @write_reg:		Flash write_reg ops: Send cmd to write len bytes from
+ *			buf
  * @read:		Flash read ops: Read len bytes at offset into buf
  *			Supported cmds: Fast Array Read
  * @write:		Flash write ops: Write len bytes from buf into offset
@@ -101,6 +104,10 @@ struct spi_flash {
 	 * if required, perhaps with a way of scanning through the list to
 	 * find the driver that matches the device.
 	 */
+	int (*read_reg)(struct spi_flash *flash, u8 opcode, size_t len,
+			void *buf);
+	int (*write_reg)(struct spi_flash *flash, u8 opcode, size_t len,
+			 const void *buf);
 	int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);
 	int (*write)(struct spi_flash *flash, u32 offset, size_t len,
 			const void *buf);
@@ -109,6 +116,9 @@ struct spi_flash {
 };
 
 struct dm_spi_flash_ops {
+	int (*read_reg)(struct udevice *dev, u8 opcode, size_t len, void *buf);
+	int (*write_reg)(struct udevice *dev, u8 opcode, size_t len,
+			 const void *buf);
 	int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf);
 	int (*write)(struct udevice *dev, u32 offset, size_t len,
 		     const void *buf);
@@ -120,6 +130,30 @@ struct dm_spi_flash_ops {
 
 #ifdef CONFIG_DM_SPI_FLASH
 /**
+ * spi_flash_read_reg_dm() - Send register command and read data result
+ *
+ * @dev:	SPI flash device
+ * @opcode:	Register command op code
+ * @len:	Number of bytes to read as register command output
+ * @buf:	Buffer to fill with the register command output
+ * @return 0 if OK, -ve on error
+ */
+int spi_flash_read_reg_dm(struct udevice *dev, u8 opcode, size_t len,
+			  void *buf);
+
+/**
+ * spi_flash_write_reg_dm() - Send register command with data
+ *
+ * @dev:	SPI flash device
+ * @opcode:	Register command op code
+ * @len:	Number of bytes to write as register command input
+ * @buf:	Buffer filled with the register command input
+ * @return 0 if OK, -ve on error
+ */
+int spi_flash_write_reg_dm(struct udevice *dev, u8 opcode, size_t len,
+			   const void *buf);
+
+/**
  * spi_flash_read_dm() - Read data from SPI flash
  *
  * @dev:	SPI flash device
@@ -165,6 +199,18 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
 /* Compatibility function - this is the old U-Boot API */
 void spi_flash_free(struct spi_flash *flash);
 
+static inline int spi_flash_read_reg(struct spi_flash *flash, u8 opcode,
+				     size_t len, void *buf)
+{
+	return spi_flash_read_reg_dm(flash->dev, opcode, len, buf);
+}
+
+static inline int spi_flash_write_reg(struct spi_flash *flash, u8 opcode,
+				      size_t len, const void *buf)
+{
+	return spi_flash_write_reg_dm(flash->dev, opcode, len, buf);
+}
+
 static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
 				 size_t len, void *buf)
 {
@@ -208,6 +254,18 @@ struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
 
 void spi_flash_free(struct spi_flash *flash);
 
+static inline int spi_flash_read_reg(struct spi_flash *flash, u8 opcode,
+				     size_t len, void *buf)
+{
+	return flash->read_reg(flash, opcode, len, buf);
+}
+
+static inline int spi_flash_write_reg(struct spi_flash *flash, u8 opcode,
+				      size_t len, const void *buf)
+{
+	return flash->write_reg(flash, opcode, len, buf);
+}
+
 static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
 		size_t len, void *buf)
 {
-- 
1.8.2.2

  parent reply	other threads:[~2016-03-15 18:12 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-15 18:12 [U-Boot] [PATCH 00/18] sf: fix support of QSPI memories and controllers Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 01/18] Revert "sf: Fix quad bit set for micron devices" Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 02/18] sf: call spi_claim_bus() and spi_release_bus() only once per read, write or erase Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 03/18] sf: replace spi_flash_read_common() calls by spi_flash_cmd_read() Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 04/18] sf: remove spi_flash_write_common() Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 05/18] sf: export spi_flash_wait_ready() function Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 06/18] sf: share erase generic algorithm Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 07/18] sf: share write " Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 08/18] sf: share read " Cyrille Pitchen
2016-03-15 18:12 ` Cyrille Pitchen [this message]
2016-03-15 18:12 ` [U-Boot] [PATCH 10/18] sf: move support of SST flash into generic spi_flash_write_alg() Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 11/18] sf: fix selection of supported READ commands for QSPI memories Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 12/18] sf: fix detection of QSPI memories when they boot in Quad or Dual mode Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 13/18] sf: add helper function to set the number of dummy bytes Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 14/18] sf: add 4byte address opcodes Cyrille Pitchen
2016-03-21  8:58   ` [U-Boot] [PATCH 14/18 v2] " Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 15/18] sf: prepare next fixes to support of QSPI memories by manufacturer Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 16/18] sf: fix support of Micron memories Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 17/18] ARM: at91: clock: add function to get QSPI clocks Cyrille Pitchen
2016-03-15 18:12 ` [U-Boot] [PATCH 18/18] sf: add driver for Atmel QSPI controller Cyrille Pitchen
2016-03-15 18:21 ` [U-Boot] [PATCH 00/18] sf: fix support of QSPI memories and controllers Jagan Teki
2016-03-15 19:17   ` Marek Vasut
2016-03-16 13:30   ` Cyrille Pitchen
2016-03-16 14:14     ` Jagan Teki
2016-03-16 16:23       ` Albert ARIBAUD
2016-03-16 16:34         ` Jagan Teki
2016-03-17  7:30           ` Albert ARIBAUD
2016-03-16 16:30       ` Cyrille Pitchen
2016-03-16 16:41         ` [U-Boot] [PATCH 1/4] rework board config files Cyrille Pitchen
2016-03-16 16:41           ` [U-Boot] [PATCH 2/4] sama5d2_xplained: add support of QSPI controllers Cyrille Pitchen
2016-03-16 16:41           ` [U-Boot] [PATCH 3/4] dts: add dts file for Atmel sama5d2 xplained board Cyrille Pitchen
2016-03-16 16:41           ` [U-Boot] [PATCH 4/4] sf: fix sf probe Cyrille Pitchen
2016-03-18 13:48       ` [U-Boot] [PATCH 00/18] sf: fix support of QSPI memories and controllers Stefan Roese
2016-03-18 15:18         ` Cyrille Pitchen
2016-03-21  9:07           ` Jagan Teki
2016-03-21 13:13             ` Cyrille Pitchen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54eb8c8c404be5cd4215345d52557c54d1a4eee1.1458063638.git.cyrille.pitchen@atmel.com \
    --to=cyrille.pitchen@atmel.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.