From owner-freebsd-mips@FreeBSD.ORG Mon Oct 26 05:34:08 2009 Return-Path: Delivered-To: freebsd-mips@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 77623106568F; Mon, 26 Oct 2009 05:34:08 +0000 (UTC) (envelope-from awmdpt@gmail.com) Received: from mail-pw0-f44.google.com (mail-pw0-f44.google.com [209.85.160.44]) by mx1.freebsd.org (Postfix) with ESMTP id 3E4418FC0A; Mon, 26 Oct 2009 05:34:08 +0000 (UTC) Received: by pwj8 with SMTP id 8so1242023pwj.3 for ; Sun, 25 Oct 2009 22:34:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:sender:subject:from:to:cc :in-reply-to:references:content-type:date:message-id:mime-version :x-mailer; bh=42GbnDnJhsCvPQacvC8ml/ZwkpvYA48vUdTxfNmyVvQ=; b=exeqYs31EmFS3CcyNhpuiWKLIZv53SIB7GFl8m0Nf3Ud1KRwmA422iEVQDzPdVC/8Z F4tPNSv9CSfFHr8/irTsxaMTLCQ2T21nNJ9CILMlVqv51pnRkCCfYMIlJmNTqEETQM58 Wkgch2X8Nyy8ggPfUJeYZiBcHJ/LAhlOqhg/4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:subject:from:to:cc:in-reply-to:references:content-type:date :message-id:mime-version:x-mailer; b=nxJcijCx6svCzwjolStSUyMKZYSsKwtzWohWaW1OkF8u5vTXt6hRa/5Q3bZsppBQf3 cWnTrsUk/e7LjUgcTowBq8VI/5uRiJonnZLIwLeDQ8Uq1/CTe+p+cE+ZF4PoOXZMUeA/ buy0eB00P4AfRZHe4cGXMrCxuxlvqb04bn2Hc= Received: by 10.115.80.18 with SMTP id h18mr9474565wal.53.1256535247591; Sun, 25 Oct 2009 22:34:07 -0700 (PDT) Received: from ?192.168.10.117? (114-33-76-31.HINET-IP.hinet.net [114.33.76.31]) by mx.google.com with ESMTPS id 23sm628090pzk.8.2009.10.25.22.34.05 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sun, 25 Oct 2009 22:34:06 -0700 (PDT) Sender: Eric From: Eric To: Andrew Thompson In-Reply-To: <20091026051144.GA89831@citylink.fud.org.nz> References: <1256528272.31398.28.camel@localhost> <20091026051144.GA89831@citylink.fud.org.nz> Content-Type: multipart/mixed; boundary="=-Fe4tX8B/oIcPcwY9d+af" Date: Mon, 26 Oct 2009 13:34:02 +0800 Message-ID: <1256535242.31398.32.camel@localhost> Mime-Version: 1.0 X-Mailer: Evolution 2.28.1 FreeBSD GNOME Team Port Cc: gonzo@FreeBSD.org, freebsd-mips@FreeBSD.org Subject: Re: Add Wistron RPAA-82 board support X-BeenThere: freebsd-mips@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Porting FreeBSD to MIPS List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 26 Oct 2009 05:34:08 -0000 --=-Fe4tX8B/oIcPcwY9d+af Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit On Mon, 2009-10-26 at 18:11 +1300, Andrew Thompson wrote: > On Mon, Oct 26, 2009 at 11:37:52AM +0800, Eric wrote: > > Hi > > I added my ar7161 board support last weekend. > > It's flash is come from Spansion. > > This is great. Oleksandr has also just added write support which will > conflict/duplicate some of your changes so have a look and merge any > outstanding changes you have made (s25fl128 support). > > http://svn.freebsd.org/viewvc/base?view=revision&revision=198465 > > cheers, > Andrew At first, I have my own write support, then I saw hit commit today. So this patch already merged his commit. -- Best Regards, Eric L. Chen --=-Fe4tX8B/oIcPcwY9d+af Content-Disposition: attachment; filename="patch-mips-spiflash.diff" Content-Type: text/x-patch; name="patch-mips-spiflash.diff"; charset="UTF-8" Content-Transfer-Encoding: 7bit Index: src-mips/sys/dev/flash/mx25l.c =================================================================== --- src-mips/sys/dev/flash/mx25l.c (revision 198476) +++ src-mips/sys/dev/flash/mx25l.c (working copy) @@ -59,6 +59,8 @@ device_t sc_dev; uint8_t sc_manufacturer_id; uint16_t sc_device_id; + unsigned int sc_sectorsize; + unsigned int sc_sectorcount; struct mtx sc_mtx; struct disk *sc_disk; struct proc *sc_p; @@ -85,6 +87,7 @@ { "mx25ll32", 0xc2, 0x2016, 64 * 1024, 64 }, { "mx25ll64", 0xc2, 0x2017, 64 * 1024, 128 }, { "mx25ll128", 0xc2, 0x2018, 64 * 1024, 256 }, + { "s25fl128", 0x01, 0x2018, 64 * 1024, 256 }, }; static uint8_t @@ -172,6 +175,7 @@ cmd.rx_cmd = rxBuf; cmd.rx_cmd_sz = 1; cmd.tx_cmd_sz = 1; + mx25l_wait_for_device_ready(dev); err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd); } @@ -182,7 +186,6 @@ struct spi_command cmd; int err; - mx25l_wait_for_device_ready(dev); mx25l_set_writable(dev, 1); memset(&cmd, 0, sizeof(cmd)); @@ -197,10 +200,134 @@ txBuf[1] = ((sector >> 16) & 0xff); txBuf[2] = ((sector >> 8) & 0xff); txBuf[3] = (sector & 0xff); + mx25l_wait_for_device_ready(dev); err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd); } +static void +mx25l_write_sector(device_t dev, off_t offset, caddr_t data) +{ + struct mx25l_softc *sc = device_get_softc(dev); + uint8_t txBuf[4], rxBuf[4]; + struct spi_command cmd; + uint8_t *ptr = (uint8_t*)data; + long n; + int err; + + for (n = 0; n < sc->sc_sectorsize; n += FLASH_PAGE_SIZE) { + bzero(&cmd, sizeof(cmd)); + bzero(txBuf, sizeof(txBuf)); + bzero(rxBuf, sizeof(rxBuf)); + + cmd.tx_cmd_sz = 4; + cmd.rx_cmd_sz = 4; + cmd.tx_cmd = txBuf; + cmd.rx_cmd = rxBuf; + + txBuf[0] = CMD_PAGE_PROGRAM; + txBuf[1] = (((offset + n) >> 16) & 0xff); + txBuf[2] = (((offset + n) >> 8) & 0xff); + txBuf[3] = ((offset + n) & 0xff); + + cmd.tx_data = ptr + n; + cmd.tx_data_sz = FLASH_PAGE_SIZE; + cmd.rx_data = ptr + n; + cmd.rx_data_sz = FLASH_PAGE_SIZE; + + mx25l_set_writable(dev, 1); + mx25l_wait_for_device_ready(dev); + err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd); + } +} + static int +mx25l_read(device_t dev, off_t offset, long count, caddr_t data) +{ + uint8_t txBuf[8], rxBuf[8]; + struct spi_command cmd; + int ret; + + bzero(&cmd, sizeof(cmd)); + bzero(txBuf, sizeof(txBuf)); + bzero(rxBuf, sizeof(rxBuf)); + + cmd.tx_cmd_sz = 5; + cmd.rx_cmd_sz = 5; + + txBuf[0] = CMD_FAST_READ; + txBuf[1] = ((offset >> 16) & 0xff); + txBuf[2] = ((offset >> 8) & 0xff); + txBuf[3] = (offset & 0xff); + txBuf[4] = 0; /* Dummy byte required by fast read */ + + cmd.tx_cmd = txBuf; + cmd.rx_cmd = rxBuf; + cmd.tx_data = data; + cmd.tx_data_sz = count; + cmd.rx_data = data; + cmd.rx_data_sz = count; + mx25l_wait_for_device_ready(dev); + ret = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd); + + return ret; +} + +static int +mx25l_write(device_t dev, off_t offset, long count, caddr_t data) +{ + struct mx25l_softc *sc = device_get_softc(dev); + off_t sector; + int sector_offset, sector_remain, i, n; + uint8_t *temp, *ptr = (uint8_t*)data; + + temp = malloc(sc->sc_sectorsize, M_TEMP, M_WAITOK); + if (NULL == temp){ + printf("%s: failed to alloc.\n", __func__); + return -1; + } + + sector_offset = offset % sc->sc_sectorsize; + sector_remain = sc->sc_sectorsize - sector_offset; + sector = offset - sector_offset; + + if (sector_remain >= count) { + /* in sector */ + mx25l_read(dev, sector, sc->sc_sectorsize, temp); + bcopy(ptr, temp + sector_offset, count); + mx25l_erase_sector(dev, sector); + mx25l_write_sector(dev, sector, temp); + } else { + /* cross sectoer, first */ + mx25l_read(dev, sector, sc->sc_sectorsize, temp); + bcopy(ptr, temp + sector_offset, sector_remain); + mx25l_erase_sector(dev, sector); + mx25l_write_sector(dev, sector, temp); + count -= sector_remain; + ptr += sector_remain; + + /* inter */ + n = count / sc->sc_sectorsize; + for (i = 0; i < n; i++) { + mx25l_erase_sector(dev, sector); + mx25l_write_sector(dev, sector, ptr); + count -= sc->sc_sectorsize; + sector += sc->sc_sectorsize; + ptr += sc->sc_sectorsize; + } + /* last */ + if (count > 0) { + mx25l_read(dev, sector, sc->sc_sectorsize, temp); + bcopy(ptr, temp, count); + mx25l_erase_sector(dev, sector); + mx25l_write_sector(dev, sector, temp); + } + + } + free(temp, M_TEMP); + return 0; +} + +static int mx25l_probe(device_t dev) { device_set_desc(dev, "M25Pxx Flash Family"); @@ -223,6 +350,11 @@ mx25l_wait_for_device_ready(sc->sc_dev); + sc->sc_manufacturer_id = ident->manufacturer_id; + sc->sc_device_id = ident->device_id; + sc->sc_sectorsize = ident->sectorsize; + sc->sc_sectorcount = ident->sectorcount; + sc->sc_disk = disk_alloc(); sc->sc_disk->d_open = mx25l_open; sc->sc_disk->d_close = mx25l_close; @@ -231,7 +363,7 @@ sc->sc_disk->d_name = "flash/spi"; sc->sc_disk->d_drv1 = sc; sc->sc_disk->d_maxsize = DFLTPHYS; - sc->sc_disk->d_sectorsize = ident->sectorsize; + sc->sc_disk->d_sectorsize = 512; sc->sc_disk->d_mediasize = ident->sectorsize * ident->sectorcount; sc->sc_disk->d_unit = device_get_unit(sc->sc_dev); sc->sc_disk->d_dump = NULL; /* NB: no dumps */ @@ -294,15 +426,10 @@ { struct mx25l_softc *sc = (struct mx25l_softc*)arg; struct bio *bp; - uint8_t txBuf[8], rxBuf[8]; - struct spi_command cmd; - device_t dev, pdev; - off_t write_offset; - long bytes_to_write, bytes_writen; + device_t dev; + dev = sc->sc_dev; for (;;) { - dev = sc->sc_dev; - pdev = device_get_parent(dev); M25PXX_LOCK(sc); do { bp = bioq_first(&sc->sc_bio_queue); @@ -312,84 +439,16 @@ bioq_remove(&sc->sc_bio_queue, bp); M25PXX_UNLOCK(sc); - if (bp->bio_cmd == BIO_READ) { - txBuf[0] = CMD_FAST_READ; - cmd.tx_cmd_sz = 5; - cmd.rx_cmd_sz = 5; - - txBuf[1] = (((bp->bio_offset) >> 16) & 0xff); - txBuf[2] = (((bp->bio_offset) >> 8) & 0xff); - txBuf[3] = ((bp->bio_offset) & 0xff); - /* Dummy byte */ - txBuf[4] = 0; - - cmd.tx_cmd = txBuf; - cmd.rx_cmd = rxBuf; - cmd.tx_data = bp->bio_data; - cmd.tx_data_sz = bp->bio_bcount; - cmd.rx_data = bp->bio_data; - cmd.rx_data_sz = bp->bio_bcount; - - bp->bio_error = SPIBUS_TRANSFER(pdev, dev, &cmd); + switch(bp->bio_cmd) { + case BIO_READ: + bp->bio_error = mx25l_read(dev, bp->bio_offset, bp->bio_bcount, bp->bio_data); + bp->bio_resid = 0; + break; + case BIO_WRITE: + bp->bio_error = mx25l_write(dev, bp->bio_offset, bp->bio_bcount, bp->bio_data); + bp->bio_resid = 0; + break; } - else if (bp->bio_cmd == BIO_WRITE) { - mx25l_erase_sector(dev, bp->bio_offset); - - cmd.tx_cmd_sz = 4; - cmd.rx_cmd_sz = 4; - - bytes_writen = 0; - write_offset = bp->bio_offset; - - /* - * I 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 %d bytes aliIgned", - 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 - * one by one - */ - while (bytes_writen < bp->bio_bcount) { - txBuf[0] = CMD_PAGE_PROGRAM; - txBuf[1] = ((write_offset >> 16) & 0xff); - txBuf[2] = ((write_offset >> 8) & 0xff); - txBuf[3] = (write_offset & 0xff); - - bytes_to_write = MIN(FLASH_PAGE_SIZE, - bp->bio_bcount - bytes_writen); - cmd.tx_cmd = txBuf; - cmd.rx_cmd = rxBuf; - cmd.tx_data = bp->bio_data + bytes_writen; - cmd.tx_data_sz = bytes_to_write; - cmd.rx_data = bp->bio_data + bytes_writen; - cmd.rx_data_sz = bytes_to_write; - - /* - * Eash completed write operation resets WEL - * (write enable latch) to disabled state, - * so we re-enable it here - */ - mx25l_wait_for_device_ready(dev); - mx25l_set_writable(dev, 1); - - bp->bio_error = SPIBUS_TRANSFER(pdev, dev, &cmd); - if (bp->bio_error) - break; - - bytes_writen += bytes_to_write; - write_offset += bytes_to_write; - } - } - else - bp->bio_error = EINVAL; - - biodone(bp); } } Index: src-mips/sys/dev/flash/mx25lreg.h =================================================================== --- src-mips/sys/dev/flash/mx25lreg.h (revision 198476) +++ src-mips/sys/dev/flash/mx25lreg.h (working copy) @@ -46,6 +46,7 @@ * Status register flags */ #define STATUS_SRWD (1 << 7) +#define STATUS_BP3 (1 << 5) #define STATUS_BP2 (1 << 4) #define STATUS_BP1 (1 << 3) #define STATUS_BP0 (1 << 2) Index: src-mips/sys/geom/geom_redboot.c =================================================================== --- src-mips/sys/geom/geom_redboot.c (revision 198476) +++ src-mips/sys/geom/geom_redboot.c (working copy) @@ -366,16 +366,23 @@ return (NULL); g_topology_unlock(); head = NULL; - offset = cp->provider->mediasize - blksize; -again: - buf = g_read_data(cp, offset, blksize, NULL); + /* + * Find out FIS Directory block by block + */ + buf = g_read_data(cp, 0, blksize, NULL); if (buf != NULL) - head = parse_fis_directory(buf, blksize, offset, offmask); - if (head == NULL && offset != 0) { - if (buf != NULL) - g_free(buf); - offset = 0; /* check the front */ - goto again; + head = parse_fis_directory(buf, blksize, 0, offmask); + if (head == NULL) { + g_free(buf); + for (offset = cp->provider->mediasize - blksize; offset > 0; offset -= blksize) { + buf = g_read_data(cp, offset, blksize, NULL); + if (buf != NULL) + head = parse_fis_directory(buf, blksize, offset, offmask); + if (head) + break; + if (buf != NULL) + g_free(buf); + } } g_topology_lock(); if (head == NULL) { --=-Fe4tX8B/oIcPcwY9d+af--