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