Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1185970 > unrolled thread

[PATCH 0/7] add driver for Atmel QSPI controller

Started byCyrille Pitchen <cyrille.pitchen@atmel.com>
First post2015-07-16 17:30 +0200
Last post2015-07-16 17:30 +0200
Articles 2 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/7] add driver for Atmel QSPI controller Cyrille Pitchen <cyrille.pitchen@atmel.com> - 2015-07-16 17:30 +0200
    [PATCH 3/7] mtd: spi-nor: allow to tune the number of dummy cycles Cyrille Pitchen <cyrille.pitchen@atmel.com> - 2015-07-16 17:30 +0200

#1185970 — [PATCH 0/7] add driver for Atmel QSPI controller

FromCyrille Pitchen <cyrille.pitchen@atmel.com>
Date2015-07-16 17:30 +0200
Subject[PATCH 0/7] add driver for Atmel QSPI controller
Message-ID<pMTgK-2eq-3@gated-at.bofh.it>
Hi all,

in order to be able to use Micron Quad SPI memories with the new Atmel QSPI
controller I added a new set_protocol() callback into struct spi_nor.
Indeed, once the quad I/O mode has been enabled on a Micron QSPI flash by
clearing bit 7 in its Enhanced Volatile Configuration Register, this memory
expects all the following commands to use the QSPI 4-4-4 protocol. So the
QSPI controller needs to be notified about this protocol change before
reading the Status register, 0x05 command sent by the
spi_nor_wail_till_ready() function, in micron_quad_enable().

Reading spi-nor.h, I saw an interesting struct spi_nor_xfer_cfg and its
associated callbacks write_xfer() and read_xfer(). However these callbacks
don't seem to be used at all for now. They look to have been designed to
add QSPI support to the generic spi-nor framework. So before extending the
framework with my own callback, I'd like to know whether I should have
tried to used the read_xfer()/write_xfer() callbacks to join an already
existing effort to add QSPI support.
If so, I think either the read/write_reg() prototypes should be updated or
new callbacks should be added for register reads/writes. As explained
above, even for reading the Status register the QSPI 4-4-4 protocol must be
used with Micron memories in quad I/O mode. So the framework has to find a
way to tell the QSPI controller which protocol it should use.

So I'm interested in your comments! :)

Best Regards,

Cyrille

ChangeLog

v1:

This series of patches add support for the new Atmel QSPI controller
embedded inside sama5d2x SoCs.

These patches were first developped for linux-3.18-at91 and tested on a
sama5d27 Xplained ultra board, which embeds a Micron n25q128a13 QSPI NOR
flash memory. Then the series was adapted for mainline.

Cyrille Pitchen (7):
  Documentation: mtd: add a DT property to set the number of dummy
    cycles
  mtd: spi-nor: notify (Q)SPI controller about protocol change
  mtd: spi-nor: allow to tune the number of dummy cycles
  Documentation: mtd: add a DT property to set the latency code of
    Spansion memory
  mtd: spi-nor: allow the set the latency code on Spansion memories
  Documentation: atmel-quadspi: add binding file for Atmel QSPI driver
  mtd: atmel-quadspi: add driver for Atmel QSPI controller

 .../devicetree/bindings/mtd/atmel-quadspi.txt      |  29 +
 .../devicetree/bindings/mtd/jedec,spi-nor.txt      |   6 +
 .../devicetree/bindings/mtd/spansion-nor.txt       |  22 +
 drivers/mtd/spi-nor/Kconfig                        |   7 +
 drivers/mtd/spi-nor/Makefile                       |   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c                | 901 +++++++++++++++++++++
 drivers/mtd/spi-nor/spi-nor.c                      | 160 +++-
 include/linux/mtd/spi-nor.h                        |  15 +
 8 files changed, 1122 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
 create mode 100644 Documentation/devicetree/bindings/mtd/spansion-nor.txt
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1185972 — [PATCH 3/7] mtd: spi-nor: allow to tune the number of dummy cycles

FromCyrille Pitchen <cyrille.pitchen@atmel.com>
Date2015-07-16 17:30 +0200
Subject[PATCH 3/7] mtd: spi-nor: allow to tune the number of dummy cycles
Message-ID<pMTgM-2eq-47@gated-at.bofh.it>
In reply to#1185970
The number of dummy cycles used during Fast Read commands can be reduced
to improve transfer performances. Each manufacturer has a dedicated set of
registers to provide the memory with the exact number of dummy cycles it
should expect. Both the memory and the (Q)SPI controller must agree on
this number of dummy cycles.

The number of dummy cycles can be found into the memory datasheet and
mostly depends on the SPI clock frequency, the Fast Read op code and the
Single/Dual Data Rate mode.

