<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<META NAME="Generator" CONTENT="MS Exchange Server version 6.5.7654.12">
<TITLE>[PATCH] MTD: Micron SPINAND Driver support</TITLE>
</HEAD>
<BODY>
<!-- Converted from text/rtf format -->
<BR>
<P><FONT SIZE=2 FACE="Courier New">This patch adds support for Micron SPINAND via MTD.</FONT>
</P>
<BR>
<P><FONT SIZE=2 FACE="Courier New">Signed-off-by: Mona Anonuevo (manonuevo@micron.com)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">Signed-off-by: Tuan Nguyen (tqnguyen@micron.com)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">----</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> drivers/mtd/Kconfig | 2 </FONT>
<BR><FONT SIZE=2 FACE="Courier New"> drivers/mtd/Makefile | 2 </FONT>
<BR><FONT SIZE=2 FACE="Courier New"> drivers/mtd/spinand/Kconfig | 25 +</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> drivers/mtd/spinand/Makefile | 10 </FONT>
<BR><FONT SIZE=2 FACE="Courier New"> drivers/mtd/spinand/spinand_lld.c | 760 ++++++++++++++++++++++++++++++++++++++</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> drivers/mtd/spinand/spinand_mtd.c | 728 ++++++++++++++++++++++++++++++++++++</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> include/linux/mtd/spinand.h | 160 ++++++++</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> 7 files changed, 1687 insertions(+)</FONT>
</P>
<P><FONT SIZE=2 FACE="Courier New">PATCH FOLLOWS</FONT>
<BR><FONT SIZE=2 FACE="Courier New">Kernel Version: Linux 2.6.33.20</FONT>
<BR><FONT SIZE=2 FACE="Courier New">diff -urN linux-2.6.33.20-orig/drivers/mtd/Kconfig linux-2.6.33.20/drivers/mtd/Kconfig</FONT>
<BR><FONT SIZE=2 FACE="Courier New">--- linux-2.6.33.20-orig/drivers/mtd/Kconfig 2010-04-01 16:02:33.000000000 -0700</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+++ linux-2.6.33.20/drivers/mtd/Kconfig 2010-05-19 04:28:06.000000000 -0700</FONT>
<BR><FONT SIZE=2 FACE="Courier New">@@ -325,6 +325,8 @@</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> </FONT>
<BR><FONT SIZE=2 FACE="Courier New"> source "drivers/mtd/onenand/Kconfig"</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+source "drivers/mtd/spinand/Kconfig"</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> source "drivers/mtd/lpddr/Kconfig"</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> </FONT>
<BR><FONT SIZE=2 FACE="Courier New"> source "drivers/mtd/ubi/Kconfig"</FONT>
<BR><FONT SIZE=2 FACE="Courier New">diff -urN linux-2.6.33.20-orig/drivers/mtd/Makefile linux-2.6.33.20/drivers/mtd/Makefile</FONT>
<BR><FONT SIZE=2 FACE="Courier New">--- linux-2.6.33.20-orig/drivers/mtd/Makefile 2010-04-01 16:02:33.000000000 -0700</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+++ linux-2.6.33.20/drivers/mtd/Makefile 2010-05-19 04:28:06.000000000 -0700</FONT>
<BR><FONT SIZE=2 FACE="Courier New">@@ -31,4 +31,6 @@</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> </FONT>
<BR><FONT SIZE=2 FACE="Courier New"> obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+obj-y += spinand/ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New"> obj-$(CONFIG_MTD_UBI) += ubi/</FONT>
<BR><FONT SIZE=2 FACE="Courier New">diff -urN linux-2.6.33.20-orig/drivers/mtd/spinand/Kconfig linux-2.6.33.20/drivers/mtd/spinand/Kconfig</FONT>
<BR><FONT SIZE=2 FACE="Courier New">--- linux-2.6.33.20-orig/drivers/mtd/spinand/Kconfig 1969-12-31 16:00:00.000000000 -0800</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+++ linux-2.6.33.20/drivers/mtd/spinand/Kconfig 2010-05-19 04:28:06.000000000 -0700</FONT>
<BR><FONT SIZE=2 FACE="Courier New">@@ -0,0 +1,25 @@</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+# linux/drivers/mtd/spinand/Kconfig</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+menuconfig MTD_SPINAND</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ tristate "SPINAND Device Support"</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ depends on MTD</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ help</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ This enables support for accessing Micron SPI NAND flash</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ devices.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+if MTD_SPINAND</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+config MTD_SPINAND_ONDIEECC</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ bool "Use SPINAND internal ECC"</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ help</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ Internel ECC</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+config MTD_SPINAND_SWECC</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ bool "Use software ECC"</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ depends on MTD_NAND</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ help</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ software ECC</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+endif</FONT>
<BR><FONT SIZE=2 FACE="Courier New">diff -urN linux-2.6.33.20-orig/drivers/mtd/spinand/Makefile linux-2.6.33.20/drivers/mtd/spinand/Makefile</FONT>
<BR><FONT SIZE=2 FACE="Courier New">--- linux-2.6.33.20-orig/drivers/mtd/spinand/Makefile 1969-12-31 16:00:00.000000000 -0800</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+++ linux-2.6.33.20/drivers/mtd/spinand/Makefile 2010-05-19 04:28:07.000000000 -0700</FONT>
<BR><FONT SIZE=2 FACE="Courier New">@@ -0,0 +1,10 @@</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+# Makefile for the SPI NAND MTD</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+# Core functionality.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+obj-$(CONFIG_MTD_SPINAND) += spinand.o</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+spinand-objs := spinand_mtd.o spinand_lld.o</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">diff -urN linux-2.6.33.20-orig/drivers/mtd/spinand/spinand_lld.c linux-2.6.33.20/drivers/mtd/spinand/spinand_lld.c</FONT>
<BR><FONT SIZE=2 FACE="Courier New">--- linux-2.6.33.20-orig/drivers/mtd/spinand/spinand_lld.c 1969-12-31 16:00:00.000000000 -0800</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+++ linux-2.6.33.20/drivers/mtd/spinand/spinand_lld.c 2010-05-19 03:56:51.000000000 -0700</FONT>
<BR><FONT SIZE=2 FACE="Courier New">@@ -0,0 +1,760 @@</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/*</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+spinand_lld.c</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+Copyright (c) 2009-2010 Micron Technology, Inc.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+This program is free software; you can redistribute it and/or</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+modify it under the terms of the GNU General Public License</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+as published by the Free Software Foundation; either version 2</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+of the License, or (at your option) any later version.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+This program is distributed in the hope that it will be useful,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+but WITHOUT ANY WARRANTY; without even the implied warranty of</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+GNU General Public License for more details.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+*/</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/init.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/module.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/device.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/interrupt.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/mutex.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/math64.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/mtd/mtd.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/mtd/partitions.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/mtd/spinand.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/spi/spi.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define mu_spi_nand_driver_version "Beagle-MTD_01.00_Linux2.6.33_20100507"</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define SPI_NAND_MICRON_DRIVER_KEY 0x1233567</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/****************************************************************************/</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ OOB area specification layout: Total 32 available free bytes.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+*/</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static struct nand_ecclayout spinand_oob_64 = {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .eccbytes = 24,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .eccpos = {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ 1, 2, 3, 4, 5, 6,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ 17, 18, 19, 20, 21, 22,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ 33, 34, 35, 36, 37, 38,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ 49, 50, 51, 52, 53, 54, },</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .oobavail = 32,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .oobfree = {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {.offset = 8,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .length = 8},</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {.offset = 24,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .length = 8},</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {.offset = 40,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .length = 8},</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {.offset = 56,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .length = 8}, }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_cmd - to process a command to send to the SPI Nand</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Set up the command buffer to send to the SPI controller.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * The command buffer has to initized to 0</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+int spinand_cmd(struct spi_device *spi, struct spinand_cmd *cmd)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int ret;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spi_message message;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spi_transfer x[4];</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 dummy = 0xff;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spi_message_init(&message);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memset(x, 0, sizeof x);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ x[0].len = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ x[0].tx_buf = &cmd->cmd;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spi_message_add_tail(&x[0], &message);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (cmd->n_addr)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ x[1].len = cmd->n_addr;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ x[1].tx_buf = cmd->addr;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spi_message_add_tail(&x[1], &message);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (cmd->n_dummy)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ x[2].len = cmd->n_dummy;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ x[2].tx_buf = &dummy;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spi_message_add_tail(&x[2], &message); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (cmd->n_tx)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ x[3].len = cmd->n_tx;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ x[3].tx_buf = cmd->tx_buf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spi_message_add_tail(&x[3], &message); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (cmd->n_rx)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ x[3].len = cmd->n_rx;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ x[3].rx_buf = cmd->rx_buf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spi_message_add_tail(&x[3], &message); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ret = spi_sync(spi, &message);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return ret; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_reset- send reset command "0xff" to the Nand device</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Reset the SPI Nand with the reset command 0xff</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_reset(struct spi_device *spi_nand)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_RESET;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return spinand_cmd(spi_nand, &cmd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_read_id- Read SPI Nand ID</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Read ID: read two ID bytes from the SPI Nand device</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_read_id(struct spi_device *spi_nand, u8 *id)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_READ_ID;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_dummy = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_rx = 2;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.rx_buf = id;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_cmd(spi_nand, &cmd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval != 0) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "error %d reading id\n",</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ (int) retval);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_lock_block- send write register 0x1f command to the Nand device</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * After power up, all the Nand blocks are locked. This function allows</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * one to unlock the blocks, and so it can be wriiten or erased.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_lock_block(struct spi_device *spi_nand, struct spinand_info *info, u8 lock)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_WRITE_REG;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_addr = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[0] = REG_BLOCK_LOCK;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_tx = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.tx_buf = &lock;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_cmd(spi_nand, &cmd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval != 0) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "error %d lock block\n",</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ (int) retval);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_read_status- send command 0xf to the SPI Nand status register</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * After read, write, or erase, the Nand device is expected to set the busy status.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * This function is to allow reading the status of the command: read, write, and erase.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Once the status turns to be ready, the other status bits also are valid status bits.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_read_status(struct spi_device *spi_nand, struct spinand_info *info, u8 *status)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_READ_REG;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_addr = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[0] = REG_STATUS;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_rx = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.rx_buf = status;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_cmd(spi_nand, &cmd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval != 0) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "error %d reading status register\n",</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ (int) retval);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_get_otp- send command 0xf to read the SPI Nand OTP register</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * There is one bit( bit 0x10 ) to set or to clear the internal ECC.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Enable chip internal ECC, set the bit to 1</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Disable chip internal ECC, clear the bit to 0</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_get_otp(struct spi_device *spi_nand, struct spinand_info *info, u8* otp)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_READ_REG;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_addr = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[0] = REG_OTP;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_rx = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.rx_buf = otp;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_cmd(spi_nand, &cmd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval != 0) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "error %d get otp\n",</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ (int) retval);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_set_otp- send command 0x1f to write the SPI Nand OTP register</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * There is one bit( bit 0x10 ) to set or to clear the internal ECC.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Enable chip internal ECC, set the bit to 1</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Disable chip internal ECC, clear the bit to 0</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_set_otp(struct spi_device *spi_nand, struct spinand_info *info, u8* otp)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_WRITE_REG;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_addr = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[0] = REG_OTP;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_tx = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.tx_buf = otp;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_cmd(spi_nand, &cmd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval != 0) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "error %d set otp\n",</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ (int) retval);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * sspinand_enable_ecc- send command 0x1f to write the SPI Nand OTP register</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * There is one bit( bit 0x10 ) to set or to clear the internal ECC.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Enable chip internal ECC, set the bit to 1</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Disable chip internal ECC, clear the bit to 0</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_enable_ecc(struct spi_device *spi_nand, struct spinand_info *info)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 otp = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_get_otp(spi_nand, info, &otp);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((otp & OTP_ECC_MASK) == OTP_ECC_MASK)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ otp |= OTP_ECC_MASK;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_set_otp(spi_nand, info, &otp);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_get_otp(spi_nand, info, &otp);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_disable_ecc(struct spi_device *spi_nand, struct spinand_info *info)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 otp = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_get_otp(spi_nand, info, &otp);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((otp & OTP_ECC_MASK) == OTP_ECC_MASK)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ otp &= ~OTP_ECC_MASK;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_set_otp(spi_nand, info, &otp);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_get_otp(spi_nand, info, &otp);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * sspinand_write_enable- send command 0x06 to enable write or erase the Nand cells</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Before write and erase the Nand cells, the write enable has to be set.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * After the write or erase, the write enable bit is automatically cleared( status register bit 2 )</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Set the bit 2 of the status register has the same effect</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_write_enable(struct spi_device *spi_nand, struct spinand_info *info)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_WR_ENABLE;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return spinand_cmd(spi_nand, &cmd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_read_page_to_cache(struct spi_device *spi_nand, struct spinand_info *info, u16 page_id)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 row;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ row = page_id;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_READ;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_addr = 3;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[1] = (u8)((row&0xff00)>>8);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[2] = (u8)(row&0x00ff);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return spinand_cmd(spi_nand, &cmd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_read_from_cache- send command 0x03 to read out the data from the cache register( 2112 bytes max )</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * The read can specify 1 to 2112 bytes of data read at the coresponded locations.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * No tRd delay.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_read_from_cache(struct spi_device *spi_nand, struct spinand_info *info, u16 byte_id, u16 len, u8* rbuf)</FONT></P>
<P><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 column;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ column = byte_id;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_READ_RDM;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_addr = 2;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[0] = (u8)((column&0xff00)>>8);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[1] = (u8)(column&0x00ff);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_dummy = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_rx = len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.rx_buf = rbuf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return spinand_cmd(spi_nand, &cmd); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_read_page-to read a page with:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @page_id: the physical page number</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @offset: the location from 0 to 2111</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @len: number of bytes to read</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @rbuf: read buffer to hold @len bytes</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * The read icludes two commands to the Nand: 0x13 and 0x03 commands</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Poll to read status to wait for tRD time.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_read_page(struct spi_device *spi_nand, struct spinand_info *info, u16 page_id, u16 offset, u16 len, u8* rbuf)</FONT></P>
<P><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 status = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_read_page_to_cache(spi_nand, info, page_id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ while (1)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_read_status(spi_nand, info, &status);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval<0) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "error %d reading status register\n",</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ (int) retval);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((status & STATUS_OIP_MASK) == STATUS_READY)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "ecc error, page=%d\n", page_id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (spi_nand == SPI_NAND_MICRON_DRIVER_KEY)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ printk(KERN_INFO "Error: reformat or erase your device. \n"); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ break;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_read_from_cache(spi_nand, info, offset, len, rbuf);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_program_data_to_cache--to write a page to cache with:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @byte_id: the location to write to the cache</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @len: number of bytes to write</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @rbuf: read buffer to hold @len bytes</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * The write command used here is 0x84--indicating that the cache is not cleared first.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Since it is writing the data to cache, there is no tPROG time.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_program_data_to_cache(struct spi_device *spi_nand, struct spinand_info *info, u16 byte_id, u16 len, u8* wbuf)</FONT></P>
<P><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 column;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ column = byte_id;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_PROG_PAGE_CLRCACHE;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_addr = 2;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[0] = (u8)((column&0xff00)>>8);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[1] = (u8)(column&0x00ff);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_tx = len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.tx_buf = wbuf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return spinand_cmd(spi_nand, &cmd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_program_execute--to write a page from cache to the Nand array with:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @page_id: the physical page location to write the page.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * The write command used here is 0x10--indicating the cache is writing to the Nand array.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Need to wait for tPROG time to finish the transaction.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_program_execute(struct spi_device *spi_nand, struct spinand_info *info, u16 page_id)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 row;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ row = page_id;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_PROG_PAGE_EXC;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_addr = 3;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[1] = (u8)((row&0xff00)>>8);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[2] = (u8)(row&0x00ff);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return spinand_cmd(spi_nand, &cmd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_program_page--to write a page with:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @page_id: the physical page location to write the page.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @offset: the location from the cache starting from 0 to 2111</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @len: the number of bytes to write </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @wbuf: the buffer to hold the number of bytes</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * The commands used here are 0x06, 0x84, and 0x10--indicating that the write enable is first</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * sent, the write cache command, and the write execute command</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Poll to wait for the tPROG time to finish the transaction.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_program_page(struct spi_device *spi_nand, struct spinand_info *info, u16 page_id, u16 offset, u16 len, u8* wbuf)</FONT></P>
<P><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 status = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_write_enable(spi_nand, info);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_program_data_to_cache(spi_nand, info, offset, len, wbuf);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_program_execute(spi_nand, info, page_id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ while (1)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_read_status(spi_nand, info, &status);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval<0) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "error %d reading status register\n",</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ (int) retval);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((status & STATUS_OIP_MASK) == STATUS_READY)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((status & STATUS_P_FAIL_MASK) == STATUS_P_FAIL)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "program error, page=%d\n", page_id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ break;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_erase_block_erase--to erase a page with:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @block_id: the physical block location to erase.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * The command used here is 0xd8--indicating an erase command to erase one block--64 pages</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Need to wait for tERS.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_erase_block_erase(struct spi_device *spi_nand, struct spinand_info *info, u16 block_id)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_cmd cmd = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 row;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ row = block_id << 6;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.cmd = CMD_ERASE_BLK;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.n_addr = 3;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[1] = (u8)((row&0xff00)>>8);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ cmd.addr[2] = (u8)(row&0x00ff);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return spinand_cmd(spi_nand, &cmd); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_erase_block--to erase a page with:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @block_id: the physical block location to erase.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * The commands used here are 0x06 and 0xd8--indicating an erase command to erase one block--64 pages</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * It will first to enable the write enable bit ( 0x06 command ), and then send the 0xd8 erase command</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Poll to wait for the tERS time to complete the tranaction.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_erase_block(struct spi_device *spi_nand, struct spinand_info *info, u16 block_id)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 status= 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_write_enable(spi_nand, info);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_erase_block_erase(spi_nand, info, block_id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ while (1)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_read_status(spi_nand, info, &status);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval<0) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "error %d reading status register\n",</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ (int) retval);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((status & STATUS_OIP_MASK) == STATUS_READY)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((status & STATUS_E_FAIL_MASK) == STATUS_E_FAIL)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_err(&spi_nand->dev, "erase error, block=%d\n", block_id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ break;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/*</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+* spinand_get_info: get NAND info, from read id or const value </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * To set up the device parameters.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_get_info(struct spi_device *spi_nand, struct spinand_info *info, u8* id)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (id[0]==0x2C && (id[1]==0x11 || id[1]==0x12 || id[1]==0x13))</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->mid = id[0];</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->did = id[1];</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->name = "MT29F1G01ZAC";</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->nand_size = (1024 * 64 * 2112);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->usable_size = (1024 * 64 * 2048);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->block_size = (2112*64);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->block_main_size = (2048*64);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->block_num_per_chip = 1024;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->page_size = 2112;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->page_main_size = 2048;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->page_spare_size = 64;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->page_num_per_block = 64;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->block_shift = 17;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->block_mask = 0x1ffff;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->page_shift = 11;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->page_mask = 0x7ff;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info->ecclayout = &spinand_oob_64;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ } </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_probe - [spinand Interface] </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+* @spi_nand: registered device driver.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * To set up the device driver parameters to make the device available.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int __devinit spinand_probe(struct spi_device *spi_nand)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ssize_t retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct mtd_info *mtd;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *chip; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_info *info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 id[2]= {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_reset(spi_nand);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_reset(spi_nand);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_read_id(spi_nand, (u8*)&id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (id[0]==0 && id[1]==0)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ printk(KERN_INFO "SPINAND: read id error! 0x%02x, 0x%02x!\n", id[0], id[1]); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ info = kzalloc(sizeof(struct spinand_info), GFP_KERNEL);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (!info)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -ENOMEM;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_get_info(spi_nand, info, (u8*)&id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ printk(KERN_INFO "SPINAND: 0x%02x, 0x%02x, %s\n", id[0], id[1], info->name); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ printk(KERN_INFO "%s\n", mu_spi_nand_driver_version);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_lock_block(spi_nand, info, BL_ALL_UNLOCKED);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#ifdef CONFIG_MTD_SPINAND_ONDIEECC</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_enable_ecc(spi_nand, info);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_disable_ecc(spi_nand, info);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#endif</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip = kzalloc(sizeof(struct spinand_chip), GFP_KERNEL);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (!chip)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -ENOMEM;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->spi_nand = spi_nand;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->info = info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->reset = spinand_reset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->read_id = spinand_read_id;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->read_page = spinand_read_page;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->program_page = spinand_program_page;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->erase_block = spinand_erase_block;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->buf = kzalloc(info->page_size, GFP_KERNEL);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (!chip->buf)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -ENOMEM;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->oobbuf = kzalloc(info->ecclayout->oobavail, GFP_KERNEL);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (!chip->oobbuf)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -ENOMEM;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (!mtd)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -ENOMEM;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ dev_set_drvdata(&spi_nand->dev, mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->priv = chip;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_mtd(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * __devexit spinand_remove--Remove the device driver</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @spi: the spi device.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Description:</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * To remove the device driver parameters and free up allocated memories.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int __devexit spinand_remove(struct spi_device *spi)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct mtd_info *mtd;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *chip; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev));</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd = dev_get_drvdata(&spi->dev);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_mtd_release(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ kfree(chip->info);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ kfree(chip->buf);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ kfree(chip->oobbuf);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ kfree(chip);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ kfree(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Device name structure description</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+*/</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static struct spi_driver spinand_driver = {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .driver = {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .name = "spi_nand",</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .bus = &spi_bus_type,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .owner = THIS_MODULE,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ },</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .probe = spinand_probe,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ .remove = __devexit_p(spinand_remove),</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Device driver registration</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+*/</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int __init spinand_init(void)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return spi_register_driver(&spinand_driver);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * unregister Device driver.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+*/</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static void __exit spinand_exit(void)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spi_unregister_driver(&spinand_driver);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+module_init(spinand_init);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+module_exit(spinand_exit);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+MODULE_LICENSE("GPL");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+MODULE_AUTHOR("Henry Pan <hspan@micron.com>");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+MODULE_DESCRIPTION("SPI NAND driver code");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">diff -urN linux-2.6.33.20-orig/drivers/mtd/spinand/spinand_mtd.c linux-2.6.33.20/drivers/mtd/spinand/spinand_mtd.c</FONT>
<BR><FONT SIZE=2 FACE="Courier New">--- linux-2.6.33.20-orig/drivers/mtd/spinand/spinand_mtd.c 1969-12-31 16:00:00.000000000 -0800</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+++ linux-2.6.33.20/drivers/mtd/spinand/spinand_mtd.c 2010-05-19 04:28:07.000000000 -0700</FONT>
<BR><FONT SIZE=2 FACE="Courier New">@@ -0,0 +1,728 @@</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/*</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+spinand_mtd.c</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+Copyright (c) 2009-2010 Micron Technology, Inc.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+This program is free software; you can redistribute it and/or</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+modify it under the terms of the GNU General Public License</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+as published by the Free Software Foundation; either version 2</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+of the License, or (at your option) any later version.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+This program is distributed in the hope that it will be useful,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+but WITHOUT ANY WARRANTY; without even the implied warranty of</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+GNU General Public License for more details.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+*/</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/kernel.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/module.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/init.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/sched.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/delay.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/interrupt.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/jiffies.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/mtd/mtd.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/mtd/partitions.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/mtd/spinand.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/mtd/nand_ecc.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_get_device - [GENERIC] Get chip for selected access</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param mtd MTD device structure</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param new_state the state which is requested</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Get the device and lock it for exclusive access</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define mu_spi_nand_driver_version "Beagle-MTD_01.00_Linux2.6.33_20100507"</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_get_device(struct mtd_info *mtd, int new_state)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *this = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ DECLARE_WAITQUEUE(wait, current);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /*</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Grab the lock and see if the device is available</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ while (1) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spin_lock(&this->chip_lock);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (this->state == FL_READY) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ this->state = new_state;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spin_unlock(&this->chip_lock);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ break;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (new_state == FL_PM_SUSPENDED) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spin_unlock(&this->chip_lock);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ set_current_state(TASK_UNINTERRUPTIBLE);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ add_wait_queue(&this->wq, &wait);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spin_unlock(&this->chip_lock);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ schedule();</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ remove_wait_queue(&this->wq, &wait);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_release_device - [GENERIC] release chip</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param mtd MTD device structure</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Deselect, release chip lock and wake up anyone waiting on the device</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static void spinand_release_device(struct mtd_info *mtd)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *this = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* Release the chip */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spin_lock(&this->chip_lock);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ this->state = FL_READY;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ wake_up(&this->wq);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spin_unlock(&this->chip_lock);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#ifdef CONFIG_MTD_SPINAND_SWECC </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static void spinand_calculate_ecc(struct mtd_info *mtd)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int i; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int eccsize = 512;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int eccbytes = 3;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int eccsteps = 4;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int ecctotal = 12;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *chip = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_info *info = chip->info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ unsigned char *p = chip->buf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ __nand_calculate_ecc(p, eccsize, &chip->ecc_calc[i]);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ for (i = 0; i < ecctotal; i++)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->buf[info->page_main_size + info->ecclayout->eccpos[i]] = chip->ecc_calc[i];</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_correct_data(struct mtd_info *mtd)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int i; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int eccsize = 512;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int eccbytes = 3;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int eccsteps = 4;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int ecctotal = 12;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *chip = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_info *info = chip->info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ unsigned char *p = chip->buf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int errcode = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ __nand_calculate_ecc(p, eccsize, &chip->ecc_calc[i]);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ for (i = 0; i < ecctotal; i++)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->ecc_code[i] = chip->buf[info->page_main_size + info->ecclayout->eccpos[i]];</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int stat;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ stat = __nand_correct_data(p, &chip->ecc_code[i], &chip->ecc_calc[i], eccsize);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (stat < 0)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ errcode = -1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else if (stat == 1)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ errcode = 1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return errcode;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#endif</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_read_ops(struct mtd_info *mtd, loff_t from,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct mtd_oob_ops *ops)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *chip = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spi_device *spi_nand = chip->spi_nand;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_info *info = chip->info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int page_id, page_offset, page_num, oob_num;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int count;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int main_ok, main_left, main_offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int oob_ok, oob_left;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ signed int retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ signed int errcode=0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (!chip->buf)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ page_id = from >> info->page_shift;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* for main data */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ page_offset = from & info->page_mask;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ page_num = (page_offset + ops->len + info->page_main_size -1 ) / info->page_main_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* for oob */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ oob_num = (ops->ooblen + info->ecclayout->oobavail -1) / info->ecclayout->oobavail;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ count = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_left = ops->len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_ok = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_offset = page_offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ oob_left = ops->ooblen;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ oob_ok = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ while (1)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (count < page_num || count < oob_num) </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memset(chip->buf, 0, info->page_size); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = chip->read_page(spi_nand, info, page_id + count, 0, info->page_size, chip->buf);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval != 0)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ errcode = -1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ printk(KERN_INFO "spinand_read_ops: fail, page=%d!\n", page_id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return errcode;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ break;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (count < page_num && ops->datbuf) </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#ifdef CONFIG_MTD_SPINAND_SWECC</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = spinand_correct_data(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval == -1)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ printk(KERN_INFO "SWECC uncorrectable error! page=%x\n", page_id+count); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else if (retval == 1)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ printk(KERN_INFO "SWECC 1 bit error, corrected! page=%x\n", page_id+count); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#endif</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((main_offset + main_left) < info->page_main_size)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ size = main_left;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ size = info->page_main_size - main_offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (ops->datbuf + main_ok, chip->buf, size);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_ok += size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_left -= size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_offset = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ops->retlen = main_ok;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (count < oob_num && ops->oobbuf && chip->oobbuf)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int offset, len, temp;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* repack spare to oob */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memset(chip->oobbuf, 0, info->ecclayout->oobavail);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ temp = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ offset = info->ecclayout->oobfree[0].offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ len = info->ecclayout->oobfree[0].length;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (chip->oobbuf + temp, chip->buf + info->page_main_size + offset, len);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ temp += len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ offset = info->ecclayout->oobfree[1].offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ len = info->ecclayout->oobfree[1].length;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (chip->oobbuf + temp, chip->buf + info->page_main_size + offset, len);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ temp += len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ offset = info->ecclayout->oobfree[2].offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ len = info->ecclayout->oobfree[2].length;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (chip->oobbuf + temp, chip->buf + info->page_main_size + offset, len);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ temp += len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ offset = info->ecclayout->oobfree[3].offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ len = info->ecclayout->oobfree[3].length;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (chip->oobbuf + temp, chip->buf + info->page_main_size + offset, len);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* copy oobbuf to ops oobbuf */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (oob_left < info->ecclayout->oobavail) </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ size = oob_left;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ size = info->ecclayout->oobavail;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (ops->oobbuf + oob_ok, chip->oobbuf, size);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ oob_ok += size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ oob_left -= size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ops->oobretlen = oob_ok;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ count++;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return errcode;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_write_ops(struct mtd_info *mtd, loff_t to,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct mtd_oob_ops *ops)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *chip = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spi_device *spi_nand = chip->spi_nand;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_info *info = chip->info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int page_id, page_offset, page_num, oob_num;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int count;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int main_ok, main_left, main_offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int oob_ok, oob_left;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ signed int retval;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ signed int errcode=0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (!chip->buf)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ page_id = to >> info->page_shift;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* for main data */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ page_offset = to & info->page_mask;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ page_num = (page_offset + ops->len + info->page_main_size -1 ) / info->page_main_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* for oob */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ oob_num = (ops->ooblen + info->ecclayout->oobavail -1) / info->ecclayout->oobavail;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ count = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_left = ops->len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_ok = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_offset = page_offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ oob_left = ops->ooblen;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ oob_ok = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ while (1)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (count < page_num || count < oob_num) </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memset(chip->buf, 0xFF, info->page_size); </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ break; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (count < page_num && ops->datbuf) </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((main_offset + main_left) < info->page_main_size)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ size = main_left;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ size = info->page_main_size - main_offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (chip->buf, ops->datbuf + main_ok, size);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_ok += size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_left -= size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ main_offset = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#ifdef CONFIG_MTD_SPINAND_SWECC </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_calculate_ecc(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#endif</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (count < oob_num && ops->oobbuf && chip->oobbuf)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int offset, len, temp;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memset(chip->oobbuf, 0xFF, info->ecclayout->oobavail);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (oob_left < info->ecclayout->oobavail) </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ size = oob_left;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ size = info->ecclayout->oobavail;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (chip->oobbuf, ops->oobbuf + oob_ok, size);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ oob_ok += size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ oob_left -= size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* repack oob to spare */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ temp = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ offset = info->ecclayout->oobfree[0].offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ len = info->ecclayout->oobfree[0].length;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (chip->buf + info->page_main_size + offset, chip->oobbuf + temp, len);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ temp += len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ offset = info->ecclayout->oobfree[1].offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ len = info->ecclayout->oobfree[1].length;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (chip->buf + info->page_main_size + offset, chip->oobbuf + temp, len);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ temp += len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ offset = info->ecclayout->oobfree[2].offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ len = info->ecclayout->oobfree[2].length;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (chip->buf + info->page_main_size + offset, chip->oobbuf + temp, len);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ temp += len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ offset = info->ecclayout->oobfree[3].offset;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ len = info->ecclayout->oobfree[3].length;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ memcpy (chip->buf + info->page_main_size + offset, chip->oobbuf + temp, len);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (count < page_num || count < oob_num) </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = chip->program_page(spi_nand, info, page_id + count, 0, info->page_size, chip->buf);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval != 0)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ errcode = -1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ printk(KERN_INFO "spinand_write_ops: fail, page=%d!\n", page_id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return errcode;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (count < page_num && ops->datbuf) </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ops->retlen = main_ok;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (count < oob_num && ops->oobbuf && chip->oobbuf)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ops->oobretlen = oob_ok;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ count++;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return errcode;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_read(struct mtd_info *mtd, loff_t from, size_t len,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ size_t *retlen, u_char *buf)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct mtd_oob_ops ops = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int ret;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* Do not allow reads past end of device */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((from + len) > mtd->size)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -EINVAL;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (!len)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_get_device(mtd, FL_READING);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ops.len = len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ops.datbuf = buf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ret = spinand_read_ops(mtd, from, &ops);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *retlen = ops.retlen;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_release_device(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return ret;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_write(struct mtd_info *mtd, loff_t to, size_t len,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ size_t *retlen, const u_char *buf)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct mtd_oob_ops ops = {0};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int ret;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* Do not allow reads past end of device */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((to + len) > mtd->size)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -EINVAL;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (!len)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_get_device(mtd, FL_WRITING);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ops.len = len;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ops.datbuf = (uint8_t *)buf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ret = spinand_write_ops(mtd, to, &ops);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *retlen = ops.retlen;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_release_device(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return ret;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_read_oob(struct mtd_info *mtd, loff_t from,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct mtd_oob_ops *ops)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int ret;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_get_device(mtd, FL_READING);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ret = spinand_read_ops(mtd, from, ops);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_release_device(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return ret;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_write_oob(struct mtd_info *mtd, loff_t to,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct mtd_oob_ops *ops)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int ret;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_get_device(mtd, FL_WRITING);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ret = spinand_write_ops(mtd, to, ops);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_release_device(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return ret;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_erase - [MTD Interface] erase block(s)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param mtd MTD device structure</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param instr erase instruction</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Erase one ore more blocks</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_erase(struct mtd_info *mtd, struct erase_info *instr)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *chip = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spi_device *spi_nand = chip->spi_nand;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_info *info = chip->info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 block_id, block_num, count;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ signed int retval=0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ signed int errcode=0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ DEBUG(MTD_DEBUG_LEVEL3, "spinand_erase: start = 0x%012llx, len = %llu\n",</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ (unsigned long long)instr->addr, (unsigned long long)instr->len);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* check address align on block boundary */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (instr->addr & (info->block_main_size - 1)) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ DEBUG(MTD_DEBUG_LEVEL0, "spinand_erase: Unaligned address\n");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -EINVAL;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (instr->len & (info->block_main_size - 1)) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ DEBUG(MTD_DEBUG_LEVEL0, "spinand_erase: "</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ "Length not block aligned\n");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -EINVAL;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* Do not allow erase past end of device */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if ((instr->len + instr->addr) > info->usable_size) {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ DEBUG(MTD_DEBUG_LEVEL0, "spinand_erase: "</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ "Erase past end of device\n");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return -EINVAL;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* Grab the lock and see if the device is available */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_get_device(mtd, FL_ERASING);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ block_id = instr->addr >> info->block_shift;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ block_num = instr->len >> info->block_shift; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ count = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ while (count < block_num )</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = chip->erase_block(spi_nand, info, block_id+count);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval!=0)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ retval = chip->erase_block(spi_nand, info, block_id+count);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (retval!=0)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ printk(KERN_INFO "spinand_erase: fail, block=%d!\n", block_id+count);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ errcode = -1;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ count++;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (errcode == 0)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ instr->state = MTD_ERASE_DONE;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* Deselect and wake up anyone waiting on the device */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_release_device(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* Do call back function */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if(instr->callback)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ instr->callback(instr);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return errcode;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_sync - [MTD Interface] sync</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param mtd MTD device structure</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Sync is actually a wait for chip ready function</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static void spinand_sync(struct mtd_info *mtd)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ DEBUG(MTD_DEBUG_LEVEL3, "spinand_sync: called\n");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* Grab the lock and see if the device is available */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_get_device(mtd, FL_SYNCING);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /* Release it and go back */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_release_device(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_block_isbad(struct mtd_info *mtd, loff_t ofs)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *chip = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spi_device *spi_nand = chip->spi_nand;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_info *info = chip->info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 block_id;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 is_bad = 0x00;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 ret = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_get_device(mtd, FL_READING);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ block_id = ofs >> info->block_shift;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->read_page(spi_nand, info, block_id*info->page_num_per_block, info->page_main_size, 1, &is_bad);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (is_bad != 0xFF)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ ret = 1; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ }</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_release_device(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return ret; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_block_markbad - [MTD Interface] Mark bad block</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param mtd MTD device structure</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param ofs Bad block number</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_block_markbad(struct mtd_info *mtd, loff_t ofs)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *chip = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spi_device *spi_nand = chip->spi_nand;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_info *info = chip->info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 block_id;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 is_bad = 0x00; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 ret = 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_get_device(mtd, FL_WRITING);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ block_id = ofs >> info->block_shift;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->program_page(spi_nand, info, block_id*info->page_num_per_block, info->page_main_size, 1, &is_bad);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_release_device(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return ret;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_suspend - [MTD Interface] Suspend the spinand flash</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param mtd MTD device structure</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static int spinand_suspend(struct mtd_info *mtd)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return spinand_get_device(mtd, FL_PM_SUSPENDED);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_resume - [MTD Interface] Resume the spinand flash</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param mtd MTD device structure</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+static void spinand_resume(struct mtd_info *mtd)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *this = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ if (this->state == FL_PM_SUSPENDED)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_release_device(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ else</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ printk(KERN_ERR "resume() called for the chip which is not"</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ "in suspended state\n");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/**</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * spinand_mtd - add MTD device with parameters</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * @param mtd MTD device structure</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Add MTD device with parameters.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+int spinand_mtd(struct mtd_info *mtd)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_chip *chip = mtd->priv;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_info *info = chip->info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ chip->state = FL_READY;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ init_waitqueue_head(&chip->wq);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spin_lock_init(&chip->chip_lock);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->name = info->name;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->size = info->usable_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->erasesize = info->block_main_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->writesize = info->page_main_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->oobsize = info->ecclayout->oobavail;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->owner = THIS_MODULE;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->type = MTD_NANDFLASH;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->flags = MTD_CAP_NANDFLASH;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->ecclayout = info->ecclayout;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->erase = spinand_erase;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->point = NULL;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->unpoint = NULL;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->read = spinand_read;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->write = spinand_write;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->read_oob = spinand_read_oob;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->write_oob = spinand_write_oob;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->sync = spinand_sync;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->lock = NULL;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->unlock = NULL;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->suspend = spinand_suspend;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->resume = spinand_resume;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->block_isbad = spinand_block_isbad;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ mtd->block_markbad = spinand_block_markbad;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ return add_mtd_device(mtd) == 1 ? -ENODEV : 0;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+void spinand_mtd_release(struct mtd_info *mtd)</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+{</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ del_mtd_device(mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+}</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+EXPORT_SYMBOL_GPL(spinand_mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+MODULE_LICENSE("GPL");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+MODULE_AUTHOR("Henry Pan <hspan@micron.com>");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+MODULE_DESCRIPTION("SPI NAND driver code");</FONT>
<BR><FONT SIZE=2 FACE="Courier New">diff -urN linux-2.6.33.20-orig/include/linux/mtd/spinand.h linux-2.6.33.20/include/linux/mtd/spinand.h</FONT>
<BR><FONT SIZE=2 FACE="Courier New">--- linux-2.6.33.20-orig/include/linux/mtd/spinand.h 1969-12-31 16:00:00.000000000 -0800</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+++ linux-2.6.33.20/include/linux/mtd/spinand.h 2010-05-19 04:28:07.000000000 -0700</FONT>
<BR><FONT SIZE=2 FACE="Courier New">@@ -0,0 +1,160 @@</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/*</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * linux/include/linux/mtd/spinand.h</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ Copyright (c) 2009-2010 Micron Technology, Inc.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+This software is licensed under the terms of the GNU General Public</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+License version 2, as published by the Free Software Foundation, and</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+may be copied, distributed, and modified under those terms.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+This program is distributed in the hope that it will be useful,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+but WITHOUT ANY WARRANTY; without even the implied warranty of</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+GNU General Public License for more details.</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * Henry Pan <hspan@micron.com></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ *</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ * based on nand.h</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#ifndef __LINUX_MTD_SPI_NAND_H</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define __LINUX_MTD_SPI_NAND_H</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/wait.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/spinlock.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#include <linux/mtd/mtd.h></FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/* cmd */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_READ 0x13</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_READ_RDM 0x03</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_PROG_PAGE_CLRCACHE 0x02</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_PROG_PAGE 0x84</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_PROG_PAGE_EXC 0x10</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_ERASE_BLK 0xd8</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_WR_ENABLE 0x06</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_WR_DISABLE 0x04</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_READ_ID 0x9f</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_RESET 0xff</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_READ_REG 0x0f</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define CMD_WRITE_REG 0x1f</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/* feature/ status reg */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define REG_BLOCK_LOCK 0xa0</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define REG_OTP 0xb0</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define REG_STATUS 0xc0/* timing */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/* status */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_OIP_MASK 0x01</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_READY 0 << 0</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_BUSY 1 << 0</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_E_FAIL_MASK 0x04</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_E_FAIL 1 << 2</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_P_FAIL_MASK 0x08</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_P_FAIL 1 << 3</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_ECC_MASK 0x30</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_ECC_1BIT_CORRECTED 1 << 4</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_ECC_ERROR 2 << 4</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define STATUS_ECC_RESERVED 3 << 4</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/*ECC enable defines*/</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define OTP_ECC_MASK 0x10</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define OTP_ECC_OFF 0</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define OTP_ECC_ON 1</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define ECC_DISABLED</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define ECC_IN_NAND </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define ECC_SOFT</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/* block lock */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define BL_ALL_LOCKED 0x38 </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define BL_1_2_LOCKED 0x30</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define BL_1_4_LOCKED 0x28</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define BL_1_8_LOCKED 0x20</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define BL_1_16_LOCKED 0x18</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define BL_1_32_LOCKED 0x10</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define BL_1_64_LOCKED 0x08</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#define BL_ALL_UNLOCKED 0</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+/****************************************************************************/</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+struct spinand_info {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 mid;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 did;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ char *name;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u64 nand_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u64 usable_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u32 block_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u32 block_main_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /*u32 block_spare_size; */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 block_num_per_chip;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 page_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 page_main_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 page_spare_size;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 page_num_per_block;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 block_shift;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u32 block_mask;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 page_shift;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u16 page_mask;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct nand_ecclayout *ecclayout;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+typedef enum {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ FL_READY,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ FL_READING,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ FL_WRITING,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ FL_ERASING,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ FL_SYNCING,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ FL_LOCKING,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ FL_RESETING,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ FL_OTPING,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ FL_PM_SUSPENDED,</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+} spinand_state_t;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+struct spinand_chip { /* used for multi chip */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinlock_t chip_lock;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ wait_queue_head_t wq; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ spinand_state_t state;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spi_device *spi_nand;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ struct spinand_info *info;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ /*struct mtd_info *mtd; */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int (*reset) (struct spi_device *spi_nand);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int (*read_id) (struct spi_device *spi_nand, u8* id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ int (*read_page) (struct spi_device *spi_nand, struct spinand_info *info, u16 page_id, u16 offset, u16 len, u8* rbuf);</FONT></P>
<P><FONT SIZE=2 FACE="Courier New">+ int (*program_page) (struct spi_device *spi_nand, struct spinand_info *info, u16 page_id, u16 offset, u16 len, u8* wbuf);</FONT></P>
<P><FONT SIZE=2 FACE="Courier New">+ int (*erase_block) (struct spi_device *spi_nand, struct spinand_info *info, u16 block_id);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 *buf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 *oobbuf; /* temp buffer */</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#ifdef CONFIG_MTD_SPINAND_SWECC</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 ecc_calc[12];</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 ecc_code[12];</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#endif</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+struct spinand_cmd {</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 cmd;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ unsigned n_addr; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 addr[3];</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ unsigned n_dummy;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ unsigned n_tx; </FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 *tx_buf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ unsigned n_rx;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+ u8 *rx_buf;</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+};</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+extern int spinand_mtd(struct mtd_info *mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+extern void spinand_mtd_release(struct mtd_info *mtd);</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+</FONT>
<BR><FONT SIZE=2 FACE="Courier New">+#endif /* __LINUX_MTD_SPI_NAND_H */</FONT>
</P>
</BODY>
</HTML>