Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Feb 2019 16:20:58 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r344523 - head/sys/dev/flash
Message-ID:  <201902251620.x1PGKwnP049710@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Mon Feb 25 16:20:58 2019
New Revision: 344523
URL: https://svnweb.freebsd.org/changeset/base/344523

Log:
  Include the jedec "extended device information string" in the criteria used
  to match a chip to our table of metadata describing the chips. At least one
  new DataFlash chip has a 3-byte jedec ID identical to its predecessors and
  differs only in the extended info, and it has different metadata requiring a
  unique entry in the table.  This paves the way for supporting such chips.
  
  The metadata table now includes two new fields, extmask and extid.  The two
  bytes of extended info obtained from the chip are ANDed with extmask then
  compared to extid, so it's possible to use only a subset of the extended
  info in the matching.
  
  We now always read 6 bytes of jedec ID info. Most chips don't return any
  extended info, and the values read back for those two bytes may be
  indeterminate, but such chips have extmask and extid values of 0x0000 in the
  table, so the extid effectively doesn't participate in the matching on those
  chips and it doesn't matter what they return in the extended info bytes.

Modified:
  head/sys/dev/flash/at45d.c

Modified: head/sys/dev/flash/at45d.c
==============================================================================
--- head/sys/dev/flash/at45d.c	Mon Feb 25 15:51:31 2019	(r344522)
+++ head/sys/dev/flash/at45d.c	Mon Feb 25 16:20:58 2019	(r344523)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/bio.h>
 #include <sys/bus.h>
 #include <sys/conf.h>
+#include <sys/endian.h>
 #include <sys/kernel.h>
 #include <sys/kthread.h>
 #include <sys/lock.h>
