All of lore.kernel.org
 help / color / mirror / Atom feed
From: <mark.marshall@omicronenergy.com>
To: <computersforpeace@gmail.com>, <linux-mtd@lists.infradead.org>,
	<cyrille.pitchen@atmel.com>, <marek.vasut@gmail.com>
Cc: <markmarshall14@gmail.com>, <dwmw2@infradead.org>,
	<richard@nod.at>, <boris.brezillon@free-electrons.com>,
	Mark Marshall <mark.marshall@omicronenergy.com>
Subject: [PATCH v2 1/3] mtd: spi-nor: flash_info table, use a u64 for the ID
Date: Tue, 14 Feb 2017 16:35:51 +0100	[thread overview]
Message-ID: <04e48a3c19a8efb9e0d1d24bccf7b44a5a4b4ce8.1487085166.git.mark.marshall@omicronenergy.com> (raw)
In-Reply-To: <cover.1487085166.git.mark.marshall@omicronenergy.com>

From: Mark Marshall <mark.marshall@omicronenergy.com>

The flash_info ID matching table is getting more complex as different
chips are added.  Some chips require different amounts of the response
to the RDID command to be matched.  Replace the current u8 array and
length with a u64 id and a u64 id_mask.  This allows us to simplify the
macros used to generate the flash_info table without loosing the ability
to generate "unusual" entries.

Signed-off-by: Mark Marshall <mark.marshall@omicronenergy.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 119 ++++++++++++++++++++++--------------------
 1 file changed, 62 insertions(+), 57 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 1ae872b..ab3f380 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -41,15 +41,22 @@
 #define SPI_NOR_MAX_ADDR_WIDTH	4
 
 struct flash_info {
-	char		*name;
+	const char	*name;
 
 	/*
-	 * This array stores the ID bytes.
-	 * The first three bytes are the JEDIC ID.
-	 * JEDEC ID zero means "no ID" (mostly older chips).
+	 * This u64 stores the ID bytes.
+	 * The bytes are stored in big-endian order (that is, the
+	 * first byte of the RDID result is the MSB of the value.  The
+	 * u64 is stored in host endian).
+	 * The upper three bytes are the JEDEC ID, the lower bytes are
+	 * the extension.
 	 */
-	u8		id[SPI_NOR_MAX_ID_LEN];
-	u8		id_len;
+	u64		id;
+
+	/*
+	 * An id_mask of zero means "no ID" (mostly older chips).
+	 */
+	u64		id_mask;
 
 	/* The size listed here is what works with SPINOR_OP_SE, which isn't
 	 * necessarily called a "sector" by the vendor.
@@ -87,7 +94,7 @@ struct flash_info {
 					 */
 };
 
-#define JEDEC_MFR(info)	((info)->id[0])
+#define JEDEC_MFR(info)	((u8)((info)->id >> 56) & 0xff)
 
 static const struct flash_info *spi_nor_match_id(const char *name);
 
@@ -870,55 +877,49 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	return ret;
 }
 
+#define INFO_RAW(_id, _id_mask, _sector_size, _n_sectors, _page_size, _addr_width, _flags) \
+	.id = (_id),							\
+	.id_mask = (_id_mask),						\
+	.sector_size = (_sector_size),					\
+	.n_sectors = (_n_sectors),					\
+	.page_size = (_page_size),					\
+	.addr_width = (_addr_width),					\
+	.flags = (_flags),
+
 /* Used when the "_ext_id" is two bytes at most */
 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
-		.id = {							\
-			((_jedec_id) >> 16) & 0xff,			\
-			((_jedec_id) >> 8) & 0xff,			\
-			(_jedec_id) & 0xff,				\
-			((_ext_id) >> 8) & 0xff,			\
-			(_ext_id) & 0xff,				\
-			},						\
-		.id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),	\
-		.sector_size = (_sector_size),				\
-		.n_sectors = (_n_sectors),				\
-		.page_size = 256,					\
-		.flags = (_flags),
+	INFO_RAW(!(_jedec_id) ? 0 :					\
+		 (((u64)(_jedec_id) << (64 - (8 * 3))) |		\
+		  ((u64)(_ext_id) << (64 - (40)))),			\
+		 !(_jedec_id) ? 0 :					\
+		 GENMASK_ULL(63, 64 - (8 * (3 + ((_ext_id) ? 2 : 0)))),	\
+		 (_sector_size),					\
+		 (_n_sectors),						\
+		 256,							\
+		 0,							\
+		 (_flags))
 
 #define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
-		.id = {							\
-			((_jedec_id) >> 16) & 0xff,			\
-			((_jedec_id) >> 8) & 0xff,			\
-			(_jedec_id) & 0xff,				\
-			((_ext_id) >> 16) & 0xff,			\
-			((_ext_id) >> 8) & 0xff,			\
-			(_ext_id) & 0xff,				\
-			},						\
-		.id_len = 6,						\
-		.sector_size = (_sector_size),				\
-		.n_sectors = (_n_sectors),				\
-		.page_size = 256,					\
-		.flags = (_flags),
+	INFO_RAW((((u64)(_jedec_id) << (64 - (8 * 3))) |		\
+		  ((u64)(_ext_id) << (64 - (48)))),			\
+		 GENMASK_ULL(63, 64 - (8 * (3 + ((_ext_id) ? 3 : 0)))),	\
+		 (_sector_size),					\
+		 (_n_sectors),						\
+		 256,							\
+		 0,							\
+		 (_flags))
 
 #define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags)	\
