Skip site navigation (1)Skip section navigation (2)
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>