Index: head/sys/dev/flash/mx25l.c =================================================================== --- head/sys/dev/flash/mx25l.c +++ head/sys/dev/flash/mx25l.c @@ -56,6 +56,8 @@ #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 @@ { "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 @@ 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 @@ 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 @@ 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_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 @@ 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 @@ } 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 @@ 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; Index: head/sys/dev/flash/mx25lreg.h =================================================================== --- head/sys/dev/flash/mx25lreg.h +++ head/sys/dev/flash/mx25lreg.h @@ -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