Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 Mar 2019 06:28:25 +0000 (UTC)
From:      Allan Jude <allanjude@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r345464 - head/sys/dev/cfi
Message-ID:  <201903240628.x2O6SPd0018980@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: allanjude
Date: Sun Mar 24 06:28:25 2019
New Revision: 345464
URL: https://svnweb.freebsd.org/changeset/base/345464

Log:
  Fix AMD type flash write operations, and display chip information at boot
  
  Applies to MX flash chips on AR9132 and RT3050
  
  Submitted by:	Hiroki Mori <yamori813@yahoo.co.jp>
  Reviewed by:	imp, sbruno
  Differential Revision:	https://reviews.freebsd.org/D14279

Modified:
  head/sys/dev/cfi/cfi_core.c
  head/sys/dev/cfi/cfi_reg.h
  head/sys/dev/cfi/cfi_var.h

Modified: head/sys/dev/cfi/cfi_core.c
==============================================================================
--- head/sys/dev/cfi/cfi_core.c	Sat Mar 23 23:44:40 2019	(r345463)
+++ head/sys/dev/cfi/cfi_core.c	Sun Mar 24 06:28:25 2019	(r345464)
@@ -421,6 +421,16 @@ cfi_attach(device_t dev) 
 		}
 	}
 
+	if (sc->sc_cmdset == CFI_VEND_AMD_ECS  ||
+	    sc->sc_cmdset == CFI_VEND_AMD_SCS) {
+		cfi_amd_write(sc, 0, AMD_ADDR_START, CFI_AMD_AUTO_SELECT);
+		sc->sc_manid = cfi_read(sc, 0);
+		sc->sc_devid = cfi_read(sc, 2);
+		device_printf(dev, "Manufacturer ID:%x Device ID:%x\n",
+		    sc->sc_manid, sc->sc_devid);
+		cfi_write(sc, 0, CFI_BCS_READ_ARRAY2);
+	}
+
 	u = device_get_unit(dev);
 	sc->sc_nod = make_dev(&cfi_cdevsw, u, UID_ROOT, GID_WHEEL, 0600,
 	    "%s%u", cfi_driver_name, u);
@@ -500,6 +510,37 @@ cfi_detach(device_t dev)
 	return (0);
 }
 
+static bool
+cfi_check_erase(struct cfi_softc *sc, u_int ofs, u_int sz)
+{
+	bool result;
+	int i;
+	uint32_t val;
+
+	result = FALSE;
+	for (i = 0; i < sz; i += sc->sc_width) {
+		val = cfi_read(sc, ofs + i);
+		switch (sc->sc_width) {
+		case 1:
+			if (val != 0xff)
+				goto out;
+			continue;
+		case 2:
+			if (val != 0xffff)
+				goto out;
+			continue;
+		case 4:
+			if (val != 0xffffffff)
+				goto out;
+			continue;
+		}
+	}
+	result = TRUE;
+
+out:
+	return (result);
+}
+
 static int
 cfi_wait_ready(struct cfi_softc *sc, u_int ofs, sbintime_t start,
     enum cfi_wait_cmd cmd)
@@ -581,10 +622,12 @@ cfi_write_block(struct cfi_softc *sc)
 		uint32_t	*x32;
 	} ptr, cpyprt;
 	register_t intr;
-	int error, i, neederase = 0;
+	int error, i, j, neederase = 0;
 	uint32_t st;
 	u_int wlen;
 	sbintime_t start;