@@ -62,10 +63,22 @@ static struct ofw_compat_data compat_data[] = {
 SPIBUS_PNP_INFO(compat_data);
 #endif
 
+/* This is the information returned by the MANUFACTURER_ID command. */
+struct at45d_mfg_info {
+	uint32_t	jedec_id; /* Mfg ID, DevId1, DevId2, ExtLen */
+	uint16_t	ext_id;   /* ExtId1, ExtId2 */
+};
+
+/*
+ * This is an entry in our table of metadata describing the chips.  We match on
+ * both jedec id and extended id info returned by the MANUFACTURER_ID command.
+ */
 struct at45d_flash_ident
 {
 	const char	*name;
 	uint32_t	jedec;
+	uint16_t	extid;
+	uint16_t	extmask;
 	uint16_t	pagecount;
 	uint16_t	pageoffset;
 	uint16_t	pagesize;
@@ -111,7 +124,7 @@ static void at45d_task(void *arg);
 
 /* helper routines */
 static void at45d_delayed_attach(void *xsc);
-static int at45d_get_mfg_info(device_t dev, uint8_t *resp);
+static int at45d_get_mfg_info(device_t dev, struct at45d_mfg_info *resp);
 static int at45d_get_status(device_t dev, uint8_t *status);
 static int at45d_wait_ready(device_t dev, uint8_t *status);
 
@@ -123,19 +136,28 @@ static int at45d_wait_ready(device_t dev, uint8_t *sta
 #define	CONTINUOUS_ARRAY_READ		0xe8
 
 /*
+ * Metadata for supported chips.
+ *
+ * The jedec id in this table includes the extended id length byte.  A match is
+ * based on both jedec id and extended id matching.  The chip's extended id (not
+ * present in most chips) is ANDed with ExtMask and the result is compared to
+ * ExtId.  If a chip only returns 1 ext id byte it will be in the upper 8 bits
+ * of ExtId in this table.
+ *
  * A sectorsize2n != 0 is used to indicate that a device optionally supports
  * 2^N byte pages.  If support for the latter is enabled, the sector offset
  * has to be reduced by one.
  */
 static const struct at45d_flash_ident at45d_flash_devices[] = {
-	{ "AT45DB011B", 0x1f2200, 512, 9, 264, 256 },
-	{ "AT45DB021B", 0x1f2300, 1024, 9, 264, 256 },
-	{ "AT45DB041x", 0x1f2400, 2028, 9, 264, 256 },
-	{ "AT45DB081B", 0x1f2500, 4096, 9, 264, 256 },
-	{ "AT45DB161x", 0x1f2600, 4096, 10, 528, 512 },
-	{ "AT45DB321x", 0x1f2700, 8192, 10, 528, 0 },
-	{ "AT45DB321x", 0x1f2701, 8192, 10, 528, 512 },
-	{ "AT45DB642x", 0x1f2800, 8192, 11, 1056, 1024 }
+	/* Part Name    Jedec ID    ExtId   ExtMask PgCnt Offs PgSz PgSz2n */
+	{ "AT45DB011B", 0x1f220000, 0x0000, 0x0000,   512,  9,  264,  256 },
+	{ "AT45DB021B", 0x1f230000, 0x0000, 0x0000,  1024,  9,  264,  256 },
+	{ "AT45DB041x", 0x1f240000, 0x0000, 0x0000,  2028,  9,  264,  256 },
+	{ "AT45DB081B", 0x1f250000, 0x0000, 0x0000,  4096,  9,  264,  256 },
+	{ "AT45DB161x", 0x1f260000, 0x0000, 0x0000,  4096, 10,  528,  512 },
+	{ "AT45DB321x", 0x1f270000, 0x0000, 0x0000,  8192, 10,  528,    0 },
+	{ "AT45DB321x", 0x1f270100, 0x0000, 0x0000,  8192, 10,  528,  512 },
+	{ "AT45DB642x", 0x1f280000, 0x0000, 0x0000,  8192, 11, 1056, 1024 },
 };
 
 static int
@@ -159,7 +181,7 @@ at45d_get_status(device_t dev, uint8_t *status)
 }
 
 static int
-at45d_get_mfg_info(device_t dev, uint8_t *resp)
+at45d_get_mfg_info(device_t dev, struct at45d_mfg_info *resp)
 {
 	uint8_t rxBuf[8], txBuf[8];
 	struct spi_command cmd;
@@ -172,11 +194,14 @@ at45d_get_mfg_info(device_t dev, uint8_t *resp)
 	txBuf[0] = MANUFACTURER_ID;
 	cmd.tx_cmd = &txBuf;
 	cmd.rx_cmd = &rxBuf;
-	cmd.tx_cmd_sz = cmd.rx_cmd_sz = 5;
+	cmd.tx_cmd_sz = cmd.rx_cmd_sz = 7;
 	err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd);
 	if (err)
 		return (err);
-	memcpy(resp, rxBuf + 1, 4);
+
+	resp->jedec_id = be32dec(rxBuf + 1);
+	resp->ext_id   = be16dec(rxBuf + 5);
+
 	return (0);
 }
 
@@ -268,11 +293,12 @@ static void
 at45d_delayed_attach(void *xsc)
 {
 	struct at45d_softc *sc;
+	struct at45d_mfg_info mfginfo;
 	const struct at45d_flash_ident *ident;
 	u_int i;
 	uint32_t jedec;
 	uint16_t pagesize;
-	uint8_t buf[4], status;
+	uint8_t status;
 
 	sc = xsc;
 	ident = NULL;
@@ -282,19 +308,18 @@ at45d_delayed_attach(void *xsc)
 		device_printf(sc->dev, "Error waiting for device-ready.\n");
 		return;
 	}
-	if (at45d_get_mfg_info(sc->dev, buf) != 0) {
+	if (at45d_get_mfg_info(sc->dev, &mfginfo) != 0) {
 		device_printf(sc->dev, "Failed to get ID.\n");
 		return;
 	}
-
-	jedec = buf[0] << 16 | buf[1] << 8 | buf[2];
 	for (i = 0; i < nitems(at45d_flash_devices); i++) {
-		if (at45d_flash_devices[i].jedec == jedec) {
-			ident = &at45d_flash_devices[i];
+		ident = &at45d_flash_devices[i];
+		if (mfginfo.jedec_id == ident->jedec && 
+		    (mfginfo.ext_id & ident->extmask) == ident->extid) {
 			break;
 		}
 	}
-	if (ident == NULL) {
+	if (i == nitems(at45d_flash_devices)) {
 		device_printf(sc->dev, "JEDEC 0x%x not in list.\n", jedec);
 		return;
 	}
@@ -322,8 +347,9 @@ at45d_delayed_attach(void *xsc)
 	bioq_init(&sc->bio_queue);
 	kproc_create(&at45d_task, sc, &sc->p, 0, 0, "task: at45d flash");
 	sc->taskstate = TSTATE_RUNNING;
-	device_printf(sc->dev, "%s, %d bytes per page, %d pages\n",
-	    ident->name, pagesize, ident->pagecount);
+	device_printf(sc->dev, "%s, %d bytes per page, %d pages; %d KBytes\n",
+	    ident->name, pagesize, ident->pagecount,
+	    (pagesize * ident->pagecount) / 1024);
 }
 
 static int



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201902251620.x1PGKwnP049710>