linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
To: <computersforpeace@gmail.com>, <marek.vasut@gmail.com>,
	<boris.brezillon@free-electrons.com>, <richard@nod.at>,
	<linux-mtd@lists.infradead.org>
Cc: <nicolas.ferre@atmel.com>, <linux-kernel@vger.kernel.org>,
	Cyrille Pitchen <cyrille.pitchen@atmel.com>
Subject: [PATCH v4 3/8] mtd: spi-nor: add an alternative method to support memory >16MiB
Date: Mon, 21 Nov 2016 15:15:42 +0100	[thread overview]
Message-ID: <a68a828dc44952f0533c573af21d45f24d0ca65c.1479736401.git.cyrille.pitchen@atmel.com> (raw)
In-Reply-To: <cover.1479736401.git.cyrille.pitchen@atmel.com>

This patch provides an alternative mean to support memory above 16MiB
(128Mib) by replacing 3byte address op codes by their associated 4byte
address versions.

Using the dedicated 4byte address op codes doesn't change the internal
state of the SPI NOR memory as opposed to using other means such as
updating a Base Address Register (BAR) and sending command to enter/leave
the 4byte mode.

Hence when a CPU reset occurs, early bootloaders don't need to be aware
of BAR value or 4byte mode being enabled: they can still access the first
16MiB of the SPI NOR memory using the regular 3byte address op codes.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Tested-by: Vignesh R <vigneshr@ti.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 114 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 93 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 8a190122b13f..fd39516fef35 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -75,6 +75,10 @@ struct flash_info {
 					 * bit. Must be used with
 					 * SPI_NOR_HAS_LOCK.
 					 */
+#define SPI_NOR_4B_OPCODES	BIT(10)	/*
+					 * Use dedicated 4byte address op codes
+					 * to support memory size above 128Mib.
+					 */
 };
 
 #define JEDEC_MFR(info)	((info)->id[0])
@@ -188,6 +192,91 @@ static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
 	return mtd->priv;
 }
 
+
+struct spi_nor_address_entry {
+	u8	src_opcode;
+	u8	dst_opcode;
+};
+
+static u8 spi_nor_convert_opcode(u8 opcode,
+				 const struct spi_nor_address_entry *entries,
+				 size_t num_entries)
+{
+	int min, max;
+
+	/*
+	 * This function implements a dichotomic search in the entries[]
+	 * array indexed by src_opcode. Hence we assume that the entries[]
+	 * array is sorted by src_opcode.
+	 * The dichotomic search has a logarithmic complexity as opposed
+	 * to a simple loop on all entires, which has a linear complexity:
+	 * it means that when n is the number of entries in the input array,
+	 * the dichotomic search performs O(log2(n)) comparisons whereas
+	 * a simple loop performs O(n) comparisons.
+	 */
+	min = 0;
+	max = num_entries - 1;
+	while (min <= max) {
+		int mid = (min + max) >> 1;
+		const struct spi_nor_address_entry *entry = &entries[mid];
+
+		if (opcode == entry->src_opcode)
+			return entry->dst_opcode;
+
+		if (opcode < entry->src_opcode)
+			max = mid - 1;
+		else
+			min = mid + 1;
+	}
+
+	/* No conversion found */
+	return opcode;
+}
+
+static u8 spi_nor_3to4_opcode(u8 opcode)
+{
+	/* MUST be sorted by 3byte opcode (cf spi_nor_convert_opcode). */
+#define ENTRY_3TO4(_opcode)	{ _opcode, _opcode##_4B }
+	static const struct spi_nor_address_entry spi_nor_3to4_table[] = {
+		ENTRY_3TO4(SPINOR_OP_PP),		/* 0x02 */
+		ENTRY_3TO4(SPINOR_OP_READ),		/* 0x03 */
+		ENTRY_3TO4(SPINOR_OP_READ_FAST),	/* 0x0b */
+		ENTRY_3TO4(SPINOR_OP_BE_4K),		/* 0x20 */
+		ENTRY_3TO4(SPINOR_OP_PP_1_1_4),		/* 0x32 */
+		ENTRY_3TO4(SPINOR_OP_PP_1_4_4),		/* 0x38 */
+		ENTRY_3TO4(SPINOR_OP_READ_1_1_2),	/* 0x3b */
+		ENTRY_3TO4(SPINOR_OP_BE_32K),		/* 0x52 */
+		ENTRY_3TO4(SPINOR_OP_READ_1_1_4),	/* 0x6b */
+		ENTRY_3TO4(SPINOR_OP_READ_1_2_2),	/* 0xbb */
+		ENTRY_3TO4(SPINOR_OP_SE),		/* 0xd8 */
+		ENTRY_3TO4(SPINOR_OP_READ_1_4_4),	/* 0xeb */
+	};
+#undef ENTRY_3TO4
+
+	return spi_nor_convert_opcode(opcode, spi_nor_3to4_table,
+				      ARRAY_SIZE(spi_nor_3to4_table));
+}
+
+static void spi_nor_set_4byte_opcodes(struct spi_nor *nor,
+				      const struct flash_info *info)
+{
+	/* Do some manufacturer fixups first */
+	switch (JEDEC_MFR(info)) {
+	case SNOR_MFR_SPANSION:
+		/* No small sector erase for 4-byte command set */
+		nor->erase_opcode = SPINOR_OP_SE;
+		nor->mtd.erasesize = info->sector_size;
+		break;
+
+	default:
+		break;
+	}
+
+	nor->read_opcode	= spi_nor_3to4_opcode(nor->read_opcode);
+	nor->program_opcode	= spi_nor_3to4_opcode(nor->program_opcode);
+	nor->erase_opcode	= spi_nor_3to4_opcode(nor->erase_opcode);
+}
+
 /* Enable/disable 4-byte addressing mode. */
 static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info,
 			    int enable)