+	u_int minsz;
+	uint32_t val;
 
 	/* Intel flash must be unlocked before modification */
 	switch (sc->sc_cmdset) {
@@ -615,9 +658,27 @@ cfi_write_block(struct cfi_softc *sc)
 			break;
 		case CFI_VEND_AMD_SCS:
 		case CFI_VEND_AMD_ECS:
+			/* find minimum sector size */
+			minsz = sc->sc_region[0].r_blksz;
+			for (i = 1; i < sc->sc_regions; i++) {
+				if (sc->sc_region[i].r_blksz < minsz)
+					minsz = sc->sc_region[i].r_blksz;
+			}
 			cfi_amd_write(sc, sc->sc_wrofs, AMD_ADDR_START,
 			    CFI_AMD_ERASE_SECTOR);
-			cfi_amd_write(sc, sc->sc_wrofs, 0, CFI_AMD_BLOCK_ERASE);
+			cfi_amd_write(sc, sc->sc_wrofs, 
+			    sc->sc_wrofs >> (ffs(minsz) - 1),
+			    CFI_AMD_BLOCK_ERASE);
+			for (i = 0; i < CFI_AMD_MAXCHK; ++i) {
+				if (cfi_check_erase(sc, sc->sc_wrofs,
+				    sc->sc_wrbufsz))
+					break;
+				DELAY(10);
+			}
+			if (i == CFI_AMD_MAXCHK) {
+				printf("\nCFI Sector Erase time out error\n");
+				return (ENODEV);
+			}
 			break;
 		default:
 			/* Better safe than sorry... */
@@ -749,10 +810,37 @@ cfi_write_block(struct cfi_softc *sc)
 		
 		intr_restore(intr);
 
-		error = cfi_wait_ready(sc, sc->sc_wrofs, start,
-		   CFI_TIMEOUT_WRITE);
-		if (error)
-			goto out;
+		if (sc->sc_cmdset == CFI_VEND_AMD_ECS  ||
+		    sc->sc_cmdset == CFI_VEND_AMD_SCS) {
+			for (j = 0; j < CFI_AMD_MAXCHK; ++j) {
+				switch (sc->sc_width) {
+				case 1:
+					val = *(ptr.x8 + i);
+					break;
+				case 2:
+					val = *(ptr.x16 + i / 2);
+					break;
+				case 4:
+					val = *(ptr.x32 + i / 4);
+					break;
+				}
+
+				if (cfi_read(sc, sc->sc_wrofs + i) == val)
+					break;
+					
+				DELAY(10);
+			}
+			if (j == CFI_AMD_MAXCHK) {
+				printf("\nCFI Program Verify time out error\n");
+				error = ENXIO;
+				goto out;
+			}
+		} else {
+			error = cfi_wait_ready(sc, sc->sc_wrofs, start,
+			   CFI_TIMEOUT_WRITE);
+			if (error)
+				goto out;
+		}
 	}
 
 	/* error is 0. */

Modified: head/sys/dev/cfi/cfi_reg.h
==============================================================================
--- head/sys/dev/cfi/cfi_reg.h	Sat Mar 23 23:44:40 2019	(r345463)
+++ head/sys/dev/cfi/cfi_reg.h	Sun Mar 24 06:28:25 2019	(r345464)
@@ -146,10 +146,13 @@ struct cfi_qry {
 #define	CFI_AMD_BLOCK_ERASE	0x30
 #define	CFI_AMD_UNLOCK_ACK	0x55
 #define	CFI_AMD_ERASE_SECTOR	0x80
+#define	CFI_AMD_AUTO_SELECT	0x90
 #define	CFI_AMD_PROGRAM		0xa0
 #define	CFI_AMD_UNLOCK		0xaa
 
 #define	AMD_ADDR_START		0xaaa
 #define	AMD_ADDR_ACK		0x555
+
+#define	CFI_AMD_MAXCHK		0x10000
 
 #endif /* _DEV_CFI_REG_H_ */

Modified: head/sys/dev/cfi/cfi_var.h
==============================================================================
--- head/sys/dev/cfi/cfi_var.h	Sat Mar 23 23:44:40 2019	(r345463)
+++ head/sys/dev/cfi/cfi_var.h	Sun Mar 24 06:28:25 2019	(r345464)
@@ -80,6 +80,9 @@ struct cfi_softc {
 	u_int		sc_wrbufsz;
 	u_int		sc_wrofs;
 	u_int		sc_writing;
+
+	u_int		sc_manid;
+	u_int		sc_devid;
 };
 
 extern char cfi_driver_name[];



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