Probing JEDEC Serial Flash Discoverable Parameters (SFDP) tables would
only provide the driver with a high enough number of dummy cycles for each
Fast Read command to be used for all clock frequencies: this solution
would not be optimized.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 97 ++++++++++++++++++++++++++++++++++---------
 include/linux/mtd/spi-nor.h   |  2 +
 2 files changed, 80 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 93627d4e6be8..5df6e4712a9e 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -119,24 +119,6 @@ static int read_cr(struct spi_nor *nor)
 }
 
 /*
- * Dummy Cycle calculation for different type of read.
- * It can be used to support more commands with
- * different dummy cycle requirements.
- */
-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
-{
-	switch (nor->flash_read) {
-	case SPI_NOR_FAST:
-	case SPI_NOR_DUAL:
-	case SPI_NOR_QUAD:
-		return 8;
-	case SPI_NOR_NORMAL:
-		return 0;
-	}
-	return 0;
-}
-
-/*
  * Write status register 1 byte
  * Returns negative if error occurred.
  */
@@ -1007,6 +989,81 @@ static int set_quad_mode(struct spi_nor *nor, struct flash_info *info)
 	}
 }
 
+static int micron_set_dummy_cycles(struct spi_nor *nor)
+{
+	int ret;
+	u8 val, mask;
+
+	/* read the Volatile Configuration Register (VCR) */
+	ret = nor->read_reg(nor, SPINOR_OP_RD_VCR, &val, 1);
+	if (ret < 0) {
+		dev_err(nor->dev, "error %d reading VCR\n", ret);
+		return ret;
+	}
+
+	write_enable(nor);
+
+	/* update the number of dummy into the VCR */
+	mask = GENMASK(7, 4);
+	val &= ~mask;
+	val |= (nor->read_dummy << 4) & mask;
+	ret = nor->write_reg(nor, SPINOR_OP_WR_VCR, &val, 1, 0);
+	if (ret < 0) {
+		dev_err(nor->dev, "error while writing VCR register\n");
+		return ret;
+	}
+
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * Dummy Cycle calculation for different type of read.
+ * It can be used to support more commands with
+ * different dummy cycle requirements.
+ */
+static int spi_nor_read_dummy_cycles(struct spi_nor *nor,
+				     const struct flash_info *info)
+{
+	struct device_node *np = nor->dev->of_node;
+	u32 num_dummy_cycles;
+
+	if (np && !of_property_read_u32(np, "m25p,num-dummy-cycles",
+					&num_dummy_cycles)) {
+		nor->read_dummy = num_dummy_cycles;
+
+		/*
+		 * This switch block might be moved after the if...then...else
+		 * statement but it was not tested with all Spansion or Micron
+		 * memories.
+		 * Now the "m25p,num-dummy-cycles" property needs to be
+		 * explicitly set in the device tree so the switch statement is
+		 * executed. This should avoid unwanted side effects and keep
+		 * backward compatibility.
+		 */
+		switch (JEDEC_MFR(info)) {
+		case CFI_MFR_ST:
+			return micron_set_dummy_cycles(nor);
+		default:
+			break;
+		}
+	} else {
+		switch (nor->flash_read) {
+		case SPI_NOR_FAST:
+		case SPI_NOR_DUAL:
+		case SPI_NOR_QUAD:
+			nor->read_dummy = 8;
+		case SPI_NOR_NORMAL:
+			nor->read_dummy = 0;
+		}
+	}
+
+	return 0;
+}
+
 static int spi_nor_check(struct spi_nor *nor)
 {
 	if (!nor->dev || !nor->read || !nor->write ||
@@ -1211,7 +1268,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
 		nor->addr_width = 3;
 	}
 
-	nor->read_dummy = spi_nor_read_dummy_cycles(nor);
+	ret = spi_nor_read_dummy_cycles(nor, info);
+	if (ret)
+		return ret;
 
 	dev_info(dev, "%s (%lld Kbytes)\n", id->name,
 			(long long)mtd->size >> 10);
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 1bf6f11310ef..e03a4c4053d3 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -59,6 +59,8 @@
 /* Used for Micron flashes only. */
 #define SPINOR_OP_RD_EVCR      0x65    /* Read EVCR register */
 #define SPINOR_OP_WD_EVCR      0x61    /* Write EVCR register */
+#define SPINOR_OP_RD_VCR	0x85	/* Read VCR register */
+#define SPINOR_OP_WR_VCR	0x81	/* Write VCR register */
 
 /* Status Register bits. */
 #define SR_WIP			1	/* Write in progress */
-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web