提交 178f16db 编写于 作者: G Greg Kroah-Hartman
......@@ -97,6 +97,8 @@ source "drivers/staging/octeon/Kconfig"
source "drivers/staging/serqt_usb2/Kconfig"
source "drivers/staging/spectra/Kconfig"
source "drivers/staging/quatech_usb2/Kconfig"
source "drivers/staging/vt6655/Kconfig"
......
......@@ -22,6 +22,7 @@ obj-$(CONFIG_R8187SE) += rtl8187se/
obj-$(CONFIG_RTL8192SU) += rtl8192su/
obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_SPECTRA) += spectra/
obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_DREAM) += dream/
obj-$(CONFIG_POHMELFS) += pohmelfs/
......
menuconfig SPECTRA
tristate "Denali Spectra Flash Translation Layer"
depends on BLOCK
default n
---help---
Enable the FTL pseudo-filesystem used with the NAND Flash
controller on Intel Moorestown Platform to pretend to be a disk
choice
prompt "Compile for"
depends on SPECTRA
default SPECTRA_MRST_HW
config SPECTRA_MRST_HW
bool "Moorestown hardware mode"
help
Driver communicates with the Moorestown hardware's register interface.
in DMA mode.
config SPECTRA_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 SPECTRA_EMU
bool "RAM emulator testing"
help
Driver emulates Flash on a RAM buffer and / or disk file. Useful to test the behavior of FTL layer.
endchoice
config SPECTRA_MRST_HW_DMA
bool
default n
depends on SPECTRA_MRST_HW
help
Use DMA for native hardware interface.
#
# Makefile of Intel Moorestown NAND controller driver
#
obj-$(CONFIG_SPECTRA) += spectra.o
spectra-y := ffsport.o flash.o lld.o
spectra-$(CONFIG_SPECTRA_MRST_HW) += lld_nand.o
spectra-$(CONFIG_SPECTRA_MRST_HW_DMA) += lld_cdma.o
spectra-$(CONFIG_SPECTRA_EMU) += lld_emu.o
spectra-$(CONFIG_SPECTRA_MTD) += lld_mtd.o
This is a driver for NAND controller of Intel Moorestown platform.
This driver is a standalone linux block device driver, it acts as if it's a normal hard disk.
It includes three layer:
block layer interface - file ffsport.c
Flash Translation Layer (FTL) - file flash.c (implement the NAND flash Translation Layer, includs address mapping, garbage collection, wear-leveling and so on)
Low level layer - file lld_nand.c/lld_cdma.c/lld_emu.c (which implements actual controller hardware registers access)
This driver can be build as modules or build-in.
Dependency:
This driver has dependency on IA Firmware of Intel Moorestown platform.
It need the IA Firmware to create the block table for the first time.
And to validate this driver code without IA Firmware, you can change the
macro AUTO_FORMAT_FLASH from 0 to 1 in file spectraswconfig.h. Thus the
driver will erase the whole nand flash and create a new block table.
TODO:
- Enable Command DMA feature support
- lower the memory footprint
- Remove most of the unnecessary global variables
- Change all the upcase variable / functions name to lowercase
- Some other misc bugs
Please send patches to:
Greg Kroah-Hartman <gregkh@suse.de>
And Cc to: Gao Yunpeng <yunpeng.gao@intel.com>
/*
* 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 _FFSDEFS_
#define _FFSDEFS_
#define CLEAR 0 /*use this to clear a field instead of "fail"*/
#define SET 1 /*use this to set a field instead of "pass"*/
#define FAIL 1 /*failed flag*/
#define PASS 0 /*success flag*/
#define ERR -1 /*error flag*/
#define ERASE_CMD 10
#define WRITE_MAIN_CMD 11
#define READ_MAIN_CMD 12
#define WRITE_SPARE_CMD 13
#define READ_SPARE_CMD 14
#define WRITE_MAIN_SPARE_CMD 15
#define READ_MAIN_SPARE_CMD 16
#define MEMCOPY_CMD 17
#define DUMMY_CMD 99
#define EVENT_PASS 0x00
#define EVENT_CORRECTABLE_DATA_ERROR_FIXED 0x01
#define EVENT_UNCORRECTABLE_DATA_ERROR 0x02
#define EVENT_TIME_OUT 0x03
#define EVENT_PROGRAM_FAILURE 0x04
#define EVENT_ERASE_FAILURE 0x05
#define EVENT_MEMCOPY_FAILURE 0x06
#define EVENT_FAIL 0x07
#define EVENT_NONE 0x22
#define EVENT_DMA_CMD_COMP 0x77
#define EVENT_ECC_TRANSACTION_DONE 0x88
#define EVENT_DMA_CMD_FAIL 0x99
#define CMD_PASS 0
#define CMD_FAIL 1
#define CMD_ABORT 2
#define CMD_NOT_DONE 3
#endif /* _FFSDEFS_ */
此差异已折叠。
/*
* 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 _FFSPORT_
#define _FFSPORT_
#include "ffsdefs.h"
#if defined __GNUC__
#define PACKED
#define PACKED_GNU __attribute__ ((packed))
#define UNALIGNED
#endif
#include <linux/semaphore.h>
#include <linux/string.h> /* for strcpy(), stricmp(), etc */
#include <linux/mm.h> /* for kmalloc(), kfree() */
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h> /* printk() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/pci.h>
#include "flash.h"
#define VERBOSE 1
#define NAND_DBG_WARN 1
#define NAND_DBG_DEBUG 2
#define NAND_DBG_TRACE 3
extern int nand_debug_level;
#ifdef VERBOSE
#define nand_dbg_print(level, args...) \
do { \
if (level <= nand_debug_level) \
printk(KERN_ALERT args); \
} while (0)
#else
#define nand_dbg_print(level, args...)
#endif
#ifdef SUPPORT_BIG_ENDIAN
#define INVERTUINT16(w) ((u16)(((u16)(w)) << 8) | \
(u16)((u16)(w) >> 8))
#define INVERTUINT32(dw) (((u32)(dw) << 24) | \
(((u32)(dw) << 8) & 0x00ff0000) | \
(((u32)(dw) >> 8) & 0x0000ff00) | \
((u32)(dw) >> 24))
#else
#define INVERTUINT16(w) w
#define INVERTUINT32(dw) dw
#endif
extern int GLOB_Calc_Used_Bits(u32 n);
extern u64 GLOB_u64_Div(u64 addr, u32 divisor);
extern u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type);
#endif /* _FFSPORT_ */
此差异已折叠。
/*
* 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 _FLASH_INTERFACE_
#define _FLASH_INTERFACE_
#include "ffsport.h"
#include "spectraswconfig.h"
#define MAX_BYTE_VALUE 0xFF
#define MAX_WORD_VALUE 0xFFFF
#define MAX_U32_VALUE 0xFFFFFFFF
#define MAX_BLOCKNODE_VALUE 0xFFFFFF
#define DISCARD_BLOCK 0x800000
#define SPARE_BLOCK 0x400000
#define BAD_BLOCK 0xC00000
#define UNHIT_CACHE_ITEM 0xFFFF
#define NAND_CACHE_INIT_ADDR 0xffffffffffffffffULL
#define IN_PROGRESS_BLOCK_TABLE 0x00
#define CURRENT_BLOCK_TABLE 0x01
#define BTSIG_OFFSET (0)
#define BTSIG_BYTES (5)
#define BTSIG_DELTA (3)
#define MAX_READ_COUNTER 0x2710
#define FIRST_BT_ID (1)
#define LAST_BT_ID (254)
#define BTBLOCK_INVAL (u32)(0xFFFFFFFF)
struct device_info_tag {
u16 wDeviceMaker;
u16 wDeviceID;
u32 wDeviceType;
u32 wSpectraStartBlock;
u32 wSpectraEndBlock;
u32 wTotalBlocks;
u16 wPagesPerBlock;
u16 wPageSize;
u16 wPageDataSize;
u16 wPageSpareSize;
u16 wNumPageSpareFlag;
u16 wECCBytesPerSector;
u32 wBlockSize;
u32 wBlockDataSize;
u32 wDataBlockNum;
u8 bPlaneNum;
u16 wDeviceMainAreaSize;
u16 wDeviceSpareAreaSize;
u16 wDevicesConnected;
u16 wDeviceWidth;
u16 wHWRevision;
u16 wHWFeatures;
u16 wONFIDevFeatures;
u16 wONFIOptCommands;
u16 wONFITimingMode;
u16 wONFIPgmCacheTimingMode;
u16 MLCDevice;
u16 wSpareSkipBytes;
u8 nBitsInPageNumber;
u8 nBitsInPageDataSize;
u8 nBitsInBlockDataSize;
};
extern struct device_info_tag DeviceInfo;
/* Cache item format */
struct flash_cache_item_tag {
u64 address;
u16 use_cnt;
u16 changed;
u8 *buf;
};
struct flash_cache_tag {
u32 cache_item_size; /* Size in bytes of each cache item */
u16 pages_per_item; /* How many NAND pages in each cache item */
u16 LRU; /* No. of the least recently used cache item */
struct flash_cache_item_tag array[CACHE_ITEM_NUM];
};
/*
*Data structure for each list node of the managment table
* used for the Level 2 Cache. Each node maps one logical NAND block.
*/
struct spectra_l2_cache_list {
struct list_head list;
u32 logical_blk_num; /* Logical block number */
u32 pages_array[]; /* Page map array of this logical block.
* Array index is the logical block number,
* and for every item of this arry:
* high 16 bit is index of the L2 cache block num,
* low 16 bit is the phy page num
* of the above L2 cache block.
* This array will be kmalloc during run time.
*/
};
struct spectra_l2_cache_info {
u32 blk_array[BLK_NUM_FOR_L2_CACHE];
u16 cur_blk_idx; /* idx to the phy block number of current using */
u16 cur_page_num; /* pages number of current using */
struct spectra_l2_cache_list table; /* First node of the table */
};
#define RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE 1
#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
struct flash_cache_mod_item_tag {
u64 address;
u8 changed;
};
struct flash_cache_delta_list_tag {
u8 item; /* used cache item */
struct flash_cache_mod_item_tag cache;
};
#endif
extern struct flash_cache_tag Cache;
extern u8 *buf_read_page_main_spare;
extern u8 *buf_write_page_main_spare;
extern u8 *buf_read_page_spare;
extern u8 *buf_get_bad_block;
extern u8 *cdma_desc_buf;
extern u8 *memcp_desc_buf;
/* struture used for IndentfyDevice function */
struct spectra_indentfy_dev_tag {
u32 NumBlocks;
u16 PagesPerBlock;
u16 PageDataSize;
u16 wECCBytesPerSector;
u32 wDataBlockNum;
};
int GLOB_FTL_Flash_Init(void);
int GLOB_FTL_Flash_Release(void);
/*void GLOB_FTL_Erase_Flash(void);*/
int GLOB_FTL_Block_Erase(u64 block_addr);
int GLOB_FTL_Is_BadBlock(u32 block_num);
int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data);
int GLOB_FTL_Event_Status(int *);
u16 glob_ftl_execute_cmds(void);
/*int FTL_Read_Disturbance(ADDRESSTYPE dwBlockAddr);*/
int FTL_Read_Disturbance(u32 dwBlockAddr);
/*Flash r/w based on cache*/
int GLOB_FTL_Page_Read(u8 *read_data, u64 page_addr);
int GLOB_FTL_Page_Write(u8 *write_data, u64 page_addr);
int GLOB_FTL_Wear_Leveling(void);
int GLOB_FTL_Flash_Format(void);
int GLOB_FTL_Init(void);
int GLOB_FTL_Flush_Cache(void);
int GLOB_FTL_Garbage_Collection(void);
int GLOB_FTL_BT_Garbage_Collection(void);
void GLOB_FTL_Cache_Release(void);
u8 *get_blk_table_start_addr(void);
u8 *get_wear_leveling_table_start_addr(void);
unsigned long get_blk_table_len(void);
unsigned long get_wear_leveling_table_len(void);
#if DEBUG_BNDRY
void debug_boundary_lineno_error(int chnl, int limit, int no, int lineno,
char *filename);
#define debug_boundary_error(chnl, limit, no) debug_boundary_lineno_error(chnl,\
limit, no, __LINE__, __FILE__)
#else
#define debug_boundary_error(chnl, limit, no) ;
#endif
#endif /*_FLASH_INTERFACE_*/
/*
* 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 "spectraswconfig.h"
#include "ffsport.h"
#include "ffsdefs.h"
#include "lld.h"
#include "lld_nand.h"
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
#if FLASH_EMU /* vector all the LLD calls to the LLD_EMU code */
#include "lld_emu.h"
#include "lld_cdma.h"
/* common functions: */
u16 GLOB_LLD_Flash_Reset(void)
{
return emu_Flash_Reset();
}
u16 GLOB_LLD_Read_Device_ID(void)
{
return emu_Read_Device_ID();
}
int GLOB_LLD_Flash_Release(void)
{
return emu_Flash_Release();
}
u16 GLOB_LLD_Flash_Init(void)
{
return emu_Flash_Init();
}
u16 GLOB_LLD_Erase_Block(u32 block_add)
{
return emu_Erase_Block(block_add);
}
u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page,
u16 PageCount)
{
return emu_Write_Page_Main(write_data, block, Page, PageCount);
}
u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page,
u16 PageCount)
{
return emu_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 emu_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 emu_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 emu_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 emu_Write_Page_Spare(write_data, block, Page, PageCount);
}
u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page,
u16 PageCount)
{
return emu_Read_Page_Spare(read_data, block, Page, PageCount);
}
u16 GLOB_LLD_Get_Bad_Block(u32 block)
{
return emu_Get_Bad_Block(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 */
#include "lld_nand.h"
#include "lld_cdma.h"
#include "flash.h"
/* common functions for LLD_NAND */
void GLOB_LLD_ECC_Control(int enable)
{
NAND_ECC_Ctrl(enable);
}
/* common functions for LLD_NAND */
u16 GLOB_LLD_Flash_Reset(void)
{
return NAND_Flash_Reset();
}
u16 GLOB_LLD_Read_Device_ID(void)
{
return NAND_Read_Device_ID();
}
u16 GLOB_LLD_UnlockArrayAll(void)
{
return NAND_UnlockArrayAll();
}
u16 GLOB_LLD_Flash_Init(void)
{
return NAND_Flash_Init();
}
int GLOB_LLD_Flash_Release(void)
{
return nand_release_spectra();
}
u16 GLOB_LLD_Erase_Block(u32 block_add)
{
return NAND_Erase_Block(block_add);
}
u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page,
u16 PageCount)
{
return NAND_Write_Page_Main(write_data, block, Page, PageCount);
}
u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 page,
u16 page_count)
{
if (page_count == 1) /* Using polling to improve read speed */
return NAND_Read_Page_Main_Polling(read_data, block, page, 1);
else
return NAND_Read_Page_Main(read_data, block, page, page_count);
}
u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
u32 block, u16 page, u16 page_count)
{
return NAND_Read_Page_Main_Polling(read_data,
block, page, page_count);
}
u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block,
u16 Page, u16 PageCount)
{
return NAND_Write_Page_Main_Spare(write_data, block, Page, PageCount);
}
u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page,
u16 PageCount)
{
return NAND_Write_Page_Spare(write_data, block, Page, PageCount);
}
u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block,
u16 page, u16 page_count)
{
return NAND_Read_Page_Main_Spare(read_data, block, page, page_count);
}
u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page,
u16 PageCount)
{
return NAND_Read_Page_Spare(read_data, block, Page, PageCount);
}
u16 GLOB_LLD_Get_Bad_Block(u32 block)
{
return NAND_Get_Bad_Block(block);
}
#if CMD_DMA
u16 GLOB_LLD_Event_Status(void)
{
return CDMA_Event_Status();
}
u16 glob_lld_execute_cmds(void)
{
return CDMA_Execute_CMDs();
}
u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src,
u32 ByteCount, u16 flag)
{
/* Replace the hardware memcopy with software memcpy function */
if (CDMA_Execute_CMDs())
return FAIL;
memcpy(dest, src, ByteCount);
return PASS;
/* return CDMA_MemCopy_CMD(dest, src, ByteCount, flag); */
}
u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags)
{
return CDMA_Data_CMD(ERASE_CMD, 0, block, 0, 0, flags);
}
u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, u32 block, u16 page, u16 count)
{
return CDMA_Data_CMD(WRITE_MAIN_CMD, data, block, page, count, 0);
}
u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, u32 block, u16 page,
u16 count, u16 flags)
{
return CDMA_Data_CMD(READ_MAIN_CMD, data, block, page, count, flags);
}
u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, u32 block, u16 page,
u16 count, u16 flags)
{
return CDMA_Data_CMD(WRITE_MAIN_SPARE_CMD,
data, block, page, count, flags);
}
u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data,
u32 block, u16 page, u16 count)
{
return CDMA_Data_CMD(READ_MAIN_SPARE_CMD, data, block, page, count,
LLD_CMD_FLAG_MODE_CDMA);
}
#endif /* CMD_DMA */
#endif /* FLASH_NAND */
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/* end of LLD.c */
/*
* 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_
#define _LLD_
#include "ffsport.h"
#include "spectraswconfig.h"
#include "flash.h"
#define GOOD_BLOCK 0
#define DEFECTIVE_BLOCK 1
#define READ_ERROR 2
#define CLK_X 5
#define CLK_MULTI 4
/* Typedefs */
/* prototypes: API for LLD */
/* Currently, Write_Page_Main
* MemCopy
* Read_Page_Main_Spare
* do not have flag because they were not implemented prior to this
* They are not being added to keep changes to a minimum for now.
* Currently, they are not required (only reqd for Wr_P_M_S.)
* Later on, these NEED to be changed.
*/
extern void GLOB_LLD_ECC_Control(int enable);
extern u16 GLOB_LLD_Flash_Reset(void);
extern u16 GLOB_LLD_Read_Device_ID(void);
extern u16 GLOB_LLD_UnlockArrayAll(void);
extern u16 GLOB_LLD_Flash_Init(void);
extern int GLOB_LLD_Flash_Release(void);
extern u16 GLOB_LLD_Erase_Block(u32 block_add);
extern u16 GLOB_LLD_Write_Page_Main(u8 *write_data,
u32 block, u16 Page, u16 PageCount);
extern u16 GLOB_LLD_Read_Page_Main(u8 *read_data,
u32 block, u16 page, u16 page_count);
extern u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
u32 block, u16 page, u16 page_count);
extern u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data,
u32 block, u16 Page, u16 PageCount);
extern u16 GLOB_LLD_Write_Page_Spare(u8 *write_data,
u32 block, u16 Page, u16 PageCount);
extern u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data,
u32 block, u16 page, u16 page_count);
extern u16 GLOB_LLD_Read_Page_Spare(u8 *read_data,
u32 block, u16 Page, u16 PageCount);
extern u16 GLOB_LLD_Get_Bad_Block(u32 block);
extern u16 GLOB_LLD_Event_Status(void);
extern u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, u32 ByteCount, u16 flag);
extern u16 glob_lld_execute_cmds(void);
extern u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags);
extern u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data,
u32 block, u16 page, u16 count);
extern u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data,
u32 block, u16 page, u16 count, u16 flags);
extern u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data,
u32 block, u16 page, u16 count, u16 flags);
extern u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data,
u32 block, u16 page, u16 count);
#define LLD_CMD_FLAG_ORDER_BEFORE_REST (0x1)
#define LLD_CMD_FLAG_MODE_CDMA (0x8)
#endif /*_LLD_ */
此差异已折叠。
/*
* 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.
*
*/
/* header for LLD_CDMA.c module */
#ifndef _LLD_CDMA_
#define _LLD_CDMA_
#include "flash.h"
#define DEBUG_SYNC 1
/*/////////// CDMA specific MACRO definition */
#define MAX_DESCS (255)
#define MAX_CHANS (4)
#define MAX_SYNC_POINTS (16)
#define MAX_DESC_PER_CHAN (MAX_DESCS * 3 + MAX_SYNC_POINTS + 2)
#define CHANNEL_SYNC_MASK (0x000F)
#define CHANNEL_DMA_MASK (0x00F0)
#define CHANNEL_ID_MASK (0x0300)
#define CHANNEL_CONT_MASK (0x4000)
#define CHANNEL_INTR_MASK (0x8000)
#define CHANNEL_SYNC_OFFSET (0)
#define CHANNEL_DMA_OFFSET (4)
#define CHANNEL_ID_OFFSET (8)
#define CHANNEL_CONT_OFFSET (14)
#define CHANNEL_INTR_OFFSET (15)
u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags);
u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags);
u16 CDMA_Execute_CMDs(void);
void print_pending_cmds(void);
void print_cdma_descriptors(void);
extern u8 g_SBDCmdIndex;
extern struct mrst_nand_info info;
/*/////////// prototypes: APIs for LLD_CDMA */
int is_cdma_interrupt(void);
u16 CDMA_Event_Status(void);
/* CMD-DMA Descriptor Struct. These are defined by the CMD_DMA HW */
struct cdma_descriptor {
u32 NxtPointerHi;
u32 NxtPointerLo;
u32 FlashPointerHi;
u32 FlashPointerLo;
u32 CommandType;
u32 MemAddrHi;
u32 MemAddrLo;
u32 CommandFlags;
u32 Channel;
u32 Status;
u32 MemCopyPointerHi;
u32 MemCopyPointerLo;
u32 Reserved12;
u32 Reserved13;
u32 Reserved14;
u32 pcmd; /* pending cmd num related to this descriptor */
};
/* This struct holds one MemCopy descriptor as defined by the HW */
struct memcpy_descriptor {
u32 NxtPointerHi;
u32 NxtPointerLo;
u32 SrcAddrHi;
u32 SrcAddrLo;
u32 DestAddrHi;
u32 DestAddrLo;
u32 XferSize;
u32 MemCopyFlags;
u32 MemCopyStatus;
u32 reserved9;
u32 reserved10;
u32 reserved11;
u32 reserved12;
u32 reserved13;
u32 reserved14;
u32 reserved15;
};
/* Pending CMD table entries (includes MemCopy parameters */
struct pending_cmd {
u8 CMD;
u8 *DataAddr;
u32 Block;
u16 Page;
u16 PageCount;
u8 *DataDestAddr;
u8 *DataSrcAddr;
u32 MemCopyByteCnt;
u16 Flags;
u16 Status;
};
#if DEBUG_SYNC
extern u32 debug_sync_cnt;
#endif
/* Definitions for CMD DMA descriptor chain fields */
#define CMD_DMA_DESC_COMP 0x8000
#define CMD_DMA_DESC_FAIL 0x4000
#endif /*_LLD_CDMA_*/
此差异已折叠。
/*
* 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_EMU_
#define _LLD_EMU_
#include "ffsport.h"
#include "ffsdefs.h"
/* prototypes: emulator API functions */
extern u16 emu_Flash_Reset(void);
extern u16 emu_Flash_Init(void);
extern int emu_Flash_Release(void);
extern u16 emu_Read_Device_ID(void);
extern u16 emu_Erase_Block(u32 block_addr);
extern u16 emu_Write_Page_Main(u8 *write_data, u32 Block,
u16 Page, u16 PageCount);
extern u16 emu_Read_Page_Main(u8 *read_data, u32 Block, u16 Page,
u16 PageCount);
extern u16 emu_Event_Status(void);
extern void emu_Enable_Disable_Interrupts(u16 INT_ENABLE);
extern u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block,
u16 Page, u16 PageCount);
extern u16 emu_Write_Page_Spare(u8 *write_data, u32 Block,
u16 Page, u16 PageCount);
extern u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block,
u16 Page, u16 PageCount);
extern u16 emu_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page,
u16 PageCount);
extern u16 emu_Get_Bad_Block(u32 block);
u16 emu_CDMA_Flash_Init(void);
u16 emu_CDMA_Execute_CMDs(u16 tag_count);
u16 emu_CDMA_Event_Status(void);
#endif /*_LLD_EMU_*/
/*
* 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)
{
uint64_t tmp;
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;
tmp = spectra_mtd->size;
do_div(tmp, spectra_mtd->erasesize);
DeviceInfo.wTotalBlocks = tmp;
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 */
/*
* 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_*/
此差异已折叠。
/*
* 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_NAND_
#define _LLD_NAND_
#ifdef ELDORA
#include "defs.h"
#else
#include "flash.h"
#include "ffsport.h"
#endif
#define MODE_00 0x00000000
#define MODE_01 0x04000000
#define MODE_10 0x08000000
#define MODE_11 0x0C000000
#define DATA_TRANSFER_MODE 0
#define PROTECTION_PER_BLOCK 1
#define LOAD_WAIT_COUNT 2
#define PROGRAM_WAIT_COUNT 3
#define ERASE_WAIT_COUNT 4
#define INT_MONITOR_CYCLE_COUNT 5
#define READ_BUSY_PIN_ENABLED 6
#define MULTIPLANE_OPERATION_SUPPORT 7
#define PRE_FETCH_MODE 8
#define CE_DONT_CARE_SUPPORT 9
#define COPYBACK_SUPPORT 10
#define CACHE_WRITE_SUPPORT 11
#define CACHE_READ_SUPPORT 12
#define NUM_PAGES_IN_BLOCK 13
#define ECC_ENABLE_SELECT 14
#define WRITE_ENABLE_2_READ_ENABLE 15
#define ADDRESS_2_DATA 16
#define READ_ENABLE_2_WRITE_ENABLE 17
#define TWO_ROW_ADDRESS_CYCLES 18
#define MULTIPLANE_ADDRESS_RESTRICT 19
#define ACC_CLOCKS 20
#define READ_WRITE_ENABLE_LOW_COUNT 21
#define READ_WRITE_ENABLE_HIGH_COUNT 22
#define ECC_SECTOR_SIZE 512
#define LLD_MAX_FLASH_BANKS 4
struct mrst_nand_info {
struct pci_dev *dev;
u32 state;
u32 flash_bank;
u8 *read_data;
u8 *write_data;
u32 block;
u16 page;
u32 use_dma;
void __iomem *ioaddr; /* Mapped io reg base address */
int ret;
u32 pcmds_num;
struct pending_cmd *pcmds;
int cdma_num; /* CDMA descriptor number in this chan */
u8 *cdma_desc_buf; /* CDMA descriptor table */
u8 *memcp_desc_buf; /* Memory copy descriptor table */
dma_addr_t cdma_desc; /* Mapped CDMA descriptor table */
dma_addr_t memcp_desc; /* Mapped memory copy descriptor table */
struct completion complete;
};
int NAND_Flash_Init(void);
int nand_release_spectra(void);
u16 NAND_Flash_Reset(void);
u16 NAND_Read_Device_ID(void);
u16 NAND_Erase_Block(u32 flash_add);
u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page,
u16 page_count);
u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page,
u16 page_count);
u16 NAND_UnlockArrayAll(void);
u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block,
u16 page, u16 page_count);
u16 NAND_Write_Page_Spare(u8 *read_data, u32 block, u16 page,
u16 page_count);
u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page,
u16 page_count);
u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page,
u16 page_count);
void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE);
u16 NAND_Get_Bad_Block(u32 block);
u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, u16 page,
u16 page_count);
u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block,
u16 page, u16 page_count);
u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page,
u16 page_count);
u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page,
u16 page_count);
void NAND_ECC_Ctrl(int enable);
u16 NAND_Read_Page_Main_Polling(u8 *read_data,
u32 block, u16 page, u16 page_count);
u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data,
u32 block, u16 page, u16 page_count);
void Conv_Spare_Data_Log2Phy_Format(u8 *data);
void Conv_Spare_Data_Phy2Log_Format(u8 *data);
void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count);
void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count);
extern void __iomem *FlashReg;
extern void __iomem *FlashMem;
extern int totalUsedBanks;
extern u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS];
#endif /*_LLD_NAND_*/
此差异已折叠。
/*
* 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 _SPECTRASWCONFIG_
#define _SPECTRASWCONFIG_
/* NAND driver version */
#define GLOB_VERSION "driver version 20100311"
/***** Common Parameters *****/
#define RETRY_TIMES 3
#define READ_BADBLOCK_INFO 1
#define READBACK_VERIFY 0
#define AUTO_FORMAT_FLASH 0
/***** Cache Parameters *****/
#define CACHE_ITEM_NUM 128
#define BLK_NUM_FOR_L2_CACHE 16
/***** Block Table Parameters *****/
#define BLOCK_TABLE_INDEX 0
/***** Wear Leveling Parameters *****/
#define WEAR_LEVELING_GATE 0x10
#define WEAR_LEVELING_BLOCK_NUM 10
#define DEBUG_BNDRY 0
/***** Product Feature Support *****/
#define FLASH_EMU defined(CONFIG_SPECTRA_EMU)
#define FLASH_NAND defined(CONFIG_SPECTRA_MRST_HW)
#define FLASH_MTD defined(CONFIG_SPECTRA_MTD)
#define CMD_DMA defined(CONFIG_SPECTRA_MRST_HW_DMA)
#define SPECTRA_PARTITION_ID 0
/* Enable this macro if the number of flash blocks is larger than 16K. */
#define SUPPORT_LARGE_BLOCKNUM 1
/**** Block Table and Reserved Block Parameters *****/
#define SPECTRA_START_BLOCK 3
//#define NUM_FREE_BLOCKS_GATE 30
#define NUM_FREE_BLOCKS_GATE 60
/**** Hardware Parameters ****/
#define GLOB_HWCTL_REG_BASE 0xFFA40000
#define GLOB_HWCTL_REG_SIZE 4096
#define GLOB_HWCTL_MEM_BASE 0xFFA48000
#define GLOB_HWCTL_MEM_SIZE 4096
/* KBV - Updated to LNW scratch register address */
#define SCRATCH_REG_ADDR 0xFF108018
#define SCRATCH_REG_SIZE 64
#define GLOB_HWCTL_DEFAULT_BLKS 2048
#define SUPPORT_15BITECC 1
#define SUPPORT_8BITECC 1
#define ONFI_BLOOM_TIME 0
#define MODE5_WORKAROUND 1
#endif /*_SPECTRASWCONFIG_*/
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册