Title: [6680] branches/2009R1: Fix bug [#5208], support sst spi flash chips in kernel.
Revision
6680
Author
gyang
Date
2009-06-12 03:49:39 -0500 (Fri, 12 Jun 2009)

Log Message

Fix bug [#5208], support sst spi flash chips in kernel.

Modified Paths

Diff

Modified: branches/2009R1/arch/blackfin/mach-bf527/boards/ezbrd.c (6679 => 6680)


--- branches/2009R1/arch/blackfin/mach-bf527/boards/ezbrd.c	2009-06-12 08:10:11 UTC (rev 6679)
+++ branches/2009R1/arch/blackfin/mach-bf527/boards/ezbrd.c	2009-06-12 08:49:39 UTC (rev 6680)
@@ -237,10 +237,10 @@
 	.name = "m25p80",
 	.parts = bfin_spi_flash_partitions,
 	.nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
-	.type = "m25p16",
+	.type = "sst25wf040",
 };
 
-/* SPI flash chip (m25p64) */
+/* SPI flash chip (sst25wf040) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
 	.bits_per_word = 8,

Modified: branches/2009R1/drivers/mtd/devices/m25p80.c (6679 => 6680)


--- branches/2009R1/drivers/mtd/devices/m25p80.c	2009-06-12 08:10:11 UTC (rev 6679)
+++ branches/2009R1/drivers/mtd/devices/m25p80.c	2009-06-12 08:49:39 UTC (rev 6680)
@@ -43,6 +43,11 @@
 #define	OPCODE_SE		0xd8	/* Sector erase (usually 64KiB) */
 #define	OPCODE_RDID		0x9f	/* Read JEDEC ID */
 
+/* Used for sst chips */
+#define	OPCODE_BP		0x02	/* Byte program */
+#define	OPCODE_WRDI		0x04	/* Write disable */
+#define	OPCODE_AAI_WP		0xad	/* Auto address increment word program */
+
 /* Status Register bits. */
 #define	SR_WIP			1	/* Write in progress */
 #define	SR_WEL			2	/* Write enable latch */
@@ -137,7 +142,17 @@
 	return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
 }
 
+/*
+ * Send write disble instruction to the chip.
+ */
+static inline int write_disable(struct m25p *flash)
+{
+	u8	code = OPCODE_WRDI;
 
+	return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
+}
+
+
 /*
  * Service routine to read status register until ready, or timeout occurs.
  * Returns non-zero if error.
@@ -457,7 +472,103 @@
 	return 0;
 }
 
+static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *buf)
+{
+	struct m25p *flash = mtd_to_m25p(mtd);
+	struct spi_transfer t[2];
+	struct spi_message m;
+	size_t actual;
+	int cmd_sz, ret;
 
+	if (retlen)
+		*retlen = 0;
+
+	/* sanity checks */
+	if (!len)
+		return 0;
+
+	if (to + len > flash->mtd.size)
+		return -EINVAL;
+
+	spi_message_init(&m);
+	memset(t, 0, (sizeof t));
+
+	t[0].tx_buf = flash->command;
+	t[0].len = CMD_SIZE;
+	spi_message_add_tail(&t[0], &m);
+
+	t[1].tx_buf = buf;
+	spi_message_add_tail(&t[1], &m);
+
+	mutex_lock(&flash->lock);
+
+	/* Wait until finished previous write command. */
+	ret = wait_till_ready(flash);
+	if (ret)
+		goto time_out;
+
+	write_enable(flash);
+
+	actual = to % 2;
+	/* Start write from odd address. */
+	if (actual) {
+		flash->command[0] = OPCODE_BP;
+		flash->command[1] = to >> 16;
+		flash->command[2] = to >> 8;
+		flash->command[3] = to;
+
+		/* write one byte. */
+		t[1].len = 1;
+		spi_sync(flash->spi, &m);
+		*retlen += m.actual_length - CMD_SIZE;
+	}
+	to += actual;
+
+	flash->command[0] = OPCODE_AAI_WP;
+	flash->command[1] = to >> 16;
+	flash->command[2] = to >> 8;
+	flash->command[3] = to;
+
+	cmd_sz = CMD_SIZE;
+	for (; actual < len - 1; actual += 2) {
+		t[0].len = cmd_sz;
+		/* write two bytes. */
+		t[1].len = 2;
+		t[1].tx_buf = buf + actual;
+		ret = wait_till_ready(flash);
+		if (ret)
+			goto time_out;
+		spi_sync(flash->spi, &m);
+
+		*retlen += m.actual_length - cmd_sz;
+		cmd_sz = 1;
+		to += 2;
+	}
+
+	if (actual != len) {
+		flash->command[0] = OPCODE_BP;
+		flash->command[1] = to >> 16;
+		flash->command[2] = to >> 8;
+		flash->command[3] = to;
+		t[0].len = CMD_SIZE;
+		t[1].len = 1;
+		t[1].tx_buf = buf + actual;
+		ret = wait_till_ready(flash);
+		if (ret)
+			goto time_out;
+		spi_sync(flash->spi, &m);
+
+		*retlen += m.actual_length - CMD_SIZE;
+	}
+
+	ret = wait_till_ready(flash);
+time_out:
+	write_disable(flash);
+	mutex_unlock(&flash->lock);
+	return ret;
+}
+
 /****************************************************************************/
 
 /*
@@ -519,6 +630,7 @@
 	{ "sst25vf080b", 0xbf258e, 0, 64 * 1024, 16, SECT_4K, },
 	{ "sst25vf016b", 0xbf2541, 0, 64 * 1024, 32, SECT_4K, },
 	{ "sst25vf032b", 0xbf254a, 0, 64 * 1024, 64, SECT_4K, },
+	{ "sst25wf040",  0xbf2504, 0, 64 * 1024, 8, SECT_4K, },
 
 	/* ST Microelectronics -- newer production may have feature updates */
 	{ "m25p05",  0x202010,  0, 32 * 1024, 2, },
@@ -666,8 +778,13 @@
 	flash->mtd.size = info->sector_size * info->n_sectors;
 	flash->mtd.erase = m25p80_erase;
 	flash->mtd.read = m25p80_read;
-	flash->mtd.write = m25p80_write;
 
+	/* sst flash chips use AAI word program */
+	if (info->jedec_id >> 16 == 0xbf)
+		flash->mtd.write = sst_write;
+	else
+		flash->mtd.write = m25p80_write;
+
 	/* prefer "small sector" erase if possible */
 	if (info->flags & SECT_4K) {
 		flash->erase_opcode = OPCODE_BE_4K;
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to