svn commit: r297534 - head/sys/dev/flash

Stanislav Galabov sgalabov at FreeBSD.org
Mon Apr 4 06:55:50 UTC 2016


Author: sgalabov
Date: Mon Apr  4 06:55:48 2016
New Revision: 297534
URL: https://svnweb.freebsd.org/changeset/base/297534

Log:
  Enable 4-byte address support for the mx25l family of SPI flash devices.
  
  Introduce 2 new flags:
  - FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
  - FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
  
  If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
  then an 'Enter 4-byte mode' command is sent to the chip at attach time
  and, later, all commands that require addressing are issued with 4-byte
  addresses.
  If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
  then an 'Exit 4-byte mode' command is sent to the chip at attach time
  and, later, all commands that require addressing are issued with 3-byte
  addresses.
  For chips that do not have any of these flags defined the behaviour is
  unchanged.
  
  This change also adds support for the MX25L25735F and MX25L25635E chips
  (vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
  4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
  only be fully addressed by using 4-byte addresses.
  
  Approved by:	adrian (mentor)
  Sponsored by:	Smartcom - Bulgaria AD
  Differential Revision:	https://reviews.freebsd.org/D5808

Modified:
  head/sys/dev/flash/mx25l.c
  head/sys/dev/flash/mx25lreg.h

Modified: head/sys/dev/flash/mx25l.c
==============================================================================
--- head/sys/dev/flash/mx25l.c	Mon Apr  4 06:49:20 2016	(r297533)
+++ head/sys/dev/flash/mx25l.c	Mon Apr  4 06:55:48 2016	(r297534)
@@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$");
 #define	FL_NONE			0x00
 #define	FL_ERASE_4K		0x01
 #define	FL_ERASE_32K		0x02
+#define	FL_ENABLE_4B_ADDR	0x04
+#define	FL_DISABLE_4B_ADDR	0x08
 
 /*
  * Define the sectorsize to be a smaller size rather than the flash
@@ -113,6 +115,7 @@ struct mx25l_flash_ident flash_devices[]
 	{ "mx25ll32",	0xc2, 0x2016, 64 * 1024, 64, FL_NONE },
 	{ "mx25ll64",	0xc2, 0x2017, 64 * 1024, 128, FL_NONE },
 	{ "mx25ll128",	0xc2, 0x2018, 64 * 1024, 256, FL_ERASE_4K | FL_ERASE_32K },
+	{ "mx25ll256",	0xc2, 0x2019, 64 * 1024, 512, FL_ERASE_4K | FL_ERASE_32K | FL_ENABLE_4B_ADDR },
 	{ "s25fl032",	0x01, 0x0215, 64 * 1024, 64, FL_NONE },
 	{ "s25fl064",	0x01, 0x0216, 64 * 1024, 128, FL_NONE },
 	{ "s25fl128",	0x01, 0x2018, 64 * 1024, 256, FL_NONE },
@@ -219,10 +222,13 @@ mx25l_set_writable(device_t dev, int wri
 static void
 mx25l_erase_cmd(device_t dev, off_t sector, uint8_t ecmd)
 {
-	uint8_t txBuf[4], rxBuf[4];
+	struct mx25l_softc *sc;
+	uint8_t txBuf[5], rxBuf[5];
 	struct spi_command cmd;
 	int err;
 
+	sc = device_get_softc(dev);
+
 	mx25l_wait_for_device_ready(dev);
 	mx25l_set_writable(dev, 1);
 
@@ -233,11 +239,20 @@ mx25l_erase_cmd(device_t dev, off_t sect
 	txBuf[0] = ecmd;
 	cmd.tx_cmd = txBuf;
 	cmd.rx_cmd = rxBuf;
-	cmd.rx_cmd_sz = 4;
-	cmd.tx_cmd_sz = 4;
-	txBuf[1] = ((sector >> 16) & 0xff);
-	txBuf[2] = ((sector >> 8) & 0xff);
-	txBuf[3] = (sector & 0xff);
+	if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
+		cmd.rx_cmd_sz = 5;
+		cmd.tx_cmd_sz = 5;
+		txBuf[1] = ((sector >> 24) & 0xff);
+		txBuf[2] = ((sector >> 16) & 0xff);
+		txBuf[3] = ((sector >> 8) & 0xff);
+		txBuf[4] = (sector & 0xff);
+	} else {
+		cmd.rx_cmd_sz = 4;
+		cmd.tx_cmd_sz = 4;
+		txBuf[1] = ((sector >> 16) & 0xff);
+		txBuf[2] = ((sector >> 8) & 0xff);
+		txBuf[3] = (sector & 0xff);
+	}
 	err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd);
 }
 
@@ -255,8 +270,13 @@ mx25l_write(device_t dev, off_t offset, 
 	pdev = device_get_parent(dev);
 	sc = device_get_softc(dev);
 
-	cmd.tx_cmd_sz = 4;
-	cmd.rx_cmd_sz = 4;
+	if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
+		cmd.tx_cmd_sz = 5;
+		cmd.rx_cmd_sz = 5;
+	} else {
+		cmd.tx_cmd_sz = 4;
+		cmd.rx_cmd_sz = 4;
+	}
 
 	bytes_writen = 0;
 	write_offset = offset;
@@ -290,9 +310,16 @@ mx25l_write(device_t dev, off_t offset, 
 			mx25l_erase_cmd(dev, offset + bytes_writen, CMD_SECTOR_ERASE);
 
 		txBuf[0] = CMD_PAGE_PROGRAM;
-		txBuf[1] = ((write_offset >> 16) & 0xff);
-		txBuf[2] = ((write_offset >> 8) & 0xff);
-		txBuf[3] = (write_offset & 0xff);
+		if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
+			txBuf[1] = ((write_offset >> 24) & 0xff);
+			txBuf[2] = ((write_offset >> 16) & 0xff);
+			txBuf[3] = ((write_offset >> 8) & 0xff);
+			txBuf[4] = (write_offset & 0xff);
+		} else {
+			txBuf[1] = ((write_offset >> 16) & 0xff);
+			txBuf[2] = ((write_offset >> 8) & 0xff);
+			txBuf[3] = (write_offset & 0xff);
+		}
 
 		bytes_to_write = MIN(FLASH_PAGE_SIZE,
 		    count - bytes_writen);
@@ -344,14 +371,26 @@ mx25l_read(device_t dev, off_t offset, c
 		return (EIO);
 
 	txBuf[0] = CMD_FAST_READ;
-	cmd.tx_cmd_sz = 5;
-	cmd.rx_cmd_sz = 5;
-
-	txBuf[1] = ((offset >> 16) & 0xff);
-	txBuf[2] = ((offset >> 8) & 0xff);
-	txBuf[3] = (offset & 0xff);
-	/* Dummy byte */
-	txBuf[4] = 0;
+	if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
+		cmd.tx_cmd_sz = 6;
+		cmd.rx_cmd_sz = 6;
+
+		txBuf[1] = ((offset >> 24) & 0xff);
+		txBuf[2] = ((offset >> 16) & 0xff);
+		txBuf[3] = ((offset >> 8) & 0xff);
+		txBuf[4] = (offset & 0xff);
+		/* Dummy byte */
+		txBuf[5] = 0;
+	} else {
+		cmd.tx_cmd_sz = 5;
+		cmd.rx_cmd_sz = 5;
+
+		txBuf[1] = ((offset >> 16) & 0xff);
+		txBuf[2] = ((offset >> 8) & 0xff);
+		txBuf[3] = (offset & 0xff);
+		/* Dummy byte */
+		txBuf[4] = 0;
+	}
 
 	cmd.tx_cmd = txBuf;
 	cmd.rx_cmd = rxBuf;
