Index: mx25l.c =================================================================== --- mx25l.c (revision 210265) +++ mx25l.c (working copy) @@ -70,6 +70,10 @@ struct proc *sc_p; struct bio_queue_head sc_bio_queue; unsigned int sc_flags; + struct { + unsigned int size; + uint8_t cmd; + } sc_erase; }; #define M25PXX_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) @@ -208,6 +212,9 @@ err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd); } +/* + * Implement "replace" write - ie, erase/write + */ static int mx25l_write(device_t dev, off_t offset, caddr_t data, off_t count) { @@ -228,26 +235,14 @@ bytes_writen = 0; write_offset = offset; - /* - * Sanity checks - */ - KASSERT(count % sc->sc_sectorsize == 0, - ("count for BIO_WRITE is not sector size (%d bytes) aligned", - sc->sc_sectorsize)); + /* Minimum write size is (currently) minimum erase size */ + if ((count % sc->sc_erase.size != 0) || (offset % sc->sc_erase.size != 0)) + return EIO; + /* IO size for now must also be complete FLASH_PAGE_SIZE'd chunks too */ + if ((count % FLASH_PAGE_SIZE != 0) || (offset % FLASH_PAGE_SIZE != 0)) + return EIO; - KASSERT(offset % sc->sc_sectorsize == 0, - ("offset for BIO_WRITE is not sector size (%d bytes) aligned", - sc->sc_sectorsize)); - /* - * Assume here that we write per-sector only - * and sector size should be 256 bytes aligned - */ - KASSERT(write_offset % FLASH_PAGE_SIZE == 0, - ("offset for BIO_WRITE is not page size (%d bytes) aligned", - FLASH_PAGE_SIZE)); - - /* * Maximum write size for CMD_PAGE_PROGRAM is * FLASH_PAGE_SIZE, so split data to chunks * FLASH_PAGE_SIZE bytes eash and write them @@ -258,7 +253,7 @@ * If we crossed sector boundary - erase next sector */ if (((offset + bytes_writen) % sc->sc_sectorsize) == 0) - mx25l_erase_cmd(dev, offset + bytes_writen, CMD_SECTOR_ERASE); + mx25l_erase_cmd(dev, offset + bytes_writen, sc->sc_erase.cmd); txBuf[0] = CMD_PAGE_PROGRAM; txBuf[1] = ((write_offset >> 16) & 0xff); @@ -305,17 +300,6 @@ pdev = device_get_parent(dev); sc = device_get_softc(dev); - /* - * Sanity checks - */ - KASSERT(count % sc->sc_sectorsize == 0, - ("count for BIO_READ is not sector size (%d bytes) aligned", - sc->sc_sectorsize)); - - KASSERT(offset % sc->sc_sectorsize == 0, - ("offset for BIO_READ is not sector size (%d bytes) aligned", - sc->sc_sectorsize)); - txBuf[0] = CMD_FAST_READ; cmd.tx_cmd_sz = 5; cmd.rx_cmd_sz = 5; @@ -377,6 +361,18 @@ sc->sc_sectorsize = ident->sectorsize; sc->sc_flags = ident->flags; + /* Support 4k/32k erases if possible */ + if (ident->flags & FL_ERASE_4K) { + sc->sc_erase.size = 4096; + sc->sc_erase.cmd = CMD_BLOCK_4K_ERASE; + } else if (ident->flags & FL_ERASE_32K) { + sc->sc_erase.size = 32768; + sc->sc_erase.cmd = CMD_BLOCK_32K_ERASE; + } else { + sc->sc_erase.size = ident->sectorsize; + sc->sc_erase.cmd = CMD_SECTOR_ERASE; + } + /* NB: use stripesize to hold the erase/region size for RedBoot */ sc->sc_disk->d_stripesize = ident->sectorsize;