[PATCH 005/524] spectra: Add basic mtd support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: David Woodhouse <David.Woodhouse@xxxxxxxxx>

Signed-off-by: David Woodhouse <David.Woodhouse@xxxxxxxxx>
---
 drivers/block/spectra/Kconfig           |    7 +
 drivers/block/spectra/Makefile          |    1 +
 drivers/block/spectra/lld.c             |   79 ++++
 drivers/block/spectra/lld_mtd.c         |  684 +++++++++++++++++++++++++++++++
 drivers/block/spectra/lld_mtd.h         |   51 +++
 drivers/block/spectra/spectraswconfig.h |    1 +
 6 files changed, 823 insertions(+), 0 deletions(-)
 create mode 100644 drivers/block/spectra/lld_mtd.c
 create mode 100644 drivers/block/spectra/lld_mtd.h

diff --git a/drivers/block/spectra/Kconfig b/drivers/block/spectra/Kconfig
index dae951e..4bed96f 100644
--- a/drivers/block/spectra/Kconfig
+++ b/drivers/block/spectra/Kconfig
@@ -18,6 +18,13 @@ config MRST_NAND_HW
 	  Driver communicates with the actual hardware's register interface.
 	  in DMA mode.
 
+config MRST_NAND_MTD
+	bool "Linux MTD mode"
+	depends on MTD
+	help
+	  Driver communicates with the kernel MTD subsystem instead of its own
+	  built-in hardware driver.
+
 config MRST_NAND_EMU
 	bool "RAM emulator testing"
 	help
diff --git a/drivers/block/spectra/Makefile b/drivers/block/spectra/Makefile
index 8f5e017..2a94903 100644
--- a/drivers/block/spectra/Makefile
+++ b/drivers/block/spectra/Makefile
@@ -7,4 +7,5 @@ spectra-y := ffsport.o flash.o lld.o
 spectra-$(CONFIG_MRST_NAND_HW) += lld_nand.o 
 spectra-$(CONFIG_MRST_NAND_HW_DMA) += lld_cdma.o
 spectra-$(CONFIG_MRST_NAND_EMU) += lld_emu.o
+spectra-$(CONFIG_MRST_NAND_MTD) += lld_mtd.o
 
diff --git a/drivers/block/spectra/lld.c b/drivers/block/spectra/lld.c
index c9a3112..ac25eea 100644
--- a/drivers/block/spectra/lld.c
+++ b/drivers/block/spectra/lld.c
@@ -103,6 +103,85 @@ u16  GLOB_LLD_Get_Bad_Block(u32 block)
 
 #endif /* FLASH_EMU */
 
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+#if FLASH_MTD		/* vector all the LLD calls to the LLD_MTD code */
+#include "lld_mtd.h"
+#include "lld_cdma.h"
+
+/* common functions: */
+u16 GLOB_LLD_Flash_Reset(void)
+{
+	return mtd_Flash_Reset();
+}
+
+u16 GLOB_LLD_Read_Device_ID(void)
+{
+	return mtd_Read_Device_ID();
+}
+
+int GLOB_LLD_Flash_Release(void)
+{
+	return mtd_Flash_Release();
+}
+
+u16 GLOB_LLD_Flash_Init(void)
+{
+	return mtd_Flash_Init();
+}
+
+u16 GLOB_LLD_Erase_Block(u32 block_add)
+{
+	return mtd_Erase_Block(block_add);
+}
+
+u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page,
+				u16 PageCount)
+{
+	return mtd_Write_Page_Main(write_data, block, Page, PageCount);
+}
+
+u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page,
+			       u16 PageCount)
+{
+	return mtd_Read_Page_Main(read_data, block, Page, PageCount);
+}
+
+u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
+			u32 block, u16 page, u16 page_count)
+{
+	return mtd_Read_Page_Main(read_data, block, page, page_count);
+}
+
+u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block,
+				      u16 Page, u16 PageCount)
+{
+	return mtd_Write_Page_Main_Spare(write_data, block, Page, PageCount);
+}
+
+u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block,
+				     u16 Page, u16 PageCount)
+{
+	return mtd_Read_Page_Main_Spare(read_data, block, Page, PageCount);
+}
+
+u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page,
+				 u16 PageCount)
+{
+	return mtd_Write_Page_Spare(write_data, block, Page, PageCount);
+}
+
+u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page,
+				u16 PageCount)
+{
+	return mtd_Read_Page_Spare(read_data, block, Page, PageCount);
+}
+
+u16  GLOB_LLD_Get_Bad_Block(u32 block)
+{
+    return  mtd_Get_Bad_Block(block);
+}
+
+#endif /* FLASH_MTD */
 
 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
 #if FLASH_NAND	/* vector all the LLD calls to the NAND controller code */