@@ -1476,27 +1565,10 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
 	else if (mtd->size > 0x1000000) {
 		/* enable 4-byte addressing if the device exceeds 16MiB */
 		nor->addr_width = 4;
-		if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) {
-			/* Dedicated 4-byte command set */
-			switch (nor->flash_read) {
-			case SPI_NOR_QUAD:
-				nor->read_opcode = SPINOR_OP_READ_1_1_4_4B;
-				break;
-			case SPI_NOR_DUAL:
-				nor->read_opcode = SPINOR_OP_READ_1_1_2_4B;
-				break;
-			case SPI_NOR_FAST:
-				nor->read_opcode = SPINOR_OP_READ_FAST_4B;
-				break;
-			case SPI_NOR_NORMAL:
-				nor->read_opcode = SPINOR_OP_READ_4B;
-				break;
-			}
-			nor->program_opcode = SPINOR_OP_PP_4B;
-			/* No small sector erase for 4-byte command set */
-			nor->erase_opcode = SPINOR_OP_SE_4B;
-			mtd->erasesize = info->sector_size;
-		} else
+		if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
+		    info->flags & SPI_NOR_4B_OPCODES)
+			spi_nor_set_4byte_opcodes(nor, info);
+		else
 			set_4byte(nor, info, 1);
 	} else {
 		nor->addr_width = 3;
-- 
2.7.4

  parent reply	other threads:[~2016-11-21 14:17 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-21 14:15 [PATCH v4 0/8] mtd: spi-nor: parse SFDP tables to setup (Q)SPI memories Cyrille Pitchen
2016-11-21 14:15 ` [PATCH v4 1/8] mtd: spi-nor: improve macronix_quad_enable() Cyrille Pitchen
2016-11-21 14:15 ` [PATCH v4 2/8] mtd: spi-nor: rename SPINOR_OP_* macros of the 4-byte address op codes Cyrille Pitchen
2016-11-21 14:15 ` Cyrille Pitchen [this message]
2016-11-21 14:15 ` [PATCH v4 4/8] mtd: spi-nor: add support of SPI protocols like SPI 1-2-2 and SPI 1-4-4 Cyrille Pitchen
2016-12-13  9:46   ` Krzeminski, Marcin (Nokia - PL/Wroclaw)
2016-12-16 13:47     ` Krzeminski, Marcin (Nokia - PL/Wroclaw)
2016-12-19 17:00       ` Cyrille Pitchen
2016-12-20 19:41         ` Odp.: " Krzeminski, Marcin (Nokia - PL/Wroclaw)
2016-12-19 16:38     ` Cyrille Pitchen
2016-12-20 19:36       ` Odp.: " Krzeminski, Marcin (Nokia - PL/Wroclaw)
2016-11-21 14:15 ` [PATCH v4 5/8] mtd: spi-nor: remove unused set_quad_mode() function Cyrille Pitchen
2016-11-21 14:15 ` [PATCH v4 6/8] mtd: m25p80: add support of dual and quad spi protocols to all commands Cyrille Pitchen
2016-11-21 14:15 ` [PATCH v4 7/8] mtd: spi-nor: parse Serial Flash Discoverable Parameters (SFDP) tables Cyrille Pitchen
2016-11-21 14:15 ` [PATCH v4 8/8] mtd: spi-nor: parse SFDP 4-byte Address Instruction Table Cyrille Pitchen
2016-12-13  9:46 ` [PATCH v4 0/8] mtd: spi-nor: parse SFDP tables to setup (Q)SPI memories Krzeminski, Marcin (Nokia - PL/Wroclaw)
2016-12-20 16:42   ` Cyrille Pitchen
2016-12-20 19:51     ` Odp.: " Krzeminski, Marcin (Nokia - PL/Wroclaw)

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=a68a828dc44952f0533c573af21d45f24d0ca65c.1479736401.git.cyrille.pitchen@atmel.com \
    --to=cyrille.pitchen@atmel.com \
    --cc=boris.brezillon@free-electrons.com \
    --cc=computersforpeace@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=marek.vasut@gmail.com \
    --cc=nicolas.ferre@atmel.com \
    --cc=richard@nod.at \
    /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 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).