-		.sector_size = (_sector_size),				\
-		.n_sectors = (_n_sectors),				\
-		.page_size = (_page_size),				\
-		.addr_width = (_addr_width),				\
-		.flags = (_flags),
+	INFO_RAW(0, 0, (_sector_size), (_n_sectors), (_page_size), (_addr_width), (_flags))
 
 #define S3AN_INFO(_jedec_id, _n_sectors, _page_size)			\
-		.id = {							\
-			((_jedec_id) >> 16) & 0xff,			\
-			((_jedec_id) >> 8) & 0xff,			\
-			(_jedec_id) & 0xff				\
-			},						\
-		.id_len = 3,						\
-		.sector_size = (8*_page_size),				\
-		.n_sectors = (_n_sectors),				\
-		.page_size = _page_size,				\
-		.addr_width = 3,					\
-		.flags = SPI_NOR_NO_FR | SPI_S3AN,
+	INFO_RAW((((u64)(_jedec_id) << (64 - (8 * 3)))),		\
+		 GENMASK_ULL(63, 64 - (8 * (3))),			\
+		 8 * (_page_size),					\
+		 (_n_sectors),						\
+		 (_page_size),						\
+		 3,							\
+		 SPI_NOR_NO_FR | SPI_S3AN)
 
 /* NOTE: double check command sets and memory organization when you add
  * more nor chips.  This current list focusses on newer chips, which
@@ -1170,24 +1171,28 @@ static const struct flash_info spi_nor_ids[] = {
 static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
 {
 	int			tmp;
-	u8			id[SPI_NOR_MAX_ID_LEN];
+	u8			id_bytes[sizeof(u64)];
+	u64			id;
 	const struct flash_info	*info;
 
-	tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
+	BUILD_BUG_ON(SPI_NOR_MAX_ID_LEN > sizeof(u64));
+
+	memset(id_bytes, 0, sizeof(id_bytes));
+	tmp = nor->read_reg(nor, SPINOR_OP_RDID, id_bytes, SPI_NOR_MAX_ID_LEN);
 	if (tmp < 0) {
 		dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp);
 		return ERR_PTR(tmp);
 	}
 
+	id = get_unaligned_be64(id_bytes);
+
 	for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {
 		info = &spi_nor_ids[tmp];
-		if (info->id_len) {
-			if (!memcmp(info->id, id, info->id_len))
-				return &spi_nor_ids[tmp];
-		}
+		if (info->id_mask && (id & info->id_mask) == info->id)
+			return info;
 	}
-	dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n",
-		id[0], id[1], id[2]);
+	dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
+		SPI_NOR_MAX_ID_LEN, id_bytes);
 	return ERR_PTR(-ENODEV);
 }
 
@@ -1551,7 +1556,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
 	 * If caller has specified name of flash model that can normally be
 	 * detected using JEDEC, let's verify it.
 	 */
-	if (name && info->id_len) {
+	if (name && info->id_mask) {
 		const struct flash_info *jinfo;
 
 		jinfo = spi_nor_read_id(nor);
-- 
2.7.4

  reply	other threads:[~2017-02-14 15:37 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-24 13:52 [PATCH] m25p80: Use a 512 byte page size for Spansion flash s25fl512s mark.marshall
2017-01-24 16:48 ` Marek Vasut
2017-01-26 14:58   ` Mark Marshall
2017-02-04 22:25     ` Marek Vasut
2017-02-13 13:53       ` [PATCH] mtd: spi-nor: flash_info table, use a u64 for the ID mark.marshall
2017-02-14  5:02         ` Marek Vasut
2017-02-14 10:22           ` Cyrille Pitchen
2017-02-14 15:35             ` [PATCH v2 0/3] " mark.marshall
2017-02-14 15:35               ` mark.marshall [this message]
2017-02-14 15:35               ` [PATCH v2 2/3] mtd: spi-nor: Use more explicit macros to generate the flash_info table mark.marshall
2017-02-14 15:35               ` [PATCH v2 3/3] mtd: spi-nor: s25fl512s: Set a page size of 512 mark.marshall
2017-08-01 16:49                 ` 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=04e48a3c19a8efb9e0d1d24bccf7b44a5a4b4ce8.1487085166.git.mark.marshall@omicronenergy.com \
    --to=mark.marshall@omicronenergy.com \
    --cc=boris.brezillon@free-electrons.com \
    --cc=computersforpeace@gmail.com \
    --cc=cyrille.pitchen@atmel.com \
    --cc=dwmw2@infradead.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=marek.vasut@gmail.com \
    --cc=markmarshall14@gmail.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 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.