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
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to