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"