Date: Mon, 26 Oct 2009 11:37:52 +0800 From: Eric <lihong@ieee.org> To: gonzo@freebsd.org Cc: freebsd-mips@freebsd.org Subject: Add Wistron RPAA-82 board support Message-ID: <1256528272.31398.28.camel@localhost>
next in thread | raw e-mail | index | archive | help
--=-cGh19E6cDpSf0EFAbWSZ
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 7bit
Hi
I added my ar7161 board support last weekend.
It's flash is come from Spansion.
--
Best Regards,
Eric L. Chen <lihong@ieee.org>
--=-cGh19E6cDpSf0EFAbWSZ
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) {
--=-cGh19E6cDpSf0EFAbWSZ--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1256528272.31398.28.camel>