@@ -366,6 +405,34 @@ mx25l_read(device_t dev, off_t offset, c
 }
 
 static int
+mx25l_set_4b_mode(device_t dev, uint8_t command)
+{
+	uint8_t txBuf[1], rxBuf[1];
+	struct spi_command cmd;
+	device_t pdev;
+	int err;
+
+	memset(&cmd, 0, sizeof(cmd));
+	memset(txBuf, 0, sizeof(txBuf));
+	memset(rxBuf, 0, sizeof(rxBuf));
+
+	pdev = device_get_parent(dev);
+
+	cmd.tx_cmd_sz = cmd.rx_cmd_sz = 1;
+
+	cmd.tx_cmd = txBuf;
+	cmd.rx_cmd = rxBuf;
+
+	txBuf[0] = command;
+
+	err = SPIBUS_TRANSFER(pdev, dev, &cmd);
+
+	mx25l_wait_for_device_ready(dev);
+
+	return (err);
+}
+
+static int
 mx25l_probe(device_t dev)
 {
 
@@ -413,6 +480,12 @@ mx25l_attach(device_t dev)
 	sc->sc_sectorsize =  ident->sectorsize;
 	sc->sc_flags = ident->flags;
 
+	if (sc->sc_flags & FL_ENABLE_4B_ADDR)
+		mx25l_set_4b_mode(dev, CMD_ENTER_4B_MODE);
+
+	if (sc->sc_flags & FL_DISABLE_4B_ADDR)
+		mx25l_set_4b_mode(dev, CMD_EXIT_4B_MODE);
+
         /* NB: use stripesize to hold the erase/region size for RedBoot */
 	sc->sc_disk->d_stripesize = ident->sectorsize;
 

Modified: head/sys/dev/flash/mx25lreg.h
==============================================================================
--- head/sys/dev/flash/mx25lreg.h	Mon Apr  4 06:49:20 2016	(r297533)
+++ head/sys/dev/flash/mx25lreg.h	Mon Apr  4 06:55:48 2016	(r297534)
@@ -45,6 +45,8 @@
 #define CMD_BULK_ERASE		0xC7
 #define	CMD_BLOCK_4K_ERASE	0x20
 #define	CMD_BLOCK_32K_ERASE	0x52
+#define	CMD_ENTER_4B_MODE	0xB7
+#define	CMD_EXIT_4B_MODE	0xE9
 
 /*
  * Status register flags


More information about the svn-src-head mailing list