diff --git a/drivers/block/spectra/lld_mtd.c b/drivers/block/spectra/lld_mtd.c
new file mode 100644
index 0000000..f5666a9
--- /dev/null
+++ b/drivers/block/spectra/lld_mtd.c
@@ -0,0 +1,684 @@
+/*
+ * NAND Flash Controller Device Driver
+ * Copyright (c) 2009, Intel Corporation and its suppliers.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include "flash.h"
+#include "ffsdefs.h"
+#include "lld_emu.h"
+#include "lld.h"
+#if CMD_DMA
+#include "lld_cdma.h"
+#endif
+
+#define GLOB_LLD_PAGES           64
+#define GLOB_LLD_PAGE_SIZE       (512+16)
+#define GLOB_LLD_PAGE_DATA_SIZE  512
+#define GLOB_LLD_BLOCKS          2048
+
+#if CMD_DMA
+#include "lld_cdma.h"
+u32 totalUsedBanks;
+u32 valid_banks[MAX_CHANS];
+#endif
+
+static struct mtd_info *spectra_mtd;
+static int mtddev = -1;
+module_param(mtddev, int, 0);
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Flash_Init
+* Inputs:       none
+* Outputs:      PASS=0 (notice 0=ok here)
+* Description:  Creates & initializes the flash RAM array.
+*
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_Flash_Init(void)
+{
+	if (mtddev == -1) {
+		printk(KERN_ERR "No MTD device specified. Give mtddev parameter\n");
+		return FAIL;
+	}
+
+	spectra_mtd = get_mtd_device(NULL, mtddev);
+	if (!spectra_mtd) {
+		printk(KERN_ERR "Failed to obtain MTD device #%d\n", mtddev);
+		return FAIL;
+	}
+
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	return PASS;
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Flash_Release
+* Inputs:       none
+* Outputs:      PASS=0 (notice 0=ok here)
+* Description:          Releases the flash.
+*
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+int mtd_Flash_Release(void)
+{
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+	if (!spectra_mtd)
+		return PASS;
+
+	put_mtd_device(spectra_mtd);
+	spectra_mtd = NULL;
+
+	return PASS;
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Read_Device_ID
+* Inputs:       none
+* Outputs:      PASS=1 FAIL=0
+* Description:  Reads the info from the controller registers.
+*               Sets up DeviceInfo structure with device parameters
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+
+u16 mtd_Read_Device_ID(void)
+{
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	if (!spectra_mtd)
+		return FAIL;
+
+	DeviceInfo.wDeviceMaker = 0;
+	DeviceInfo.wDeviceType = 8;
+	DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK;
+	DeviceInfo.wTotalBlocks = spectra_mtd->size / spectra_mtd->erasesize;
+	DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1;
+	DeviceInfo.wPagesPerBlock = spectra_mtd->erasesize / spectra_mtd->writesize;
+	DeviceInfo.wPageSize = spectra_mtd->writesize + spectra_mtd->oobsize;
+	DeviceInfo.wPageDataSize = spectra_mtd->writesize;
+	DeviceInfo.wPageSpareSize = spectra_mtd->oobsize;
+	DeviceInfo.wBlockSize = DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock;
+	DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * DeviceInfo.wPagesPerBlock;
+	DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock -
+						DeviceInfo.wSpectraStartBlock
+						+ 1);
+	DeviceInfo.MLCDevice = 0;//spectra_mtd->celltype & NAND_CI_CELLTYPE_MSK;
+	DeviceInfo.nBitsInPageNumber =
+		(u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock);
+	DeviceInfo.nBitsInPageDataSize =
+		(u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize);
+	DeviceInfo.nBitsInBlockDataSize =
+		(u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize);
+
+#if CMD_DMA
+	totalUsedBanks = 4;
+	valid_banks[0] = 1;
+	valid_banks[1] = 1;
+	valid_banks[2] = 1;
+	valid_banks[3] = 1;
+#endif
+
+	return PASS;
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Flash_Reset
+* Inputs:       none
+* Outputs:      PASS=0 (notice 0=ok here)
+* Description:          Reset the flash
+*
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_Flash_Reset(void)
+{
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	return PASS;
+}
+
+void erase_callback(struct erase_info *e)
+{
+	complete((void *)e->priv);
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Erase_Block
+* Inputs:       Address
+* Outputs:      PASS=0 (notice 0=ok here)
+* Description:          Erase a block
+*
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_Erase_Block(u32 block_add)
+{
+	struct erase_info erase;
+	DECLARE_COMPLETION_ONSTACK(comp);
+	int ret;
+
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	if (block_add >= DeviceInfo.wTotalBlocks) {
+		printk(KERN_ERR "mtd_Erase_Block error! "
+		       "Too big block address: %d\n", block_add);
+		return FAIL;
+	}
+
+	nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n",
+		(int)block_add);
+
+	erase.mtd = spectra_mtd;
+	erase.callback = erase_callback;
+	erase.addr = block_add * spectra_mtd->erasesize;
+	erase.len = spectra_mtd->erasesize;
+	erase.priv = (unsigned long)&comp;
+
+	ret = spectra_mtd->erase(spectra_mtd, &erase);
+	if (!ret) {
+		wait_for_completion(&comp);
+		if (erase.state != MTD_ERASE_DONE)
+			ret = -EIO;
+	}
+	if (ret) {
+		printk(KERN_WARNING "mtd_Erase_Block error! "
+		       "erase of region [0x%llx, 0x%llx] failed\n",
+		       erase.addr, erase.len);
+		return FAIL;
+	}
+
+	return PASS;
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Write_Page_Main
+* Inputs:       Write buffer address pointer
+*               Block number
+*               Page  number
+*               Number of pages to process
+* Outputs:      PASS=0 (notice 0=ok here)
+* Description:  Write the data in the buffer to main area of flash
+*
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_Write_Page_Main(u8 *write_data, u32 Block,
+			   u16 Page, u16 PageCount)
+{
+	size_t retlen;
+	int ret = 0;
+
+	if (Block >= DeviceInfo.wTotalBlocks)
+		return FAIL;
+
+	if (Page + PageCount > DeviceInfo.wPagesPerBlock)
+		return FAIL;
+
+	nand_dbg_print(NAND_DBG_DEBUG, "mtd_Write_Page_Main: "
+		       "lba %u Page %u PageCount %u\n",
+		       (unsigned int)Block,
+		       (unsigned int)Page, (unsigned int)PageCount);
+
+
+	while (PageCount) {
+		ret = spectra_mtd->write(spectra_mtd,
+					 (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
+					 DeviceInfo.wPageDataSize, &retlen, write_data);
+		if (ret) {
+			printk(KERN_ERR "%s failed %d\n", __func__, ret);
+			return FAIL;
+		}
+		write_data += DeviceInfo.wPageDataSize;
+		Page++;
+		PageCount--;
+	}
+
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	return PASS;
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Read_Page_Main
+* Inputs:       Read buffer address pointer
+*               Block number
+*               Page  number
+*               Number of pages to process
+* Outputs:      PASS=0 (notice 0=ok here)
+* Description:  Read the data from the flash main area to the buffer
+*
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_Read_Page_Main(u8 *read_data, u32 Block,
+			  u16 Page, u16 PageCount)
+{
+	size_t retlen;
+	int ret = 0;
+
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	if (Block >= DeviceInfo.wTotalBlocks)
+		return FAIL;
+
+	if (Page + PageCount > DeviceInfo.wPagesPerBlock)
+		return FAIL;
+
+	nand_dbg_print(NAND_DBG_DEBUG, "mtd_Read_Page_Main: "
+		       "lba %u Page %u PageCount %u\n",
+		       (unsigned int)Block,
+		       (unsigned int)Page, (unsigned int)PageCount);
+
+
+	while (PageCount) {
+		ret = spectra_mtd->read(spectra_mtd,
+					(Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
+					DeviceInfo.wPageDataSize, &retlen, read_data);
+		if (ret) {
+			printk(KERN_ERR "%s failed %d\n", __func__, ret);
+			return FAIL;
+		}
+		read_data += DeviceInfo.wPageDataSize;
+		Page++;
+		PageCount--;
+	}
+
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	return PASS;
+}
+
+#ifndef ELDORA
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Read_Page_Main_Spare
+* Inputs:       Write Buffer
+*                       Address
+*                       Buffer size
+* Outputs:      PASS=0 (notice 0=ok here)
+* Description:          Read from flash main+spare area
+*
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block,
+				u16 Page, u16 PageCount)
+{
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	if (Block >= DeviceInfo.wTotalBlocks) {
+		printk(KERN_ERR "Read Page Main+Spare "
+		       "Error: Block Address too big\n");
+		return FAIL;
+	}
+
+	if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
+		printk(KERN_ERR "Read Page Main+Spare "
+		       "Error: Page number %d+%d too big in block %d\n",
+		       Page, PageCount, Block);
+		return FAIL;
+	}
+
+	nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - "
+		       "No. of pages %u block %u start page %u\n",
+		       (unsigned int)PageCount,
+		       (unsigned int)Block, (unsigned int)Page);
+
+
+	while (PageCount) {
+		struct mtd_oob_ops ops;
+		int ret;
+
+		ops.mode = MTD_OOB_AUTO;
+		ops.datbuf = read_data;
+		ops.len = DeviceInfo.wPageDataSize;
+		ops.oobbuf = read_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET;
+		ops.ooblen = BTSIG_BYTES;
+		ops.ooboffs = 0;
+
+		ret = spectra_mtd->read_oob(spectra_mtd,
+					    (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
+					    &ops);
+		if (ret) {
+			printk(KERN_ERR "%s failed %d\n", __func__, ret);
+			return FAIL;
+		}
+		read_data += DeviceInfo.wPageSize;
+		Page++;
+		PageCount--;
+	}
+
+	return PASS;
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Write_Page_Main_Spare
+* Inputs:       Write buffer
+*                       address
+*                       buffer length
+* Outputs:      PASS=0 (notice 0=ok here)
+* Description:          Write the buffer to main+spare area of flash
+*
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block,
+				 u16 Page, u16 page_count)
+{
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	if (Block >= DeviceInfo.wTotalBlocks) {
+		printk(KERN_ERR "Write Page Main + Spare "
+		       "Error: Block Address too big\n");
+		return FAIL;
+	}
+
+	if (Page + page_count > DeviceInfo.wPagesPerBlock) {
+		printk(KERN_ERR "Write Page Main + Spare "
+		       "Error: Page number %d+%d too big in block %d\n",
+		       Page, page_count, Block);
+		WARN_ON(1);
+		return FAIL;
+	}
+
+	nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - "
+		       "No. of pages %u block %u start page %u\n",
+		       (unsigned int)page_count,
+		       (unsigned int)Block, (unsigned int)Page);
+
+	while (page_count) {
+		struct mtd_oob_ops ops;
+		int ret;
+
+		ops.mode = MTD_OOB_AUTO;
+		ops.datbuf = write_data;
+		ops.len = DeviceInfo.wPageDataSize;
+		ops.oobbuf = write_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET;
+		ops.ooblen = BTSIG_BYTES;
+		ops.ooboffs = 0;
+
+		ret = spectra_mtd->write_oob(spectra_mtd,
+					     (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
+					     &ops);
+		if (ret) {
+			printk(KERN_ERR "%s failed %d\n", __func__, ret);
+			return FAIL;
+		}
+		write_data += DeviceInfo.wPageSize;
+		Page++;
+		page_count--;
+	}
+
+	return PASS;
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Write_Page_Spare
+* Inputs:       Write buffer
+*                       Address
+*                       buffer size
+* Outputs:      PASS=0 (notice 0=ok here)
+* Description:          Write the buffer in the spare area
+*
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block,
+			    u16 Page, u16 PageCount)
+{
+	WARN_ON(1);
+	return FAIL;
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Read_Page_Spare
+* Inputs:       Write Buffer
+*                       Address
+*                       Buffer size
+* Outputs:      PASS=0 (notice 0=ok here)
+* Description:          Read data from the spare area
+*
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block,
+			   u16 Page, u16 PageCount)
+{
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	if (Block >= DeviceInfo.wTotalBlocks) {
+		printk(KERN_ERR "Read Page Spare "
+		       "Error: Block Address too big\n");
+		return FAIL;
+	}
+
+	if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
+		printk(KERN_ERR "Read Page Spare "
+		       "Error: Page number too big\n");
+		return FAIL;
+	}
+
+	nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- "
+		       "block %u page %u (%u pages)\n",
+		       (unsigned int)Block, (unsigned int)Page, PageCount);
+
+	while (PageCount) {
+		struct mtd_oob_ops ops;
+		int ret;
+
+		ops.mode = MTD_OOB_AUTO;
+		ops.datbuf = NULL;
+		ops.len = 0;
+		ops.oobbuf = read_data;
+		ops.ooblen = BTSIG_BYTES;
+		ops.ooboffs = 0;
+
+		ret = spectra_mtd->read_oob(spectra_mtd,
+					    (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
+					    &ops);
+		if (ret) {
+			printk(KERN_ERR "%s failed %d\n", __func__, ret);
+			return FAIL;
+		}
+
+		read_data += DeviceInfo.wPageSize;
+		Page++;
+		PageCount--;
+	}
+
+	return PASS;
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Enable_Disable_Interrupts
+* Inputs:       enable or disable
+* Outputs:      none
+* Description:  NOP
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE)
+{
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+}
+
+u16 mtd_Get_Bad_Block(u32 block)
+{
+	return 0;
+}
+
+#if CMD_DMA
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Support for CDMA functions
+************************************
+*       mtd_CDMA_Flash_Init
+*           CDMA_process_data command   (use LLD_CDMA)
+*           CDMA_MemCopy_CMD            (use LLD_CDMA)
+*       mtd_CDMA_execute all commands
+*       mtd_CDMA_Event_Status
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_CDMA_Flash_Init(void)
+{
+	u16 i;
+
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) {
+		PendingCMD[i].CMD = 0;
+		PendingCMD[i].Tag = 0;
+		PendingCMD[i].DataAddr = 0;
+		PendingCMD[i].Block = 0;
+		PendingCMD[i].Page = 0;
+		PendingCMD[i].PageCount = 0;
+		PendingCMD[i].DataDestAddr = 0;
+		PendingCMD[i].DataSrcAddr = 0;
+		PendingCMD[i].MemCopyByteCnt = 0;
+		PendingCMD[i].ChanSync[0] = 0;
+		PendingCMD[i].ChanSync[1] = 0;
+		PendingCMD[i].ChanSync[2] = 0;
+		PendingCMD[i].ChanSync[3] = 0;
+		PendingCMD[i].ChanSync[4] = 0;
+		PendingCMD[i].Status = 3;
+	}
+
+	return PASS;
+}
+
+static void mtd_isr(int irq, void *dev_id)
+{
+	/* TODO:  ... */
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     CDMA_Execute_CMDs
+* Inputs:       tag_count:  the number of pending cmds to do
+* Outputs:      PASS/FAIL
+* Description:  execute each command in the pending CMD array
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_CDMA_Execute_CMDs(u16 tag_count)
+{
+	u16 i, j;
+	u8 CMD;		/* cmd parameter */
+	u8 *data;
+	u32 block;
+	u16 page;
+	u16 count;
+	u16 status = PASS;
+
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: "
+		       "Tag Count %u\n", tag_count);
+
+	for (i = 0; i < totalUsedBanks; i++) {
+		PendingCMD[i].CMD = DUMMY_CMD;
+		PendingCMD[i].Tag = 0xFF;
+		PendingCMD[i].Block =
+		    (DeviceInfo.wTotalBlocks / totalUsedBanks) * i;
+
+		for (j = 0; j <= MAX_CHANS; j++)
+			PendingCMD[i].ChanSync[j] = 0;
+	}
+
+	CDMA_Execute_CMDs(tag_count);
+
+#ifdef VERBOSE
+		print_pending_cmds(tag_count);
+#endif
+#if DEBUG_SYNC
+	}
+	debug_sync_cnt++;
+#endif
+
+	for (i = MAX_CHANS;
+	     i < tag_count + MAX_CHANS; i++) {
+		CMD = PendingCMD[i].CMD;
+		data = PendingCMD[i].DataAddr;
+		block = PendingCMD[i].Block;
+		page = PendingCMD[i].Page;
+		count = PendingCMD[i].PageCount;
+
+		switch (CMD) {
+		case ERASE_CMD:
+			mtd_Erase_Block(block);
+			PendingCMD[i].Status = PASS;
+			break;
+		case WRITE_MAIN_CMD:
+			mtd_Write_Page_Main(data, block, page, count);
+			PendingCMD[i].Status = PASS;
+			break;
+		case WRITE_MAIN_SPARE_CMD:
+			mtd_Write_Page_Main_Spare(data, block, page, count);
+			PendingCMD[i].Status = PASS;
+			break;
+		case READ_MAIN_CMD:
+			mtd_Read_Page_Main(data, block, page, count);
+			PendingCMD[i].Status = PASS;
+			break;
+		case MEMCOPY_CMD:
+			memcpy(PendingCMD[i].DataDestAddr,
+			       PendingCMD[i].DataSrcAddr,
+			       PendingCMD[i].MemCopyByteCnt);
+		case DUMMY_CMD:
+			PendingCMD[i].Status = PASS;
+			break;
+		default:
+			PendingCMD[i].Status = FAIL;
+			break;
+		}
+	}
+
+	/*
+	 * Temperory adding code to reset PendingCMD array for basic testing.
+	 * It should be done at the end of  event status function.
+	 */
+	for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) {
+		PendingCMD[i].CMD = 0;
+		PendingCMD[i].Tag = 0;
+		PendingCMD[i].DataAddr = 0;
+		PendingCMD[i].Block = 0;
+		PendingCMD[i].Page = 0;
+		PendingCMD[i].PageCount = 0;
+		PendingCMD[i].DataDestAddr = 0;
+		PendingCMD[i].DataSrcAddr = 0;
+		PendingCMD[i].MemCopyByteCnt = 0;
+		PendingCMD[i].ChanSync[0] = 0;
+		PendingCMD[i].ChanSync[1] = 0;
+		PendingCMD[i].ChanSync[2] = 0;
+		PendingCMD[i].ChanSync[3] = 0;
+		PendingCMD[i].ChanSync[4] = 0;
+		PendingCMD[i].Status = CMD_NOT_DONE;
+	}
+
+	nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n");
+
+	mtd_isr(0, 0); /* This is a null isr now. Need fill it in future */
+
+	return status;
+}
+
+/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+* Function:     mtd_Event_Status
+* Inputs:       none
+* Outputs:      Event_Status code
+* Description:  This function can also be used to force errors
+*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
+u16 mtd_CDMA_Event_Status(void)
+{
+	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
+		       __FILE__, __LINE__, __func__);
+
+	return EVENT_PASS;
+}
+
+#endif /* CMD_DMA */
+#endif /* !ELDORA */
diff --git a/drivers/block/spectra/lld_mtd.h b/drivers/block/spectra/lld_mtd.h
new file mode 100644
index 0000000..4e81ee8
--- /dev/null
+++ b/drivers/block/spectra/lld_mtd.h
@@ -0,0 +1,51 @@
+/*
+ * NAND Flash Controller Device Driver
+ * Copyright (c) 2009, Intel Corporation and its suppliers.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _LLD_MTD_
+#define _LLD_MTD_
+
+#include "ffsport.h"
+#include "ffsdefs.h"
+
+/* prototypes: MTD API functions */
+extern u16 mtd_Flash_Reset(void);
+extern u16 mtd_Flash_Init(void);
+extern int mtd_Flash_Release(void);
+extern u16 mtd_Read_Device_ID(void);
+extern u16 mtd_Erase_Block(u32 block_addr);
+extern u16 mtd_Write_Page_Main(u8 *write_data, u32 Block,
+				u16 Page, u16 PageCount);
+extern u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, u16 Page,
+				 u16 PageCount);
+extern u16 mtd_Event_Status(void);
+extern void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE);
+extern u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block,
+					u16 Page, u16 PageCount);
+extern u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block,
+					u16 Page, u16 PageCount);
+extern u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block,
+				       u16 Page, u16 PageCount);
+extern u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page,
+				  u16 PageCount);
+extern u16 mtd_Get_Bad_Block(u32 block);
+
+u16 mtd_CDMA_Flash_Init(void);
+u16 mtd_CDMA_Execute_CMDs(u16 tag_count);
+u16 mtd_CDMA_Event_Status(void);
+#endif /*_LLD_MTD_*/
diff --git a/drivers/block/spectra/spectraswconfig.h b/drivers/block/spectra/spectraswconfig.h
index 1e6afd3..557c091 100644
--- a/drivers/block/spectra/spectraswconfig.h
+++ b/drivers/block/spectra/spectraswconfig.h
@@ -47,6 +47,7 @@
 /***** Product Feature Support *****/
 #define FLASH_EMU               defined(CONFIG_MRST_NAND_EMU)
 #define FLASH_NAND              defined(CONFIG_MRST_NAND_HW)
+#define FLASH_MTD               defined(CONFIG_MRST_NAND_MTD)
 #define CMD_DMA                 defined(CONFIG_MRST_NAND_HW_DMA)
 
 #define SPECTRA_PARTITION_ID    0
-- 
1.7.1

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux