Staging: delete spectra driver
To quote Alan: Moorestown/Oaktrail has appeared only in the PC like form so the following bits of staging can be binned: drivers/staging/spectra so let's delete it. Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
9dc367bc4c
commit
be7f39c5ec
|
@ -72,8 +72,6 @@ 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"
|
||||
|
|
|
@ -21,7 +21,6 @@ obj-$(CONFIG_RTL8192E) += rtl8192e/
|
|||
obj-$(CONFIG_R8712U) += rtl8712/
|
||||
obj-$(CONFIG_RTS_PSTOR) += rts_pstor/
|
||||
obj-$(CONFIG_RTS5139) += rts5139/
|
||||
obj-$(CONFIG_SPECTRA) += spectra/
|
||||
obj-$(CONFIG_TRANZPORT) += frontier/
|
||||
obj-$(CONFIG_POHMELFS) += pohmelfs/
|
||||
obj-$(CONFIG_IDE_PHISON) += phison/
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
|
||||
menuconfig SPECTRA
|
||||
tristate "Denali Spectra Flash Translation Layer"
|
||||
depends on BLOCK
|
||||
depends on X86_MRST
|
||||
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.
|
|
@ -1,11 +0,0 @@
|
|||
#
|
||||
# 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
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
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>
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* 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_ */
|
|
@ -1,834 +0,0 @@
|
|||
/*
|
||||
* 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 "ffsport.h"
|
||||
#include "flash.h"
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/async.h>
|
||||
|
||||
/**** Helper functions used for Div, Remainder operation on u64 ****/
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: GLOB_Calc_Used_Bits
|
||||
* Inputs: Power of 2 number
|
||||
* Outputs: Number of Used Bits
|
||||
* 0, if the argument is 0
|
||||
* Description: Calculate the number of bits used by a given power of 2 number
|
||||
* Number can be up to 32 bit
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
int GLOB_Calc_Used_Bits(u32 n)
|
||||
{
|
||||
int tot_bits = 0;
|
||||
|
||||
if (n >= 1 << 16) {
|
||||
n >>= 16;
|
||||
tot_bits += 16;
|
||||
}
|
||||
|
||||
if (n >= 1 << 8) {
|
||||
n >>= 8;
|
||||
tot_bits += 8;
|
||||
}
|
||||
|
||||
if (n >= 1 << 4) {
|
||||
n >>= 4;
|
||||
tot_bits += 4;
|
||||
}
|
||||
|
||||
if (n >= 1 << 2) {
|
||||
n >>= 2;
|
||||
tot_bits += 2;
|
||||
}
|
||||
|
||||
if (n >= 1 << 1)
|
||||
tot_bits += 1;
|
||||
|
||||
return ((n == 0) ? (0) : tot_bits);
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: GLOB_u64_Div
|
||||
* Inputs: Number of u64
|
||||
* A power of 2 number as Division
|
||||
* Outputs: Quotient of the Divisor operation
|
||||
* Description: It divides the address by divisor by using bit shift operation
|
||||
* (essentially without explicitely using "/").
|
||||
* Divisor is a power of 2 number and Divided is of u64
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u64 GLOB_u64_Div(u64 addr, u32 divisor)
|
||||
{
|
||||
return (u64)(addr >> GLOB_Calc_Used_Bits(divisor));
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: GLOB_u64_Remainder
|
||||
* Inputs: Number of u64
|
||||
* Divisor Type (1 -PageAddress, 2- BlockAddress)
|
||||
* Outputs: Remainder of the Division operation
|
||||
* Description: It calculates the remainder of a number (of u64) by
|
||||
* divisor(power of 2 number ) by using bit shifting and multiply
|
||||
* operation(essentially without explicitely using "/").
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type)
|
||||
{
|
||||
u64 result = 0;
|
||||
|
||||
if (divisor_type == 1) { /* Remainder -- Page */
|
||||
result = (addr >> DeviceInfo.nBitsInPageDataSize);
|
||||
result = result * DeviceInfo.wPageDataSize;
|
||||
} else if (divisor_type == 2) { /* Remainder -- Block */
|
||||
result = (addr >> DeviceInfo.nBitsInBlockDataSize);
|
||||
result = result * DeviceInfo.wBlockDataSize;
|
||||
}
|
||||
|
||||
result = addr - result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define NUM_DEVICES 1
|
||||
#define PARTITIONS 8
|
||||
|
||||
#define GLOB_SBD_NAME "nd"
|
||||
#define GLOB_SBD_IRQ_NUM (29)
|
||||
|
||||
#define GLOB_SBD_IOCTL_GC (0x7701)
|
||||
#define GLOB_SBD_IOCTL_WL (0x7702)
|
||||
#define GLOB_SBD_IOCTL_FORMAT (0x7703)
|
||||
#define GLOB_SBD_IOCTL_ERASE_FLASH (0x7704)
|
||||
#define GLOB_SBD_IOCTL_FLUSH_CACHE (0x7705)
|
||||
#define GLOB_SBD_IOCTL_COPY_BLK_TABLE (0x7706)
|
||||
#define GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE (0x7707)
|
||||
#define GLOB_SBD_IOCTL_GET_NAND_INFO (0x7708)
|
||||
#define GLOB_SBD_IOCTL_WRITE_DATA (0x7709)
|
||||
#define GLOB_SBD_IOCTL_READ_DATA (0x770A)
|
||||
|
||||
static int reserved_mb = 0;
|
||||
module_param(reserved_mb, int, 0);
|
||||
MODULE_PARM_DESC(reserved_mb, "Reserved space for OS image, in MiB (default 25 MiB)");
|
||||
|
||||
int nand_debug_level;
|
||||
module_param(nand_debug_level, int, 0644);
|
||||
MODULE_PARM_DESC(nand_debug_level, "debug level value: 1-3");
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
struct spectra_nand_dev {
|
||||
struct pci_dev *dev;
|
||||
u64 size;
|
||||
u16 users;
|
||||
spinlock_t qlock;
|
||||
void __iomem *ioaddr; /* Mapped address */
|
||||
struct request_queue *queue;
|
||||
struct task_struct *thread;
|
||||
struct gendisk *gd;
|
||||
u8 *tmp_buf;
|
||||
};
|
||||
|
||||
|
||||
static int GLOB_SBD_majornum;
|
||||
|
||||
static char *GLOB_version = GLOB_VERSION;
|
||||
|
||||
static struct spectra_nand_dev nand_device[NUM_DEVICES];
|
||||
|
||||
static struct mutex spectra_lock;
|
||||
|
||||
static int res_blks_os = 1;
|
||||
|
||||
struct spectra_indentfy_dev_tag IdentifyDeviceData;
|
||||
|
||||
static int force_flush_cache(void)
|
||||
{
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
if (ERR == GLOB_FTL_Flush_Cache()) {
|
||||
printk(KERN_ERR "Fail to Flush FTL Cache!\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
#if CMD_DMA
|
||||
if (glob_ftl_execute_cmds())
|
||||
return -EIO;
|
||||
else
|
||||
return 0;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ioctl_rw_page_info {
|
||||
u8 *data;
|
||||
unsigned int page;
|
||||
};
|
||||
|
||||
static int ioctl_read_page_data(unsigned long arg)
|
||||
{
|
||||
u8 *buf;
|
||||
struct ioctl_rw_page_info info;
|
||||
int result = PASS;
|
||||
|
||||
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
|
||||
return -EFAULT;
|
||||
|
||||
buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC);
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "ioctl_read_page_data: "
|
||||
"failed to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_lock(&spectra_lock);
|
||||
result = GLOB_FTL_Page_Read(buf,
|
||||
(u64)info.page * IdentifyDeviceData.PageDataSize);
|
||||
mutex_unlock(&spectra_lock);
|
||||
|
||||
if (copy_to_user((void __user *)info.data, buf,
|
||||
IdentifyDeviceData.PageDataSize)) {
|
||||
printk(KERN_ERR "ioctl_read_page_data: "
|
||||
"failed to copy user data\n");
|
||||
kfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ioctl_write_page_data(unsigned long arg)
|
||||
{
|
||||
u8 *buf;
|
||||
struct ioctl_rw_page_info info;
|
||||
int result = PASS;
|
||||
|
||||
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
|
||||
return -EFAULT;
|
||||
|
||||
buf = memdup_user((void __user *)info.data,
|
||||
IdentifyDeviceData.PageDataSize);
|
||||
if (IS_ERR(buf)) {
|
||||
printk(KERN_ERR "ioctl_write_page_data: "
|
||||
"failed to copy user data\n");
|
||||
return PTR_ERR(buf);
|
||||
}
|
||||
|
||||
mutex_lock(&spectra_lock);
|
||||
result = GLOB_FTL_Page_Write(buf,
|
||||
(u64)info.page * IdentifyDeviceData.PageDataSize);
|
||||
mutex_unlock(&spectra_lock);
|
||||
|
||||
kfree(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return how many blocks should be reserved for bad block replacement */
|
||||
static int get_res_blk_num_bad_blk(void)
|
||||
{
|
||||
return IdentifyDeviceData.wDataBlockNum / 10;
|
||||
}
|
||||
|
||||
/* Return how many blocks should be reserved for OS image */
|
||||
static int get_res_blk_num_os(void)
|
||||
{
|
||||
u32 res_blks, blk_size;
|
||||
|
||||
blk_size = IdentifyDeviceData.PageDataSize *
|
||||
IdentifyDeviceData.PagesPerBlock;
|
||||
|
||||
res_blks = (reserved_mb * 1024 * 1024) / blk_size;
|
||||
|
||||
if ((res_blks < 1) || (res_blks >= IdentifyDeviceData.wDataBlockNum))
|
||||
res_blks = 1; /* Reserved 1 block for block table */
|
||||
|
||||
return res_blks;
|
||||
}
|
||||
|
||||
/* Transfer a full request. */
|
||||
static int do_transfer(struct spectra_nand_dev *tr, struct request *req)
|
||||
{
|
||||
u64 start_addr, addr;
|
||||
u32 logical_start_sect, hd_start_sect;
|
||||
u32 nsect, hd_sects;
|
||||
u32 rsect, tsect = 0;
|
||||
char *buf;
|
||||
u32 ratio = IdentifyDeviceData.PageDataSize >> 9;
|
||||
|
||||
start_addr = (u64)(blk_rq_pos(req)) << 9;
|
||||
/* Add a big enough offset to prevent the OS Image from
|
||||
* being accessed or damaged by file system */
|
||||
start_addr += IdentifyDeviceData.PageDataSize *
|
||||
IdentifyDeviceData.PagesPerBlock *
|
||||
res_blks_os;
|
||||
|
||||
if (req->cmd_type & REQ_FLUSH) {
|
||||
if (force_flush_cache()) /* Fail to flush cache */
|
||||
return -EIO;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (req->cmd_type != REQ_TYPE_FS)
|
||||
return -EIO;
|
||||
|
||||
if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(tr->gd)) {
|
||||
printk(KERN_ERR "Spectra error: request over the NAND "
|
||||
"capacity!sector %d, current_nr_sectors %d, "
|
||||
"while capacity is %d\n",
|
||||
(int)blk_rq_pos(req),
|
||||
blk_rq_cur_sectors(req),
|
||||
(int)get_capacity(tr->gd));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
logical_start_sect = start_addr >> 9;
|
||||
hd_start_sect = logical_start_sect / ratio;
|
||||
rsect = logical_start_sect - hd_start_sect * ratio;
|
||||
|
||||
addr = (u64)hd_start_sect * ratio * 512;
|
||||
buf = req->buffer;
|
||||
nsect = blk_rq_cur_sectors(req);
|
||||
|
||||
if (rsect)
|
||||
tsect = (ratio - rsect) < nsect ? (ratio - rsect) : nsect;
|
||||
|
||||
switch (rq_data_dir(req)) {
|
||||
case READ:
|
||||
/* Read the first NAND page */
|
||||
if (rsect) {
|
||||
if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
|
||||
printk(KERN_ERR "Error in %s, Line %d\n",
|
||||
__FILE__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
memcpy(buf, tr->tmp_buf + (rsect << 9), tsect << 9);
|
||||
addr += IdentifyDeviceData.PageDataSize;
|
||||
buf += tsect << 9;
|
||||
nsect -= tsect;
|
||||
}
|
||||
|
||||
/* Read the other NAND pages */
|
||||
for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) {
|
||||
if (GLOB_FTL_Page_Read(buf, addr)) {
|
||||
printk(KERN_ERR "Error in %s, Line %d\n",
|
||||
__FILE__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
addr += IdentifyDeviceData.PageDataSize;
|
||||
buf += IdentifyDeviceData.PageDataSize;
|
||||
}
|
||||
|
||||
/* Read the last NAND pages */
|
||||
if (nsect % ratio) {
|
||||
if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
|
||||
printk(KERN_ERR "Error in %s, Line %d\n",
|
||||
__FILE__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
memcpy(buf, tr->tmp_buf, (nsect % ratio) << 9);
|
||||
}
|
||||
#if CMD_DMA
|
||||
if (glob_ftl_execute_cmds())
|
||||
return -EIO;
|
||||
else
|
||||
return 0;
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
case WRITE:
|
||||
/* Write the first NAND page */
|
||||
if (rsect) {
|
||||
if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
|
||||
printk(KERN_ERR "Error in %s, Line %d\n",
|
||||
__FILE__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
memcpy(tr->tmp_buf + (rsect << 9), buf, tsect << 9);
|
||||
if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) {
|
||||
printk(KERN_ERR "Error in %s, Line %d\n",
|
||||
__FILE__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
addr += IdentifyDeviceData.PageDataSize;
|
||||
buf += tsect << 9;
|
||||
nsect -= tsect;
|
||||
}
|
||||
|
||||
/* Write the other NAND pages */
|
||||
for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) {
|
||||
if (GLOB_FTL_Page_Write(buf, addr)) {
|
||||
printk(KERN_ERR "Error in %s, Line %d\n",
|
||||
__FILE__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
addr += IdentifyDeviceData.PageDataSize;
|
||||
buf += IdentifyDeviceData.PageDataSize;
|
||||
}
|
||||
|
||||
/* Write the last NAND pages */
|
||||
if (nsect % ratio) {
|
||||
if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
|
||||
printk(KERN_ERR "Error in %s, Line %d\n",
|
||||
__FILE__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
memcpy(tr->tmp_buf, buf, (nsect % ratio) << 9);
|
||||
if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) {
|
||||
printk(KERN_ERR "Error in %s, Line %d\n",
|
||||
__FILE__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
#if CMD_DMA
|
||||
if (glob_ftl_execute_cmds())
|
||||
return -EIO;
|
||||
else
|
||||
return 0;
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
default:
|
||||
printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req));
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is copied from drivers/mtd/mtd_blkdevs.c */
|
||||
static int spectra_trans_thread(void *arg)
|
||||
{
|
||||
struct spectra_nand_dev *tr = arg;
|
||||
struct request_queue *rq = tr->queue;
|
||||
struct request *req = NULL;
|
||||
|
||||
/* we might get involved when memory gets low, so use PF_MEMALLOC */
|
||||
current->flags |= PF_MEMALLOC;
|
||||
|
||||
spin_lock_irq(rq->queue_lock);
|
||||
while (!kthread_should_stop()) {
|
||||
int res;
|
||||
|
||||
if (!req) {
|
||||
req = blk_fetch_request(rq);
|
||||
if (!req) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
spin_unlock_irq(rq->queue_lock);
|
||||
schedule();
|
||||
spin_lock_irq(rq->queue_lock);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(rq->queue_lock);
|
||||
|
||||
mutex_lock(&spectra_lock);
|
||||
res = do_transfer(tr, req);
|
||||
mutex_unlock(&spectra_lock);
|
||||
|
||||
spin_lock_irq(rq->queue_lock);
|
||||
|
||||
if (!__blk_end_request_cur(req, res))
|
||||
req = NULL;
|
||||
}
|
||||
|
||||
if (req)
|
||||
__blk_end_request_all(req, -EIO);
|
||||
|
||||
spin_unlock_irq(rq->queue_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Request function that "handles clustering". */
|
||||
static void GLOB_SBD_request(struct request_queue *rq)
|
||||
{
|
||||
struct spectra_nand_dev *pdev = rq->queuedata;
|
||||
wake_up_process(pdev->thread);
|
||||
}
|
||||
|
||||
static int GLOB_SBD_open(struct block_device *bdev, fmode_t mode)
|
||||
|
||||
{
|
||||
nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GLOB_SBD_release(struct gendisk *disk, fmode_t mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
mutex_lock(&spectra_lock);
|
||||
ret = force_flush_cache();
|
||||
mutex_unlock(&spectra_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GLOB_SBD_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
||||
{
|
||||
geo->heads = 4;
|
||||
geo->sectors = 16;
|
||||
geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"heads: %d, sectors: %d, cylinders: %d\n",
|
||||
geo->heads, geo->sectors, geo->cylinders);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GLOB_SBD_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
switch (cmd) {
|
||||
case GLOB_SBD_IOCTL_GC:
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Spectra IOCTL: Garbage Collection "
|
||||
"being performed\n");
|
||||
if (PASS != GLOB_FTL_Garbage_Collection())
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case GLOB_SBD_IOCTL_WL:
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Spectra IOCTL: Static Wear Leveling "
|
||||
"being performed\n");
|
||||
if (PASS != GLOB_FTL_Wear_Leveling())
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case GLOB_SBD_IOCTL_FORMAT:
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Flash format "
|
||||
"being performed\n");
|
||||
if (PASS != GLOB_FTL_Flash_Format())
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case GLOB_SBD_IOCTL_FLUSH_CACHE:
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Cache flush "
|
||||
"being performed\n");
|
||||
mutex_lock(&spectra_lock);
|
||||
ret = force_flush_cache();
|
||||
mutex_unlock(&spectra_lock);
|
||||
return ret;
|
||||
|
||||
case GLOB_SBD_IOCTL_COPY_BLK_TABLE:
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
|
||||
"Copy block table\n");
|
||||
if (copy_to_user((void __user *)arg,
|
||||
get_blk_table_start_addr(),
|
||||
get_blk_table_len()))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE:
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
|
||||
"Copy wear leveling table\n");
|
||||
if (copy_to_user((void __user *)arg,
|
||||
get_wear_leveling_table_start_addr(),
|
||||
get_wear_leveling_table_len()))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case GLOB_SBD_IOCTL_GET_NAND_INFO:
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
|
||||
"Get NAND info\n");
|
||||
if (copy_to_user((void __user *)arg, &IdentifyDeviceData,
|
||||
sizeof(IdentifyDeviceData)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case GLOB_SBD_IOCTL_WRITE_DATA:
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
|
||||
"Write one page data\n");
|
||||
return ioctl_write_page_data(arg);
|
||||
|
||||
case GLOB_SBD_IOCTL_READ_DATA:
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
|
||||
"Read one page data\n");
|
||||
return ioctl_read_page_data(arg);
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
static DEFINE_MUTEX(ffsport_mutex);
|
||||
|
||||
int GLOB_SBD_unlocked_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ffsport_mutex);
|
||||
ret = GLOB_SBD_ioctl(bdev, mode, cmd, arg);
|
||||
mutex_unlock(&ffsport_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct block_device_operations GLOB_SBD_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = GLOB_SBD_open,
|
||||
.release = GLOB_SBD_release,
|
||||
.ioctl = GLOB_SBD_unlocked_ioctl,
|
||||
.getgeo = GLOB_SBD_getgeo,
|
||||
};
|
||||
|
||||
static int SBD_setup_device(struct spectra_nand_dev *dev, int which)
|
||||
{
|
||||
int res_blks;
|
||||
u32 sects;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
memset(dev, 0, sizeof(struct spectra_nand_dev));
|
||||
|
||||
nand_dbg_print(NAND_DBG_WARN, "Reserved %d blocks "
|
||||
"for OS image, %d blocks for bad block replacement.\n",
|
||||
get_res_blk_num_os(),
|
||||
get_res_blk_num_bad_blk());
|
||||
|
||||
res_blks = get_res_blk_num_bad_blk() + get_res_blk_num_os();
|
||||
|
||||
dev->size = (u64)IdentifyDeviceData.PageDataSize *
|
||||
IdentifyDeviceData.PagesPerBlock *
|
||||
(IdentifyDeviceData.wDataBlockNum - res_blks);
|
||||
|
||||
res_blks_os = get_res_blk_num_os();
|
||||
|
||||
spin_lock_init(&dev->qlock);
|
||||
|
||||
dev->tmp_buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC);
|
||||
if (!dev->tmp_buf) {
|
||||
printk(KERN_ERR "Failed to kmalloc memory in %s Line %d, exit.\n",
|
||||
__FILE__, __LINE__);
|
||||
goto out_vfree;
|
||||
}
|
||||
|
||||
dev->queue = blk_init_queue(GLOB_SBD_request, &dev->qlock);
|
||||
if (dev->queue == NULL) {
|
||||
printk(KERN_ERR
|
||||
"Spectra: Request queue could not be initialized."
|
||||
" Aborting\n ");
|
||||
goto out_vfree;
|
||||
}
|
||||
dev->queue->queuedata = dev;
|
||||
|
||||
/* As Linux block layer doesn't support >4KB hardware sector, */
|
||||
/* Here we force report 512 byte hardware sector size to Kernel */
|
||||
blk_queue_logical_block_size(dev->queue, 512);
|
||||
|
||||
blk_queue_flush(dev->queue, REQ_FLUSH);
|
||||
|
||||
dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd");
|
||||
if (IS_ERR(dev->thread)) {
|
||||
blk_cleanup_queue(dev->queue);
|
||||
unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME);
|
||||
return PTR_ERR(dev->thread);
|
||||
}
|
||||
|
||||
dev->gd = alloc_disk(PARTITIONS);
|
||||
if (!dev->gd) {
|
||||
printk(KERN_ERR
|
||||
"Spectra: Could not allocate disk. Aborting \n ");
|
||||
goto out_vfree;
|
||||
}
|
||||
dev->gd->major = GLOB_SBD_majornum;
|
||||
dev->gd->first_minor = which * PARTITIONS;
|
||||
dev->gd->fops = &GLOB_SBD_ops;
|
||||
dev->gd->queue = dev->queue;
|
||||
dev->gd->private_data = dev;
|
||||
snprintf(dev->gd->disk_name, 32, "%s%c", GLOB_SBD_NAME, which + 'a');
|
||||
|
||||
sects = dev->size >> 9;
|
||||
nand_dbg_print(NAND_DBG_WARN, "Capacity sects: %d\n", sects);
|
||||
set_capacity(dev->gd, sects);
|
||||
|
||||
add_disk(dev->gd);
|
||||
|
||||
return 0;
|
||||
out_vfree:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
static ssize_t show_nand_block_num(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
(int)IdentifyDeviceData.wDataBlockNum);
|
||||
}
|
||||
|
||||
static ssize_t show_nand_pages_per_block(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
(int)IdentifyDeviceData.PagesPerBlock);
|
||||
}
|
||||
|
||||
static ssize_t show_nand_page_size(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
(int)IdentifyDeviceData.PageDataSize);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(nand_block_num, 0444, show_nand_block_num, NULL);
|
||||
static DEVICE_ATTR(nand_pages_per_block, 0444, show_nand_pages_per_block, NULL);
|
||||
static DEVICE_ATTR(nand_page_size, 0444, show_nand_page_size, NULL);
|
||||
|
||||
static void create_sysfs_entry(struct device *dev)
|
||||
{
|
||||
if (device_create_file(dev, &dev_attr_nand_block_num))
|
||||
printk(KERN_ERR "Spectra: "
|
||||
"failed to create sysfs entry nand_block_num.\n");
|
||||
if (device_create_file(dev, &dev_attr_nand_pages_per_block))
|
||||
printk(KERN_ERR "Spectra: "
|
||||
"failed to create sysfs entry nand_pages_per_block.\n");
|
||||
if (device_create_file(dev, &dev_attr_nand_page_size))
|
||||
printk(KERN_ERR "Spectra: "
|
||||
"failed to create sysfs entry nand_page_size.\n");
|
||||
}
|
||||
*/
|
||||
|
||||
static void register_spectra_ftl_async(void *unused, async_cookie_t cookie)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* create_sysfs_entry(&dev->dev); */
|
||||
|
||||
if (PASS != GLOB_FTL_IdentifyDevice(&IdentifyDeviceData)) {
|
||||
printk(KERN_ERR "Spectra: Unable to Read Flash Device. "
|
||||
"Aborting\n");
|
||||
return;
|
||||
} else {
|
||||
nand_dbg_print(NAND_DBG_WARN, "In GLOB_SBD_init: "
|
||||
"Num blocks=%d, pagesperblock=%d, "
|
||||
"pagedatasize=%d, ECCBytesPerSector=%d\n",
|
||||
(int)IdentifyDeviceData.NumBlocks,
|
||||
(int)IdentifyDeviceData.PagesPerBlock,
|
||||
(int)IdentifyDeviceData.PageDataSize,
|
||||
(int)IdentifyDeviceData.wECCBytesPerSector);
|
||||
}
|
||||
|
||||
printk(KERN_ALERT "Spectra: searching block table, please wait ...\n");
|
||||
if (GLOB_FTL_Init() != PASS) {
|
||||
printk(KERN_ERR "Spectra: Unable to Initialize FTL Layer. "
|
||||
"Aborting\n");
|
||||
goto out_ftl_flash_register;
|
||||
}
|
||||
printk(KERN_ALERT "Spectra: block table has been found.\n");
|
||||
|
||||
GLOB_SBD_majornum = register_blkdev(0, GLOB_SBD_NAME);
|
||||
if (GLOB_SBD_majornum <= 0) {
|
||||
printk(KERN_ERR "Unable to get the major %d for Spectra",
|
||||
GLOB_SBD_majornum);
|
||||
goto out_ftl_flash_register;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_DEVICES; i++)
|
||||
if (SBD_setup_device(&nand_device[i], i) == -ENOMEM)
|
||||
goto out_blk_register;
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Spectra: module loaded with major number %d\n",
|
||||
GLOB_SBD_majornum);
|
||||
|
||||
return;
|
||||
|
||||
out_blk_register:
|
||||
unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME);
|
||||
out_ftl_flash_register:
|
||||
GLOB_FTL_Cache_Release();
|
||||
printk(KERN_ERR "Spectra: Module load failed.\n");
|
||||
}
|
||||
|
||||
int register_spectra_ftl()
|
||||
{
|
||||
async_schedule(register_spectra_ftl_async, NULL);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(register_spectra_ftl);
|
||||
|
||||
static int GLOB_SBD_init(void)
|
||||
{
|
||||
/* Set debug output level (0~3) here. 3 is most verbose */
|
||||
printk(KERN_ALERT "Spectra: %s\n", GLOB_version);
|
||||
|
||||
mutex_init(&spectra_lock);
|
||||
|
||||
if (PASS != GLOB_FTL_Flash_Init()) {
|
||||
printk(KERN_ERR "Spectra: Unable to Initialize Flash Device. "
|
||||
"Aborting\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit GLOB_SBD_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
for (i = 0; i < NUM_DEVICES; i++) {
|
||||
struct spectra_nand_dev *dev = &nand_device[i];
|
||||
if (dev->gd) {
|
||||
del_gendisk(dev->gd);
|
||||
put_disk(dev->gd);
|
||||
}
|
||||
if (dev->queue)
|
||||
blk_cleanup_queue(dev->queue);
|
||||
kfree(dev->tmp_buf);
|
||||
}
|
||||
|
||||
unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME);
|
||||
|
||||
mutex_lock(&spectra_lock);
|
||||
force_flush_cache();
|
||||
mutex_unlock(&spectra_lock);
|
||||
|
||||
GLOB_FTL_Cache_Release();
|
||||
|
||||
GLOB_FTL_Flash_Release();
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Spectra FTL module (major number %d) unloaded.\n",
|
||||
GLOB_SBD_majornum);
|
||||
}
|
||||
|
||||
module_init(GLOB_SBD_init);
|
||||
module_exit(GLOB_SBD_exit);
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* 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);
|
||||
extern int register_spectra_ftl(void);
|
||||
|
||||
#endif /* _FFSPORT_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,198 +0,0 @@
|
|||
/*
|
||||
* 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 management 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_*/
|
|
@ -1,339 +0,0 @@
|
|||
/*
|
||||
* 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 */
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* 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_ */
|
||||
|
||||
|
|
@ -1,910 +0,0 @@
|
|||
/*
|
||||
* 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 "spectraswconfig.h"
|
||||
#include "lld.h"
|
||||
#include "lld_nand.h"
|
||||
#include "lld_cdma.h"
|
||||
#include "lld_emu.h"
|
||||
#include "flash.h"
|
||||
#include "nand_regs.h"
|
||||
|
||||
#define MAX_PENDING_CMDS 4
|
||||
#define MODE_02 (0x2 << 26)
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: CDMA_Data_Cmd
|
||||
* Inputs: cmd code (aligned for hw)
|
||||
* data: pointer to source or destination
|
||||
* block: block address
|
||||
* page: page address
|
||||
* num: num pages to transfer
|
||||
* Outputs: PASS
|
||||
* Description: This function takes the parameters and puts them
|
||||
* into the "pending commands" array.
|
||||
* It does not parse or validate the parameters.
|
||||
* The array index is same as the tag.
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags)
|
||||
{
|
||||
u8 bank;
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
if (0 == cmd)
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"%s, Line %d, Illegal cmd (0)\n", __FILE__, __LINE__);
|
||||
|
||||
/* If a command of another bank comes, then first execute */
|
||||
/* pending commands of the current bank, then set the new */
|
||||
/* bank as current bank */
|
||||
bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
|
||||
if (bank != info.flash_bank) {
|
||||
nand_dbg_print(NAND_DBG_WARN,
|
||||
"Will access new bank. old bank: %d, new bank: %d\n",
|
||||
info.flash_bank, bank);
|
||||
if (CDMA_Execute_CMDs()) {
|
||||
printk(KERN_ERR "CDMA_Execute_CMDs fail!\n");
|
||||
return FAIL;
|
||||
}
|
||||
info.flash_bank = bank;
|
||||
}
|
||||
|
||||
info.pcmds[info.pcmds_num].CMD = cmd;
|
||||
info.pcmds[info.pcmds_num].DataAddr = data;
|
||||
info.pcmds[info.pcmds_num].Block = block;
|
||||
info.pcmds[info.pcmds_num].Page = page;
|
||||
info.pcmds[info.pcmds_num].PageCount = num;
|
||||
info.pcmds[info.pcmds_num].DataDestAddr = 0;
|
||||
info.pcmds[info.pcmds_num].DataSrcAddr = 0;
|
||||
info.pcmds[info.pcmds_num].MemCopyByteCnt = 0;
|
||||
info.pcmds[info.pcmds_num].Flags = flags;
|
||||
info.pcmds[info.pcmds_num].Status = 0xB0B;
|
||||
|
||||
switch (cmd) {
|
||||
case WRITE_MAIN_SPARE_CMD:
|
||||
Conv_Main_Spare_Data_Log2Phy_Format(data, num);
|
||||
break;
|
||||
case WRITE_SPARE_CMD:
|
||||
Conv_Spare_Data_Log2Phy_Format(data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
info.pcmds_num++;
|
||||
|
||||
if (info.pcmds_num >= MAX_PENDING_CMDS) {
|
||||
if (CDMA_Execute_CMDs()) {
|
||||
printk(KERN_ERR "CDMA_Execute_CMDs fail!\n");
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: CDMA_MemCopy_CMD
|
||||
* Inputs: dest: pointer to destination
|
||||
* src: pointer to source
|
||||
* count: num bytes to transfer
|
||||
* Outputs: PASS
|
||||
* Description: This function takes the parameters and puts them
|
||||
* into the "pending commands" array.
|
||||
* It does not parse or validate the parameters.
|
||||
* The array index is same as the tag.
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags)
|
||||
{
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
info.pcmds[info.pcmds_num].CMD = MEMCOPY_CMD;
|
||||
info.pcmds[info.pcmds_num].DataAddr = 0;
|
||||
info.pcmds[info.pcmds_num].Block = 0;
|
||||
info.pcmds[info.pcmds_num].Page = 0;
|
||||
info.pcmds[info.pcmds_num].PageCount = 0;
|
||||
info.pcmds[info.pcmds_num].DataDestAddr = dest;
|
||||
info.pcmds[info.pcmds_num].DataSrcAddr = src;
|
||||
info.pcmds[info.pcmds_num].MemCopyByteCnt = byte_cnt;
|
||||
info.pcmds[info.pcmds_num].Flags = flags;
|
||||
info.pcmds[info.pcmds_num].Status = 0xB0B;
|
||||
|
||||
info.pcmds_num++;
|
||||
|
||||
if (info.pcmds_num >= MAX_PENDING_CMDS) {
|
||||
if (CDMA_Execute_CMDs()) {
|
||||
printk(KERN_ERR "CDMA_Execute_CMDs fail!\n");
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Prints the PendingCMDs array */
|
||||
void print_pending_cmds(void)
|
||||
{
|
||||
u16 i;
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
for (i = 0; i < info.pcmds_num; i++) {
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i);
|
||||
switch (info.pcmds[i].CMD) {
|
||||
case ERASE_CMD:
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Erase Command (0x%x)\n",
|
||||
info.pcmds[i].CMD);
|
||||
break;
|
||||
case WRITE_MAIN_CMD:
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Write Main Command (0x%x)\n",
|
||||
info.pcmds[i].CMD);
|
||||
break;
|
||||
case WRITE_MAIN_SPARE_CMD:
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Write Main Spare Command (0x%x)\n",
|
||||
info.pcmds[i].CMD);
|
||||
break;
|
||||
case READ_MAIN_SPARE_CMD:
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Read Main Spare Command (0x%x)\n",
|
||||
info.pcmds[i].CMD);
|
||||
break;
|
||||
case READ_MAIN_CMD:
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Read Main Command (0x%x)\n",
|
||||
info.pcmds[i].CMD);
|
||||
break;
|
||||
case MEMCOPY_CMD:
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Memcopy Command (0x%x)\n",
|
||||
info.pcmds[i].CMD);
|
||||
break;
|
||||
case DUMMY_CMD:
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Dummy Command (0x%x)\n",
|
||||
info.pcmds[i].CMD);
|
||||
break;
|
||||
default:
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Illegal Command (0x%x)\n",
|
||||
info.pcmds[i].CMD);
|
||||
break;
|
||||
}
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "DataAddr: 0x%x\n",
|
||||
(u32)info.pcmds[i].DataAddr);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Block: %d\n",
|
||||
info.pcmds[i].Block);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Page: %d\n",
|
||||
info.pcmds[i].Page);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "PageCount: %d\n",
|
||||
info.pcmds[i].PageCount);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "DataDestAddr: 0x%x\n",
|
||||
(u32)info.pcmds[i].DataDestAddr);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "DataSrcAddr: 0x%x\n",
|
||||
(u32)info.pcmds[i].DataSrcAddr);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "MemCopyByteCnt: %d\n",
|
||||
info.pcmds[i].MemCopyByteCnt);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Flags: 0x%x\n",
|
||||
info.pcmds[i].Flags);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Status: 0x%x\n",
|
||||
info.pcmds[i].Status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the CDMA descriptors */
|
||||
void print_cdma_descriptors(void)
|
||||
{
|
||||
struct cdma_descriptor *pc;
|
||||
int i;
|
||||
|
||||
pc = (struct cdma_descriptor *)info.cdma_desc_buf;
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump cdma descriptors:\n");
|
||||
|
||||
for (i = 0; i < info.cdma_num; i++) {
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i);
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n",
|
||||
pc[i].NxtPointerHi, pc[i].NxtPointerLo);
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"FlashPointerHi: 0x%x, FlashPointerLo: 0x%x\n",
|
||||
pc[i].FlashPointerHi, pc[i].FlashPointerLo);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "CommandType: 0x%x\n",
|
||||
pc[i].CommandType);
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"MemAddrHi: 0x%x, MemAddrLo: 0x%x\n",
|
||||
pc[i].MemAddrHi, pc[i].MemAddrLo);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "CommandFlags: 0x%x\n",
|
||||
pc[i].CommandFlags);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "Channel: %d, Status: 0x%x\n",
|
||||
pc[i].Channel, pc[i].Status);
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"MemCopyPointerHi: 0x%x, MemCopyPointerLo: 0x%x\n",
|
||||
pc[i].MemCopyPointerHi, pc[i].MemCopyPointerLo);
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Reserved12: 0x%x, Reserved13: 0x%x, "
|
||||
"Reserved14: 0x%x, pcmd: %d\n",
|
||||
pc[i].Reserved12, pc[i].Reserved13,
|
||||
pc[i].Reserved14, pc[i].pcmd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the Memory copy descriptors */
|
||||
static void print_memcp_descriptors(void)
|
||||
{
|
||||
struct memcpy_descriptor *pm;
|
||||
int i;
|
||||
|
||||
pm = (struct memcpy_descriptor *)info.memcp_desc_buf;
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump mem_cpy descriptors:\n");
|
||||
|
||||
for (i = 0; i < info.cdma_num; i++) {
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i);
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n",
|
||||
pm[i].NxtPointerHi, pm[i].NxtPointerLo);
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"SrcAddrHi: 0x%x, SrcAddrLo: 0x%x\n",
|
||||
pm[i].SrcAddrHi, pm[i].SrcAddrLo);
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"DestAddrHi: 0x%x, DestAddrLo: 0x%x\n",
|
||||
pm[i].DestAddrHi, pm[i].DestAddrLo);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "XferSize: %d\n",
|
||||
pm[i].XferSize);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "MemCopyFlags: 0x%x\n",
|
||||
pm[i].MemCopyFlags);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "MemCopyStatus: %d\n",
|
||||
pm[i].MemCopyStatus);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "reserved9: 0x%x\n",
|
||||
pm[i].reserved9);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "reserved10: 0x%x\n",
|
||||
pm[i].reserved10);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "reserved11: 0x%x\n",
|
||||
pm[i].reserved11);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "reserved12: 0x%x\n",
|
||||
pm[i].reserved12);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "reserved13: 0x%x\n",
|
||||
pm[i].reserved13);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "reserved14: 0x%x\n",
|
||||
pm[i].reserved14);
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "reserved15: 0x%x\n",
|
||||
pm[i].reserved15);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Reset cdma_descriptor chain to 0 */
|
||||
static void reset_cdma_desc(int i)
|
||||
{
|
||||
struct cdma_descriptor *ptr;
|
||||
|
||||
BUG_ON(i >= MAX_DESCS);
|
||||
|
||||
ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
|
||||
|
||||
ptr[i].NxtPointerHi = 0;
|
||||
ptr[i].NxtPointerLo = 0;
|
||||
ptr[i].FlashPointerHi = 0;
|
||||
ptr[i].FlashPointerLo = 0;
|
||||
ptr[i].CommandType = 0;
|
||||
ptr[i].MemAddrHi = 0;
|
||||
ptr[i].MemAddrLo = 0;
|
||||
ptr[i].CommandFlags = 0;
|
||||
ptr[i].Channel = 0;
|
||||
ptr[i].Status = 0;
|
||||
ptr[i].MemCopyPointerHi = 0;
|
||||
ptr[i].MemCopyPointerLo = 0;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: CDMA_UpdateEventStatus
|
||||
* Inputs: none
|
||||
* Outputs: none
|
||||
* Description: This function update the event status of all the channels
|
||||
* when an error condition is reported.
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
void CDMA_UpdateEventStatus(void)
|
||||
{
|
||||
int i, j, active_chan;
|
||||
struct cdma_descriptor *ptr;
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
|
||||
|
||||
for (j = 0; j < info.cdma_num; j++) {
|
||||
/* Check for the descriptor with failure */
|
||||
if ((ptr[j].Status & CMD_DMA_DESC_FAIL))
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* All the previous cmd's status for this channel must be good */
|
||||
for (i = 0; i < j; i++) {
|
||||
if (ptr[i].pcmd != 0xff)
|
||||
info.pcmds[ptr[i].pcmd].Status = CMD_PASS;
|
||||
}
|
||||
|
||||
/* Abort the channel with type 0 reset command. It resets the */
|
||||
/* selected channel after the descriptor completes the flash */
|
||||
/* operation and status has been updated for the descriptor. */
|
||||
/* Memory Copy and Sync associated with this descriptor will */
|
||||
/* not be executed */
|
||||
active_chan = ioread32(FlashReg + CHNL_ACTIVE);
|
||||
if ((active_chan & (1 << info.flash_bank)) == (1 << info.flash_bank)) {
|
||||
iowrite32(MODE_02 | (0 << 4), FlashMem); /* Type 0 reset */
|
||||
iowrite32((0xF << 4) | info.flash_bank, FlashMem + 0x10);
|
||||
} else { /* Should not reached here */
|
||||
printk(KERN_ERR "Error! Used bank is not set in"
|
||||
" reg CHNL_ACTIVE\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void cdma_trans(u16 chan)
|
||||
{
|
||||
u32 addr;
|
||||
|
||||
addr = info.cdma_desc;
|
||||
|
||||
iowrite32(MODE_10 | (chan << 24), FlashMem);
|
||||
iowrite32((1 << 7) | chan, FlashMem + 0x10);
|
||||
|
||||
iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & (addr >> 16)) << 8),
|
||||
FlashMem);
|
||||
iowrite32((1 << 7) | (1 << 4) | 0, FlashMem + 0x10);
|
||||
|
||||
iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & addr) << 8), FlashMem);
|
||||
iowrite32((1 << 7) | (1 << 5) | 0, FlashMem + 0x10);
|
||||
|
||||
iowrite32(MODE_10 | (chan << 24), FlashMem);
|
||||
iowrite32((1 << 7) | (1 << 5) | (1 << 4) | 0, FlashMem + 0x10);
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: CDMA_Execute_CMDs (for use with CMD_DMA)
|
||||
* Inputs: tag_count: the number of pending cmds to do
|
||||
* Outputs: PASS/FAIL
|
||||
* Description: Build the SDMA chain(s) by making one CMD-DMA descriptor
|
||||
* for each pending command, start the CDMA engine, and return.
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u16 CDMA_Execute_CMDs(void)
|
||||
{
|
||||
int i, ret;
|
||||
u64 flash_add;
|
||||
u32 ptr;
|
||||
dma_addr_t map_addr, next_ptr;
|
||||
u16 status = PASS;
|
||||
u16 tmp_c;
|
||||
struct cdma_descriptor *pc;
|
||||
struct memcpy_descriptor *pm;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
/* No pending cmds to execute, just exit */
|
||||
if (0 == info.pcmds_num) {
|
||||
nand_dbg_print(NAND_DBG_TRACE,
|
||||
"No pending cmds to execute. Just exit.\n");
|
||||
return PASS;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_DESCS; i++)
|
||||
reset_cdma_desc(i);
|
||||
|
||||
pc = (struct cdma_descriptor *)info.cdma_desc_buf;
|
||||
pm = (struct memcpy_descriptor *)info.memcp_desc_buf;
|
||||
|
||||
info.cdma_desc = virt_to_bus(info.cdma_desc_buf);
|
||||
info.memcp_desc = virt_to_bus(info.memcp_desc_buf);
|
||||
next_ptr = info.cdma_desc;
|
||||
info.cdma_num = 0;
|
||||
|
||||
for (i = 0; i < info.pcmds_num; i++) {
|
||||
if (info.pcmds[i].Block >= DeviceInfo.wTotalBlocks) {
|
||||
info.pcmds[i].Status = CMD_NOT_DONE;
|
||||
continue;
|
||||
}
|
||||
|
||||
next_ptr += sizeof(struct cdma_descriptor);
|
||||
pc[info.cdma_num].NxtPointerHi = next_ptr >> 16;
|
||||
pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff;
|
||||
|
||||
/* Use the Block offset within a bank */
|
||||
tmp_c = info.pcmds[i].Block /
|
||||
(DeviceInfo.wTotalBlocks / totalUsedBanks);
|
||||
flash_add = (u64)(info.pcmds[i].Block - tmp_c *
|
||||
(DeviceInfo.wTotalBlocks / totalUsedBanks)) *
|
||||
DeviceInfo.wBlockDataSize +
|
||||
(u64)(info.pcmds[i].Page) *
|
||||
DeviceInfo.wPageDataSize;
|
||||
|
||||
ptr = MODE_10 | (info.flash_bank << 24) |
|
||||
(u32)GLOB_u64_Div(flash_add,
|
||||
DeviceInfo.wPageDataSize);
|
||||
pc[info.cdma_num].FlashPointerHi = ptr >> 16;
|
||||
pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
|
||||
|
||||
if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) ||
|
||||
(info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) {
|
||||
/* Descriptor to set Main+Spare Access Mode */
|
||||
pc[info.cdma_num].CommandType = 0x43;
|
||||
pc[info.cdma_num].CommandFlags =
|
||||
(0 << 10) | (1 << 9) | (0 << 8) | 0x40;
|
||||
pc[info.cdma_num].MemAddrHi = 0;
|
||||
pc[info.cdma_num].MemAddrLo = 0;
|
||||
pc[info.cdma_num].Channel = 0;
|
||||
pc[info.cdma_num].Status = 0;
|
||||
pc[info.cdma_num].pcmd = i;
|
||||
|
||||
info.cdma_num++;
|
||||
BUG_ON(info.cdma_num >= MAX_DESCS);
|
||||
|
||||
reset_cdma_desc(info.cdma_num);
|
||||
next_ptr += sizeof(struct cdma_descriptor);
|
||||
pc[info.cdma_num].NxtPointerHi = next_ptr >> 16;
|
||||
pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff;
|
||||
pc[info.cdma_num].FlashPointerHi = ptr >> 16;
|
||||
pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
|
||||
}
|
||||
|
||||
switch (info.pcmds[i].CMD) {
|
||||
case ERASE_CMD:
|
||||
pc[info.cdma_num].CommandType = 1;
|
||||
pc[info.cdma_num].CommandFlags =
|
||||
(0 << 10) | (1 << 9) | (0 << 8) | 0x40;
|
||||
pc[info.cdma_num].MemAddrHi = 0;
|
||||
pc[info.cdma_num].MemAddrLo = 0;
|
||||
break;
|
||||
|
||||
case WRITE_MAIN_CMD:
|
||||
pc[info.cdma_num].CommandType =
|
||||
0x2100 | info.pcmds[i].PageCount;
|
||||
pc[info.cdma_num].CommandFlags =
|
||||
(0 << 10) | (1 << 9) | (0 << 8) | 0x40;
|
||||
map_addr = virt_to_bus(info.pcmds[i].DataAddr);
|
||||
pc[info.cdma_num].MemAddrHi = map_addr >> 16;
|
||||
pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
|
||||
break;
|
||||
|
||||
case READ_MAIN_CMD:
|
||||
pc[info.cdma_num].CommandType =
|
||||
0x2000 | info.pcmds[i].PageCount;
|
||||
pc[info.cdma_num].CommandFlags =
|
||||
(0 << 10) | (1 << 9) | (0 << 8) | 0x40;
|
||||
map_addr = virt_to_bus(info.pcmds[i].DataAddr);
|
||||
pc[info.cdma_num].MemAddrHi = map_addr >> 16;
|
||||
pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
|
||||
break;
|
||||
|
||||
case WRITE_MAIN_SPARE_CMD:
|
||||
pc[info.cdma_num].CommandType =
|
||||
0x2100 | info.pcmds[i].PageCount;
|
||||
pc[info.cdma_num].CommandFlags =
|
||||
(0 << 10) | (1 << 9) | (0 << 8) | 0x40;
|
||||
map_addr = virt_to_bus(info.pcmds[i].DataAddr);
|
||||
pc[info.cdma_num].MemAddrHi = map_addr >> 16;
|
||||
pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
|
||||
break;
|
||||
|
||||
case READ_MAIN_SPARE_CMD:
|
||||
pc[info.cdma_num].CommandType =
|
||||
0x2000 | info.pcmds[i].PageCount;
|
||||
pc[info.cdma_num].CommandFlags =
|
||||
(0 << 10) | (1 << 9) | (0 << 8) | 0x40;
|
||||
map_addr = virt_to_bus(info.pcmds[i].DataAddr);
|
||||
pc[info.cdma_num].MemAddrHi = map_addr >> 16;
|
||||
pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
|
||||
break;
|
||||
|
||||
case MEMCOPY_CMD:
|
||||
pc[info.cdma_num].CommandType = 0xFFFF; /* NOP cmd */
|
||||
/* Set bit 11 to let the CDMA engine continue to */
|
||||
/* execute only after it has finished processing */
|
||||
/* the memcopy descriptor. */
|
||||
/* Also set bit 10 and bit 9 to 1 */
|
||||
pc[info.cdma_num].CommandFlags = 0x0E40;
|
||||
map_addr = info.memcp_desc + info.cdma_num *
|
||||
sizeof(struct memcpy_descriptor);
|
||||
pc[info.cdma_num].MemCopyPointerHi = map_addr >> 16;
|
||||
pc[info.cdma_num].MemCopyPointerLo = map_addr & 0xffff;
|
||||
|
||||
pm[info.cdma_num].NxtPointerHi = 0;
|
||||
pm[info.cdma_num].NxtPointerLo = 0;
|
||||
|
||||
map_addr = virt_to_bus(info.pcmds[i].DataSrcAddr);
|
||||
pm[info.cdma_num].SrcAddrHi = map_addr >> 16;
|
||||
pm[info.cdma_num].SrcAddrLo = map_addr & 0xffff;
|
||||
map_addr = virt_to_bus(info.pcmds[i].DataDestAddr);
|
||||
pm[info.cdma_num].DestAddrHi = map_addr >> 16;
|
||||
pm[info.cdma_num].DestAddrLo = map_addr & 0xffff;
|
||||
|
||||
pm[info.cdma_num].XferSize =
|
||||
info.pcmds[i].MemCopyByteCnt;
|
||||
pm[info.cdma_num].MemCopyFlags =
|
||||
(0 << 15 | 0 << 14 | 27 << 8 | 0x40);
|
||||
pm[info.cdma_num].MemCopyStatus = 0;
|
||||
break;
|
||||
|
||||
case DUMMY_CMD:
|
||||
default:
|
||||
pc[info.cdma_num].CommandType = 0XFFFF;
|
||||
pc[info.cdma_num].CommandFlags =
|
||||
(0 << 10) | (1 << 9) | (0 << 8) | 0x40;
|
||||
pc[info.cdma_num].MemAddrHi = 0;
|
||||
pc[info.cdma_num].MemAddrLo = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pc[info.cdma_num].Channel = 0;
|
||||
pc[info.cdma_num].Status = 0;
|
||||
pc[info.cdma_num].pcmd = i;
|
||||
|
||||
info.cdma_num++;
|
||||
BUG_ON(info.cdma_num >= MAX_DESCS);
|
||||
|
||||
if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) ||
|
||||
(info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) {
|
||||
/* Descriptor to set back Main Area Access Mode */
|
||||
reset_cdma_desc(info.cdma_num);
|
||||
next_ptr += sizeof(struct cdma_descriptor);
|
||||
pc[info.cdma_num].NxtPointerHi = next_ptr >> 16;
|
||||
pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff;
|
||||
|
||||
pc[info.cdma_num].FlashPointerHi = ptr >> 16;
|
||||
pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
|
||||
|
||||
pc[info.cdma_num].CommandType = 0x42;
|
||||
pc[info.cdma_num].CommandFlags =
|
||||
(0 << 10) | (1 << 9) | (0 << 8) | 0x40;
|
||||
pc[info.cdma_num].MemAddrHi = 0;
|
||||
pc[info.cdma_num].MemAddrLo = 0;
|
||||
|
||||
pc[info.cdma_num].Channel = 0;
|
||||
pc[info.cdma_num].Status = 0;
|
||||
pc[info.cdma_num].pcmd = i;
|
||||
|
||||
info.cdma_num++;
|
||||
BUG_ON(info.cdma_num >= MAX_DESCS);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a dummy descriptor at end of the CDMA chain */
|
||||
reset_cdma_desc(info.cdma_num);
|
||||
ptr = MODE_10 | (info.flash_bank << 24);
|
||||
pc[info.cdma_num].FlashPointerHi = ptr >> 16;
|
||||
pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
|
||||
pc[info.cdma_num].CommandType = 0xFFFF; /* NOP command */
|
||||
/* Set Command Flags for the last CDMA descriptor: */
|
||||
/* set Continue bit (bit 9) to 0 and Interrupt bit (bit 8) to 1 */
|
||||
pc[info.cdma_num].CommandFlags =
|
||||
(0 << 10) | (0 << 9) | (1 << 8) | 0x40;
|
||||
pc[info.cdma_num].pcmd = 0xff; /* Set it to an illegal value */
|
||||
info.cdma_num++;
|
||||
BUG_ON(info.cdma_num >= MAX_DESCS);
|
||||
|
||||
iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */
|
||||
|
||||
iowrite32(1, FlashReg + DMA_ENABLE);
|
||||
/* Wait for DMA to be enabled before issuing the next command */
|
||||
while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
|
||||
;
|
||||
cdma_trans(info.flash_bank);
|
||||
|
||||
ret = wait_for_completion_timeout(&info.complete, 50 * HZ);
|
||||
if (!ret)
|
||||
printk(KERN_ERR "Wait for completion timeout "
|
||||
"in %s, Line %d\n", __FILE__, __LINE__);
|
||||
status = info.ret;
|
||||
|
||||
info.pcmds_num = 0; /* Clear the pending cmds number to 0 */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int is_cdma_interrupt(void)
|
||||
{
|
||||
u32 ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma;
|
||||
u32 int_en_mask;
|
||||
u32 cdma_int_en_mask;
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
/* Set the global Enable masks for only those interrupts
|
||||
* that are supported */
|
||||
cdma_int_en_mask = (DMA_INTR__DESC_COMP_CHANNEL0 |
|
||||
DMA_INTR__DESC_COMP_CHANNEL1 |
|
||||
DMA_INTR__DESC_COMP_CHANNEL2 |
|
||||
DMA_INTR__DESC_COMP_CHANNEL3 |
|
||||
DMA_INTR__MEMCOPY_DESC_COMP);
|
||||
|
||||
int_en_mask = (INTR_STATUS0__ECC_ERR |
|
||||
INTR_STATUS0__PROGRAM_FAIL |
|
||||
INTR_STATUS0__ERASE_FAIL);
|
||||
|
||||
ints_b0 = ioread32(FlashReg + INTR_STATUS0) & int_en_mask;
|
||||
ints_b1 = ioread32(FlashReg + INTR_STATUS1) & int_en_mask;
|
||||
ints_b2 = ioread32(FlashReg + INTR_STATUS2) & int_en_mask;
|
||||
ints_b3 = ioread32(FlashReg + INTR_STATUS3) & int_en_mask;
|
||||
ints_cdma = ioread32(FlashReg + DMA_INTR) & cdma_int_en_mask;
|
||||
|
||||
nand_dbg_print(NAND_DBG_WARN, "ints_bank0 to ints_bank3: "
|
||||
"0x%x, 0x%x, 0x%x, 0x%x, ints_cdma: 0x%x\n",
|
||||
ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma);
|
||||
|
||||
if (ints_b0 || ints_b1 || ints_b2 || ints_b3 || ints_cdma) {
|
||||
return 1;
|
||||
} else {
|
||||
iowrite32(ints_b0, FlashReg + INTR_STATUS0);
|
||||
iowrite32(ints_b1, FlashReg + INTR_STATUS1);
|
||||
iowrite32(ints_b2, FlashReg + INTR_STATUS2);
|
||||
iowrite32(ints_b3, FlashReg + INTR_STATUS3);
|
||||
nand_dbg_print(NAND_DBG_DEBUG,
|
||||
"Not a NAND controller interrupt! Ignore it.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_event_status(void)
|
||||
{
|
||||
int i;
|
||||
struct cdma_descriptor *ptr;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
|
||||
|
||||
for (i = 0; i < info.cdma_num; i++) {
|
||||
if (ptr[i].pcmd != 0xff)
|
||||
info.pcmds[ptr[i].pcmd].Status = CMD_PASS;
|
||||
if ((ptr[i].CommandType == 0x41) ||
|
||||
(ptr[i].CommandType == 0x42) ||
|
||||
(ptr[i].CommandType == 0x43))
|
||||
continue;
|
||||
|
||||
switch (info.pcmds[ptr[i].pcmd].CMD) {
|
||||
case READ_MAIN_SPARE_CMD:
|
||||
Conv_Main_Spare_Data_Phy2Log_Format(
|
||||
info.pcmds[ptr[i].pcmd].DataAddr,
|
||||
info.pcmds[ptr[i].pcmd].PageCount);
|
||||
break;
|
||||
case READ_SPARE_CMD:
|
||||
Conv_Spare_Data_Phy2Log_Format(
|
||||
info.pcmds[ptr[i].pcmd].DataAddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u16 do_ecc_for_desc(u32 ch, u8 *buf, u16 page)
|
||||
{
|
||||
u16 event = EVENT_NONE;
|
||||
u16 err_byte;
|
||||
u16 err_page = 0;
|
||||
u8 err_sector;
|
||||
u8 err_device;
|
||||
u16 ecc_correction_info;
|
||||
u16 err_address;
|
||||
u32 eccSectorSize;
|
||||
u8 *err_pos;
|
||||
|
||||
nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
|
||||
|
||||
do {
|
||||
if (0 == ch)
|
||||
err_page = ioread32(FlashReg + ERR_PAGE_ADDR0);
|
||||
else if (1 == ch)
|
||||
err_page = ioread32(FlashReg + ERR_PAGE_ADDR1);
|
||||
else if (2 == ch)
|
||||
err_page = ioread32(FlashReg + ERR_PAGE_ADDR2);
|
||||
else if (3 == ch)
|
||||
err_page = ioread32(FlashReg + ERR_PAGE_ADDR3);
|
||||
|
||||
err_address = ioread32(FlashReg + ECC_ERROR_ADDRESS);
|
||||
err_byte = err_address & ECC_ERROR_ADDRESS__OFFSET;
|
||||
err_sector = ((err_address &
|
||||
ECC_ERROR_ADDRESS__SECTOR_NR) >> 12);
|
||||
|
||||
ecc_correction_info = ioread32(FlashReg + ERR_CORRECTION_INFO);
|
||||
err_device = ((ecc_correction_info &
|
||||
ERR_CORRECTION_INFO__DEVICE_NR) >> 8);
|
||||
|
||||
if (ecc_correction_info & ERR_CORRECTION_INFO__ERROR_TYPE) {
|
||||
event = EVENT_UNCORRECTABLE_DATA_ERROR;
|
||||
} else {
|
||||
event = EVENT_CORRECTABLE_DATA_ERROR_FIXED;
|
||||
if (err_byte < ECC_SECTOR_SIZE) {
|
||||
err_pos = buf +
|
||||
(err_page - page) *
|
||||
DeviceInfo.wPageDataSize +
|
||||
err_sector * eccSectorSize +
|
||||
err_byte *
|
||||
DeviceInfo.wDevicesConnected +
|
||||
err_device;
|
||||
*err_pos ^= ecc_correction_info &
|
||||
ERR_CORRECTION_INFO__BYTEMASK;
|
||||
}
|
||||
}
|
||||
} while (!(ecc_correction_info & ERR_CORRECTION_INFO__LAST_ERR_INFO));
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
static u16 process_ecc_int(u32 c, u16 *p_desc_num)
|
||||
{
|
||||
struct cdma_descriptor *ptr;
|
||||
u16 j;
|
||||
int event = EVENT_PASS;
|
||||
|
||||
nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
if (c != info.flash_bank)
|
||||
printk(KERN_ERR "Error!info.flash_bank is %d, while c is %d\n",
|
||||
info.flash_bank, c);
|
||||
|
||||
ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
|
||||
|
||||
for (j = 0; j < info.cdma_num; j++)
|
||||
if ((ptr[j].Status & CMD_DMA_DESC_COMP) != CMD_DMA_DESC_COMP)
|
||||
break;
|
||||
|
||||
*p_desc_num = j; /* Pass the descripter number found here */
|
||||
|
||||
if (j >= info.cdma_num) {
|
||||
printk(KERN_ERR "Can not find the correct descriptor number "
|
||||
"when ecc interrupt triggered!"
|
||||
"info.cdma_num: %d, j: %d\n", info.cdma_num, j);
|
||||
return EVENT_UNCORRECTABLE_DATA_ERROR;
|
||||
}
|
||||
|
||||
event = do_ecc_for_desc(c, info.pcmds[ptr[j].pcmd].DataAddr,
|
||||
info.pcmds[ptr[j].pcmd].Page);
|
||||
|
||||
if (EVENT_UNCORRECTABLE_DATA_ERROR == event) {
|
||||
printk(KERN_ERR "Uncorrectable ECC error!"
|
||||
"info.cdma_num: %d, j: %d, "
|
||||
"pending cmd CMD: 0x%x, "
|
||||
"Block: 0x%x, Page: 0x%x, PageCount: 0x%x\n",
|
||||
info.cdma_num, j,
|
||||
info.pcmds[ptr[j].pcmd].CMD,
|
||||
info.pcmds[ptr[j].pcmd].Block,
|
||||
info.pcmds[ptr[j].pcmd].Page,
|
||||
info.pcmds[ptr[j].pcmd].PageCount);
|
||||
|
||||
if (ptr[j].pcmd != 0xff)
|
||||
info.pcmds[ptr[j].pcmd].Status = CMD_FAIL;
|
||||
CDMA_UpdateEventStatus();
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
static void process_prog_erase_fail_int(u16 desc_num)
|
||||
{
|
||||
struct cdma_descriptor *ptr;
|
||||
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
|
||||
|
||||
if (ptr[desc_num].pcmd != 0xFF)
|
||||
info.pcmds[ptr[desc_num].pcmd].Status = CMD_FAIL;
|
||||
|
||||
CDMA_UpdateEventStatus();
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: CDMA_Event_Status (for use with CMD_DMA)
|
||||
* Inputs: none
|
||||
* Outputs: Event_Status code
|
||||
* Description: This function is called after an interrupt has happened
|
||||
* It reads the HW status register and ...tbd
|
||||
* It returns the appropriate event status
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u16 CDMA_Event_Status(void)
|
||||
{
|
||||
u32 ints_addr[4] = {INTR_STATUS0, INTR_STATUS1,
|
||||
INTR_STATUS2, INTR_STATUS3};
|
||||
u32 dma_intr_bit[4] = {DMA_INTR__DESC_COMP_CHANNEL0,
|
||||
DMA_INTR__DESC_COMP_CHANNEL1,
|
||||
DMA_INTR__DESC_COMP_CHANNEL2,
|
||||
DMA_INTR__DESC_COMP_CHANNEL3};
|
||||
u32 cdma_int_status, int_status;
|
||||
u32 ecc_enable = 0;
|
||||
u16 event = EVENT_PASS;
|
||||
u16 cur_desc = 0;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
ecc_enable = ioread32(FlashReg + ECC_ENABLE);
|
||||
|
||||
while (1) {
|
||||
int_status = ioread32(FlashReg + ints_addr[info.flash_bank]);
|
||||
if (ecc_enable && (int_status & INTR_STATUS0__ECC_ERR)) {
|
||||
event = process_ecc_int(info.flash_bank, &cur_desc);
|
||||
iowrite32(INTR_STATUS0__ECC_ERR,
|
||||
FlashReg + ints_addr[info.flash_bank]);
|
||||
if (EVENT_UNCORRECTABLE_DATA_ERROR == event) {
|
||||
nand_dbg_print(NAND_DBG_WARN,
|
||||
"ints_bank0 to ints_bank3: "
|
||||
"0x%x, 0x%x, 0x%x, 0x%x, "
|
||||
"ints_cdma: 0x%x\n",
|
||||
ioread32(FlashReg + INTR_STATUS0),
|
||||
ioread32(FlashReg + INTR_STATUS1),
|
||||
ioread32(FlashReg + INTR_STATUS2),
|
||||
ioread32(FlashReg + INTR_STATUS3),
|
||||
ioread32(FlashReg + DMA_INTR));
|
||||
break;
|
||||
}
|
||||
} else if (int_status & INTR_STATUS0__PROGRAM_FAIL) {
|
||||
printk(KERN_ERR "NAND program fail interrupt!\n");
|
||||
process_prog_erase_fail_int(cur_desc);
|
||||
event = EVENT_PROGRAM_FAILURE;
|
||||
break;
|
||||
} else if (int_status & INTR_STATUS0__ERASE_FAIL) {
|
||||
printk(KERN_ERR "NAND erase fail interrupt!\n");
|
||||
process_prog_erase_fail_int(cur_desc);
|
||||
event = EVENT_ERASE_FAILURE;
|
||||
break;
|
||||
} else {
|
||||
cdma_int_status = ioread32(FlashReg + DMA_INTR);
|
||||
if (cdma_int_status & dma_intr_bit[info.flash_bank]) {
|
||||
iowrite32(dma_intr_bit[info.flash_bank],
|
||||
FlashReg + DMA_INTR);
|
||||
update_event_status();
|
||||
event = EVENT_PASS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int_status = ioread32(FlashReg + ints_addr[info.flash_bank]);
|
||||
iowrite32(int_status, FlashReg + ints_addr[info.flash_bank]);
|
||||
cdma_int_status = ioread32(FlashReg + DMA_INTR);
|
||||
iowrite32(cdma_int_status, FlashReg + DMA_INTR);
|
||||
|
||||
iowrite32(0, FlashReg + DMA_ENABLE);
|
||||
while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
|
||||
;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* 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_*/
|
|
@ -1,776 +0,0 @@
|
|||
/*
|
||||
* 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 "flash.h"
|
||||
#include "ffsdefs.h"
|
||||
#include "lld_emu.h"
|
||||
#include "lld.h"
|
||||
#if CMD_DMA
|
||||
#include "lld_cdma.h"
|
||||
#if FLASH_EMU
|
||||
u32 totalUsedBanks;
|
||||
u32 valid_banks[MAX_CHANS];
|
||||
#endif
|
||||
#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 FLASH_EMU /* This is for entire module */
|
||||
|
||||
static u8 *flash_memory[GLOB_LLD_BLOCKS * GLOB_LLD_PAGES];
|
||||
|
||||
/* Read nand emu file and then fill it's content to flash_memory */
|
||||
int emu_load_file_to_mem(void)
|
||||
{
|
||||
mm_segment_t fs;
|
||||
struct file *nef_filp = NULL;
|
||||
struct inode *inode = NULL;
|
||||
loff_t nef_size = 0;
|
||||
loff_t tmp_file_offset, file_offset;
|
||||
ssize_t nread;
|
||||
int i, rc = -EINVAL;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
|
||||
nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0);
|
||||
if (IS_ERR(nef_filp)) {
|
||||
printk(KERN_ERR "filp_open error: "
|
||||
"Unable to open nand emu file!\n");
|
||||
return PTR_ERR(nef_filp);
|
||||
}
|
||||
|
||||
if (nef_filp->f_path.dentry) {
|
||||
inode = nef_filp->f_path.dentry->d_inode;
|
||||
} else {
|
||||
printk(KERN_ERR "Can not get valid inode!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
nef_size = i_size_read(inode->i_mapping->host);
|
||||
if (nef_size <= 0) {
|
||||
printk(KERN_ERR "Invalid nand emu file size: "
|
||||
"0x%llx\n", nef_size);
|
||||
goto out;
|
||||
} else {
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: %lld\n",
|
||||
nef_size);
|
||||
}
|
||||
|
||||
file_offset = 0;
|
||||
for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) {
|
||||
tmp_file_offset = file_offset;
|
||||
nread = vfs_read(nef_filp,
|
||||
(char __user *)flash_memory[i],
|
||||
GLOB_LLD_PAGE_SIZE, &tmp_file_offset);
|
||||
if (nread < GLOB_LLD_PAGE_SIZE) {
|
||||
printk(KERN_ERR "%s, Line %d - "
|
||||
"nand emu file partial read: "
|
||||
"%d bytes\n", __FILE__, __LINE__, (int)nread);
|
||||
goto out;
|
||||
}
|
||||
file_offset += GLOB_LLD_PAGE_SIZE;
|
||||
}
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
filp_close(nef_filp, current->files);
|
||||
set_fs(fs);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Write contents of flash_memory to nand emu file */
|
||||
int emu_write_mem_to_file(void)
|
||||
{
|
||||
mm_segment_t fs;
|
||||
struct file *nef_filp = NULL;
|
||||
struct inode *inode = NULL;
|
||||
loff_t nef_size = 0;
|
||||
loff_t tmp_file_offset, file_offset;
|
||||
ssize_t nwritten;
|
||||
int i, rc = -EINVAL;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
|
||||
nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0);
|
||||
if (IS_ERR(nef_filp)) {
|
||||
printk(KERN_ERR "filp_open error: "
|
||||
"Unable to open nand emu file!\n");
|
||||
return PTR_ERR(nef_filp);
|
||||
}
|
||||
|
||||
if (nef_filp->f_path.dentry) {
|
||||
inode = nef_filp->f_path.dentry->d_inode;
|
||||
} else {
|
||||
printk(KERN_ERR "Invalid " "nef_filp->f_path.dentry value!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
nef_size = i_size_read(inode->i_mapping->host);
|
||||
if (nef_size <= 0) {
|
||||
printk(KERN_ERR "Invalid "
|
||||
"nand emu file size: 0x%llx\n", nef_size);
|
||||
goto out;
|
||||
} else {
|
||||
nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: "
|
||||
"%lld\n", nef_size);
|
||||
}
|
||||
|
||||
file_offset = 0;
|
||||
for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) {
|
||||
tmp_file_offset = file_offset;
|
||||
nwritten = vfs_write(nef_filp,
|
||||
(char __user *)flash_memory[i],
|
||||
GLOB_LLD_PAGE_SIZE, &tmp_file_offset);
|
||||
if (nwritten < GLOB_LLD_PAGE_SIZE) {
|
||||
printk(KERN_ERR "%s, Line %d - "
|
||||
"nand emu file partial write: "
|
||||
"%d bytes\n", __FILE__, __LINE__, (int)nwritten);
|
||||
goto out;
|
||||
}
|
||||
file_offset += GLOB_LLD_PAGE_SIZE;
|
||||
}
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
filp_close(nef_filp, current->files);
|
||||
set_fs(fs);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_Flash_Init
|
||||
* Inputs: none
|
||||
* Outputs: PASS=0 (notice 0=ok here)
|
||||
* Description: Creates & initializes the flash RAM array.
|
||||
*
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u16 emu_Flash_Init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
flash_memory[0] = vmalloc(GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS *
|
||||
GLOB_LLD_PAGES * sizeof(u8));
|
||||
if (!flash_memory[0]) {
|
||||
printk(KERN_ERR "Fail to allocate memory "
|
||||
"for nand emulator!\n");
|
||||
return ERR;
|
||||
}
|
||||
|
||||
memset((char *)(flash_memory[0]), 0xFF,
|
||||
GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * GLOB_LLD_PAGES *
|
||||
sizeof(u8));
|
||||
|
||||
for (i = 1; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++)
|
||||
flash_memory[i] = flash_memory[i - 1] + GLOB_LLD_PAGE_SIZE;
|
||||
|
||||
emu_load_file_to_mem(); /* Load nand emu file to mem */
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_Flash_Release
|
||||
* Inputs: none
|
||||
* Outputs: PASS=0 (notice 0=ok here)
|
||||
* Description: Releases the flash.
|
||||
*
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
int emu_Flash_Release(void)
|
||||
{
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
emu_write_mem_to_file(); /* Write back mem to nand emu file */
|
||||
|
||||
vfree(flash_memory[0]);
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_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 emu_Read_Device_ID(void)
|
||||
{
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
DeviceInfo.wDeviceMaker = 0;
|
||||
DeviceInfo.wDeviceType = 8;
|
||||
DeviceInfo.wSpectraStartBlock = 36;
|
||||
DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1;
|
||||
DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS;
|
||||
DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES;
|
||||
DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE;
|
||||
DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE;
|
||||
DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE -
|
||||
GLOB_LLD_PAGE_DATA_SIZE;
|
||||
DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES;
|
||||
DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES;
|
||||
DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock -
|
||||
DeviceInfo.wSpectraStartBlock
|
||||
+ 1);
|
||||
DeviceInfo.MLCDevice = 1; /* Emulate MLC device */
|
||||
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: emu_Flash_Reset
|
||||
* Inputs: none
|
||||
* Outputs: PASS=0 (notice 0=ok here)
|
||||
* Description: Reset the flash
|
||||
*
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u16 emu_Flash_Reset(void)
|
||||
{
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_Erase_Block
|
||||
* Inputs: Address
|
||||
* Outputs: PASS=0 (notice 0=ok here)
|
||||
* Description: Erase a block
|
||||
*
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u16 emu_Erase_Block(u32 block_add)
|
||||
{
|
||||
int i;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
if (block_add >= DeviceInfo.wTotalBlocks) {
|
||||
printk(KERN_ERR "emu_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);
|
||||
|
||||
for (i = block_add * GLOB_LLD_PAGES;
|
||||
i < ((block_add + 1) * GLOB_LLD_PAGES); i++) {
|
||||
if (flash_memory[i]) {
|
||||
memset((u8 *)(flash_memory[i]), 0xFF,
|
||||
DeviceInfo.wPageSize * sizeof(u8));
|
||||
}
|
||||
}
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_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 emu_Write_Page_Main(u8 *write_data, u32 Block,
|
||||
u16 Page, u16 PageCount)
|
||||
{
|
||||
int i;
|
||||
|
||||
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, "emu_Write_Page_Main: "
|
||||
"lba %u Page %u PageCount %u\n",
|
||||
(unsigned int)Block,
|
||||
(unsigned int)Page, (unsigned int)PageCount);
|
||||
|
||||
for (i = 0; i < PageCount; i++) {
|
||||
if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
|
||||
printk(KERN_ERR "Run out of memory\n");
|
||||
return FAIL;
|
||||
}
|
||||
memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
|
||||
write_data, DeviceInfo.wPageDataSize);
|
||||
write_data += DeviceInfo.wPageDataSize;
|
||||
Page++;
|
||||
}
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_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 emu_Read_Page_Main(u8 *read_data, u32 Block,
|
||||
u16 Page, u16 PageCount)
|
||||
{
|
||||
int i;
|
||||
|
||||
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, "emu_Read_Page_Main: "
|
||||
"lba %u Page %u PageCount %u\n",
|
||||
(unsigned int)Block,
|
||||
(unsigned int)Page, (unsigned int)PageCount);
|
||||
|
||||
for (i = 0; i < PageCount; i++) {
|
||||
if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
|
||||
memset(read_data, 0xFF, DeviceInfo.wPageDataSize);
|
||||
} else {
|
||||
memcpy(read_data,
|
||||
(u8 *) (flash_memory[Block * GLOB_LLD_PAGES
|
||||
+ Page]),
|
||||
DeviceInfo.wPageDataSize);
|
||||
}
|
||||
read_data += DeviceInfo.wPageDataSize;
|
||||
Page++;
|
||||
}
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
#ifndef ELDORA
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_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 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block,
|
||||
u16 Page, u16 PageCount)
|
||||
{
|
||||
int i;
|
||||
|
||||
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 too big\n");
|
||||
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);
|
||||
|
||||
for (i = 0; i < PageCount; i++) {
|
||||
if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
|
||||
memset(read_data, 0xFF, DeviceInfo.wPageSize);
|
||||
} else {
|
||||
memcpy(read_data, (u8 *) (flash_memory[Block *
|
||||
GLOB_LLD_PAGES
|
||||
+ Page]),
|
||||
DeviceInfo.wPageSize);
|
||||
}
|
||||
|
||||
read_data += DeviceInfo.wPageSize;
|
||||
Page++;
|
||||
}
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_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 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block,
|
||||
u16 Page, u16 page_count)
|
||||
{
|
||||
u16 i;
|
||||
|
||||
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 too big\n");
|
||||
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);
|
||||
|
||||
for (i = 0; i < page_count; i++) {
|
||||
if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
|
||||
printk(KERN_ERR "Run out of memory!\n");
|
||||
return FAIL;
|
||||
}
|
||||
memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
|
||||
write_data, DeviceInfo.wPageSize);
|
||||
write_data += DeviceInfo.wPageSize;
|
||||
Page++;
|
||||
}
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_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 emu_Write_Page_Spare(u8 *write_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, "Write Page Spare- "
|
||||
"block %u page %u\n",
|
||||
(unsigned int)Block, (unsigned int)Page);
|
||||
|
||||
if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
|
||||
printk(KERN_ERR "Run out of memory!\n");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] +
|
||||
DeviceInfo.wPageDataSize), write_data,
|
||||
(DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_Read_Page_Spare
|
||||
* Inputs: Write Buffer
|
||||
* Address
|
||||
* Buffer size
|
||||
* Outputs: PASS=0 (notice 0=ok here)
|
||||
* Description: Read data from the spare area
|
||||
*
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u16 emu_Read_Page_Spare(u8 *write_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\n",
|
||||
(unsigned int)Block, (unsigned int)Page);
|
||||
|
||||
if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
|
||||
memset(write_data, 0xFF,
|
||||
(DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
|
||||
} else {
|
||||
memcpy(write_data,
|
||||
(u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]
|
||||
+ DeviceInfo.wPageDataSize),
|
||||
(DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
|
||||
}
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_Enable_Disable_Interrupts
|
||||
* Inputs: enable or disable
|
||||
* Outputs: none
|
||||
* Description: NOP
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
void emu_Enable_Disable_Interrupts(u16 INT_ENABLE)
|
||||
{
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
}
|
||||
|
||||
u16 emu_Get_Bad_Block(u32 block)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CMD_DMA
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Support for CDMA functions
|
||||
************************************
|
||||
* emu_CDMA_Flash_Init
|
||||
* CDMA_process_data command (use LLD_CDMA)
|
||||
* CDMA_MemCopy_CMD (use LLD_CDMA)
|
||||
* emu_CDMA_execute all commands
|
||||
* emu_CDMA_Event_Status
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u16 emu_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 emu_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 emu_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);
|
||||
|
||||
print_pending_cmds(tag_count);
|
||||
|
||||
#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:
|
||||
emu_Erase_Block(block);
|
||||
PendingCMD[i].Status = PASS;
|
||||
break;
|
||||
case WRITE_MAIN_CMD:
|
||||
emu_Write_Page_Main(data, block, page, count);
|
||||
PendingCMD[i].Status = PASS;
|
||||
break;
|
||||
case WRITE_MAIN_SPARE_CMD:
|
||||
emu_Write_Page_Main_Spare(data, block, page, count);
|
||||
PendingCMD[i].Status = PASS;
|
||||
break;
|
||||
case READ_MAIN_CMD:
|
||||
emu_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");
|
||||
|
||||
emu_isr(0, 0); /* This is a null isr now. Need fill it in future */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: emu_Event_Status
|
||||
* Inputs: none
|
||||
* Outputs: Event_Status code
|
||||
* Description: This function can also be used to force errors
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
u16 emu_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 */
|
||||
#endif /* FLASH_EMU */
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* 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_*/
|
|
@ -1,683 +0,0 @@
|
|||
/*
|
||||
* 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"
|
||||
u32 totalUsedBanks;
|
||||
u32 valid_banks[MAX_CHANS];
|
||||
#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
|
||||
|
||||
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)∁
|
||||
|
||||
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_OPS_AUTO_OOB;
|
||||
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_OPS_AUTO_OOB;
|
||||
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_OPS_AUTO_OOB;
|
||||
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 */
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* 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_*/
|
File diff suppressed because it is too large
Load Diff
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* 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_*/
|
||||
|
||||
|
||||
|
|
@ -1,619 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#define DEVICE_RESET 0x0
|
||||
#define DEVICE_RESET__BANK0 0x0001
|
||||
#define DEVICE_RESET__BANK1 0x0002
|
||||
#define DEVICE_RESET__BANK2 0x0004
|
||||
#define DEVICE_RESET__BANK3 0x0008
|
||||
|
||||
#define TRANSFER_SPARE_REG 0x10
|
||||
#define TRANSFER_SPARE_REG__FLAG 0x0001
|
||||
|
||||
#define LOAD_WAIT_CNT 0x20
|
||||
#define LOAD_WAIT_CNT__VALUE 0xffff
|
||||
|
||||
#define PROGRAM_WAIT_CNT 0x30
|
||||
#define PROGRAM_WAIT_CNT__VALUE 0xffff
|
||||
|
||||
#define ERASE_WAIT_CNT 0x40
|
||||
#define ERASE_WAIT_CNT__VALUE 0xffff
|
||||
|
||||
#define INT_MON_CYCCNT 0x50
|
||||
#define INT_MON_CYCCNT__VALUE 0xffff
|
||||
|
||||
#define RB_PIN_ENABLED 0x60
|
||||
#define RB_PIN_ENABLED__BANK0 0x0001
|
||||
#define RB_PIN_ENABLED__BANK1 0x0002
|
||||
#define RB_PIN_ENABLED__BANK2 0x0004
|
||||
#define RB_PIN_ENABLED__BANK3 0x0008
|
||||
|
||||
#define MULTIPLANE_OPERATION 0x70
|
||||
#define MULTIPLANE_OPERATION__FLAG 0x0001
|
||||
|
||||
#define MULTIPLANE_READ_ENABLE 0x80
|
||||
#define MULTIPLANE_READ_ENABLE__FLAG 0x0001
|
||||
|
||||
#define COPYBACK_DISABLE 0x90
|
||||
#define COPYBACK_DISABLE__FLAG 0x0001
|
||||
|
||||
#define CACHE_WRITE_ENABLE 0xa0
|
||||
#define CACHE_WRITE_ENABLE__FLAG 0x0001
|
||||
|
||||
#define CACHE_READ_ENABLE 0xb0
|
||||
#define CACHE_READ_ENABLE__FLAG 0x0001
|
||||
|
||||
#define PREFETCH_MODE 0xc0
|
||||
#define PREFETCH_MODE__PREFETCH_EN 0x0001
|
||||
#define PREFETCH_MODE__PREFETCH_BURST_LENGTH 0xfff0
|
||||
|
||||
#define CHIP_ENABLE_DONT_CARE 0xd0
|
||||
#define CHIP_EN_DONT_CARE__FLAG 0x01
|
||||
|
||||
#define ECC_ENABLE 0xe0
|
||||
#define ECC_ENABLE__FLAG 0x0001
|
||||
|
||||
#define GLOBAL_INT_ENABLE 0xf0
|
||||
#define GLOBAL_INT_EN_FLAG 0x01
|
||||
|
||||
#define WE_2_RE 0x100
|
||||
#define WE_2_RE__VALUE 0x003f
|
||||
|
||||
#define ADDR_2_DATA 0x110
|
||||
#define ADDR_2_DATA__VALUE 0x003f
|
||||
|
||||
#define RE_2_WE 0x120
|
||||
#define RE_2_WE__VALUE 0x003f
|
||||
|
||||
#define ACC_CLKS 0x130
|
||||
#define ACC_CLKS__VALUE 0x000f
|
||||
|
||||
#define NUMBER_OF_PLANES 0x140
|
||||
#define NUMBER_OF_PLANES__VALUE 0x0007
|
||||
|
||||
#define PAGES_PER_BLOCK 0x150
|
||||
#define PAGES_PER_BLOCK__VALUE 0xffff
|
||||
|
||||
#define DEVICE_WIDTH 0x160
|
||||
#define DEVICE_WIDTH__VALUE 0x0003
|
||||
|
||||
#define DEVICE_MAIN_AREA_SIZE 0x170
|
||||
#define DEVICE_MAIN_AREA_SIZE__VALUE 0xffff
|
||||
|
||||
#define DEVICE_SPARE_AREA_SIZE 0x180
|
||||
#define DEVICE_SPARE_AREA_SIZE__VALUE 0xffff
|
||||
|
||||
#define TWO_ROW_ADDR_CYCLES 0x190
|
||||
#define TWO_ROW_ADDR_CYCLES__FLAG 0x0001
|
||||
|
||||
#define MULTIPLANE_ADDR_RESTRICT 0x1a0
|
||||
#define MULTIPLANE_ADDR_RESTRICT__FLAG 0x0001
|
||||
|
||||
#define ECC_CORRECTION 0x1b0
|
||||
#define ECC_CORRECTION__VALUE 0x001f
|
||||
|
||||
#define READ_MODE 0x1c0
|
||||
#define READ_MODE__VALUE 0x000f
|
||||
|
||||
#define WRITE_MODE 0x1d0
|
||||
#define WRITE_MODE__VALUE 0x000f
|
||||
|
||||
#define COPYBACK_MODE 0x1e0
|
||||
#define COPYBACK_MODE__VALUE 0x000f
|
||||
|
||||
#define RDWR_EN_LO_CNT 0x1f0
|
||||
#define RDWR_EN_LO_CNT__VALUE 0x001f
|
||||
|
||||
#define RDWR_EN_HI_CNT 0x200
|
||||
#define RDWR_EN_HI_CNT__VALUE 0x001f
|
||||
|
||||
#define MAX_RD_DELAY 0x210
|
||||
#define MAX_RD_DELAY__VALUE 0x000f
|
||||
|
||||
#define CS_SETUP_CNT 0x220
|
||||
#define CS_SETUP_CNT__VALUE 0x001f
|
||||
|
||||
#define SPARE_AREA_SKIP_BYTES 0x230
|
||||
#define SPARE_AREA_SKIP_BYTES__VALUE 0x003f
|
||||
|
||||
#define SPARE_AREA_MARKER 0x240
|
||||
#define SPARE_AREA_MARKER__VALUE 0xffff
|
||||
|
||||
#define DEVICES_CONNECTED 0x250
|
||||
#define DEVICES_CONNECTED__VALUE 0x0007
|
||||
|
||||
#define DIE_MASK 0x260
|
||||
#define DIE_MASK__VALUE 0x00ff
|
||||
|
||||
#define FIRST_BLOCK_OF_NEXT_PLANE 0x270
|
||||
#define FIRST_BLOCK_OF_NEXT_PLANE__VALUE 0xffff
|
||||
|
||||
#define WRITE_PROTECT 0x280
|
||||
#define WRITE_PROTECT__FLAG 0x0001
|
||||
|
||||
#define RE_2_RE 0x290
|
||||
#define RE_2_RE__VALUE 0x003f
|
||||
|
||||
#define MANUFACTURER_ID 0x300
|
||||
#define MANUFACTURER_ID__VALUE 0x00ff
|
||||
|
||||
#define DEVICE_ID 0x310
|
||||
#define DEVICE_ID__VALUE 0x00ff
|
||||
|
||||
#define DEVICE_PARAM_0 0x320
|
||||
#define DEVICE_PARAM_0__VALUE 0x00ff
|
||||
|
||||
#define DEVICE_PARAM_1 0x330
|
||||
#define DEVICE_PARAM_1__VALUE 0x00ff
|
||||
|
||||
#define DEVICE_PARAM_2 0x340
|
||||
#define DEVICE_PARAM_2__VALUE 0x00ff
|
||||
|
||||
#define LOGICAL_PAGE_DATA_SIZE 0x350
|
||||
#define LOGICAL_PAGE_DATA_SIZE__VALUE 0xffff
|
||||
|
||||
#define LOGICAL_PAGE_SPARE_SIZE 0x360
|
||||
#define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff
|
||||
|
||||
#define REVISION 0x370
|
||||
#define REVISION__VALUE 0xffff
|
||||
|
||||
#define ONFI_DEVICE_FEATURES 0x380
|
||||
#define ONFI_DEVICE_FEATURES__VALUE 0x003f
|
||||
|
||||
#define ONFI_OPTIONAL_COMMANDS 0x390
|
||||
#define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f
|
||||
|
||||
#define ONFI_TIMING_MODE 0x3a0
|
||||
#define ONFI_TIMING_MODE__VALUE 0x003f
|
||||
|
||||
#define ONFI_PGM_CACHE_TIMING_MODE 0x3b0
|
||||
#define ONFI_PGM_CACHE_TIMING_MODE__VALUE 0x003f
|
||||
|
||||
#define ONFI_DEVICE_NO_OF_LUNS 0x3c0
|
||||
#define ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS 0x00ff
|
||||
#define ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE 0x0100
|
||||
|
||||
#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L 0x3d0
|
||||
#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L__VALUE 0xffff
|
||||
|
||||
#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U 0x3e0
|
||||
#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U__VALUE 0xffff
|
||||
|
||||
#define FEATURES 0x3f0
|
||||
#define FEATURES__N_BANKS 0x0003
|
||||
#define FEATURES__ECC_MAX_ERR 0x003c
|
||||
#define FEATURES__DMA 0x0040
|
||||
#define FEATURES__CMD_DMA 0x0080
|
||||
#define FEATURES__PARTITION 0x0100
|
||||
#define FEATURES__XDMA_SIDEBAND 0x0200
|
||||
#define FEATURES__GPREG 0x0400
|
||||
#define FEATURES__INDEX_ADDR 0x0800
|
||||
|
||||
#define TRANSFER_MODE 0x400
|
||||
#define TRANSFER_MODE__VALUE 0x0003
|
||||
|
||||
#define INTR_STATUS0 0x410
|
||||
#define INTR_STATUS0__ECC_TRANSACTION_DONE 0x0001
|
||||
#define INTR_STATUS0__ECC_ERR 0x0002
|
||||
#define INTR_STATUS0__DMA_CMD_COMP 0x0004
|
||||
#define INTR_STATUS0__TIME_OUT 0x0008
|
||||
#define INTR_STATUS0__PROGRAM_FAIL 0x0010
|
||||
#define INTR_STATUS0__ERASE_FAIL 0x0020
|
||||
#define INTR_STATUS0__LOAD_COMP 0x0040
|
||||
#define INTR_STATUS0__PROGRAM_COMP 0x0080
|
||||
#define INTR_STATUS0__ERASE_COMP 0x0100
|
||||
#define INTR_STATUS0__PIPE_CPYBCK_CMD_COMP 0x0200
|
||||
#define INTR_STATUS0__LOCKED_BLK 0x0400
|
||||
#define INTR_STATUS0__UNSUP_CMD 0x0800
|
||||
#define INTR_STATUS0__INT_ACT 0x1000
|
||||
#define INTR_STATUS0__RST_COMP 0x2000
|
||||
#define INTR_STATUS0__PIPE_CMD_ERR 0x4000
|
||||
#define INTR_STATUS0__PAGE_XFER_INC 0x8000
|
||||
|
||||
#define INTR_EN0 0x420
|
||||
#define INTR_EN0__ECC_TRANSACTION_DONE 0x0001
|
||||
#define INTR_EN0__ECC_ERR 0x0002
|
||||
#define INTR_EN0__DMA_CMD_COMP 0x0004
|
||||
#define INTR_EN0__TIME_OUT 0x0008
|
||||
#define INTR_EN0__PROGRAM_FAIL 0x0010
|
||||
#define INTR_EN0__ERASE_FAIL 0x0020
|
||||
#define INTR_EN0__LOAD_COMP 0x0040
|
||||
#define INTR_EN0__PROGRAM_COMP 0x0080
|
||||
#define INTR_EN0__ERASE_COMP 0x0100
|
||||
#define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200
|
||||
#define INTR_EN0__LOCKED_BLK 0x0400
|
||||
#define INTR_EN0__UNSUP_CMD 0x0800
|
||||
#define INTR_EN0__INT_ACT 0x1000
|
||||
#define INTR_EN0__RST_COMP 0x2000
|
||||
#define INTR_EN0__PIPE_CMD_ERR 0x4000
|
||||
#define INTR_EN0__PAGE_XFER_INC 0x8000
|
||||
|
||||
#define PAGE_CNT0 0x430
|
||||
#define PAGE_CNT0__VALUE 0x00ff
|
||||
|
||||
#define ERR_PAGE_ADDR0 0x440
|
||||
#define ERR_PAGE_ADDR0__VALUE 0xffff
|
||||
|
||||
#define ERR_BLOCK_ADDR0 0x450
|
||||
#define ERR_BLOCK_ADDR0__VALUE 0xffff
|
||||
|
||||
#define INTR_STATUS1 0x460
|
||||
#define INTR_STATUS1__ECC_TRANSACTION_DONE 0x0001
|
||||
#define INTR_STATUS1__ECC_ERR 0x0002
|
||||
#define INTR_STATUS1__DMA_CMD_COMP 0x0004
|
||||
#define INTR_STATUS1__TIME_OUT 0x0008
|
||||
#define INTR_STATUS1__PROGRAM_FAIL 0x0010
|
||||
#define INTR_STATUS1__ERASE_FAIL 0x0020
|
||||
#define INTR_STATUS1__LOAD_COMP 0x0040
|
||||
#define INTR_STATUS1__PROGRAM_COMP 0x0080
|
||||
#define INTR_STATUS1__ERASE_COMP 0x0100
|
||||
#define INTR_STATUS1__PIPE_CPYBCK_CMD_COMP 0x0200
|
||||
#define INTR_STATUS1__LOCKED_BLK 0x0400
|
||||
#define INTR_STATUS1__UNSUP_CMD 0x0800
|
||||
#define INTR_STATUS1__INT_ACT 0x1000
|
||||
#define INTR_STATUS1__RST_COMP 0x2000
|
||||
#define INTR_STATUS1__PIPE_CMD_ERR 0x4000
|
||||
#define INTR_STATUS1__PAGE_XFER_INC 0x8000
|
||||
|
||||
#define INTR_EN1 0x470
|
||||
#define INTR_EN1__ECC_TRANSACTION_DONE 0x0001
|
||||
#define INTR_EN1__ECC_ERR 0x0002
|
||||
#define INTR_EN1__DMA_CMD_COMP 0x0004
|
||||
#define INTR_EN1__TIME_OUT 0x0008
|
||||
#define INTR_EN1__PROGRAM_FAIL 0x0010
|
||||
#define INTR_EN1__ERASE_FAIL 0x0020
|
||||
#define INTR_EN1__LOAD_COMP 0x0040
|
||||
#define INTR_EN1__PROGRAM_COMP 0x0080
|
||||
#define INTR_EN1__ERASE_COMP 0x0100
|
||||
#define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200
|
||||
#define INTR_EN1__LOCKED_BLK 0x0400
|
||||
#define INTR_EN1__UNSUP_CMD 0x0800
|
||||
#define INTR_EN1__INT_ACT 0x1000
|
||||
#define INTR_EN1__RST_COMP 0x2000
|
||||
#define INTR_EN1__PIPE_CMD_ERR 0x4000
|
||||
#define INTR_EN1__PAGE_XFER_INC 0x8000
|
||||
|
||||
#define PAGE_CNT1 0x480
|
||||
#define PAGE_CNT1__VALUE 0x00ff
|
||||
|
||||
#define ERR_PAGE_ADDR1 0x490
|
||||
#define ERR_PAGE_ADDR1__VALUE 0xffff
|
||||
|
||||
#define ERR_BLOCK_ADDR1 0x4a0
|
||||
#define ERR_BLOCK_ADDR1__VALUE 0xffff
|
||||
|
||||
#define INTR_STATUS2 0x4b0
|
||||
#define INTR_STATUS2__ECC_TRANSACTION_DONE 0x0001
|
||||
#define INTR_STATUS2__ECC_ERR 0x0002
|
||||
#define INTR_STATUS2__DMA_CMD_COMP 0x0004
|
||||
#define INTR_STATUS2__TIME_OUT 0x0008
|
||||
#define INTR_STATUS2__PROGRAM_FAIL 0x0010
|
||||
#define INTR_STATUS2__ERASE_FAIL 0x0020
|
||||
#define INTR_STATUS2__LOAD_COMP 0x0040
|
||||
#define INTR_STATUS2__PROGRAM_COMP 0x0080
|
||||
#define INTR_STATUS2__ERASE_COMP 0x0100
|
||||
#define INTR_STATUS2__PIPE_CPYBCK_CMD_COMP 0x0200
|
||||
#define INTR_STATUS2__LOCKED_BLK 0x0400
|
||||
#define INTR_STATUS2__UNSUP_CMD 0x0800
|
||||
#define INTR_STATUS2__INT_ACT 0x1000
|
||||
#define INTR_STATUS2__RST_COMP 0x2000
|
||||
#define INTR_STATUS2__PIPE_CMD_ERR 0x4000
|
||||
#define INTR_STATUS2__PAGE_XFER_INC 0x8000
|
||||
|
||||
#define INTR_EN2 0x4c0
|
||||
#define INTR_EN2__ECC_TRANSACTION_DONE 0x0001
|
||||
#define INTR_EN2__ECC_ERR 0x0002
|
||||
#define INTR_EN2__DMA_CMD_COMP 0x0004
|
||||
#define INTR_EN2__TIME_OUT 0x0008
|
||||
#define INTR_EN2__PROGRAM_FAIL 0x0010
|
||||
#define INTR_EN2__ERASE_FAIL 0x0020
|
||||
#define INTR_EN2__LOAD_COMP 0x0040
|
||||
#define INTR_EN2__PROGRAM_COMP 0x0080
|
||||
#define INTR_EN2__ERASE_COMP 0x0100
|
||||
#define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200
|
||||
#define INTR_EN2__LOCKED_BLK 0x0400
|
||||
#define INTR_EN2__UNSUP_CMD 0x0800
|
||||
#define INTR_EN2__INT_ACT 0x1000
|
||||
#define INTR_EN2__RST_COMP 0x2000
|
||||
#define INTR_EN2__PIPE_CMD_ERR 0x4000
|
||||
#define INTR_EN2__PAGE_XFER_INC 0x8000
|
||||
|
||||
#define PAGE_CNT2 0x4d0
|
||||
#define PAGE_CNT2__VALUE 0x00ff
|
||||
|
||||
#define ERR_PAGE_ADDR2 0x4e0
|
||||
#define ERR_PAGE_ADDR2__VALUE 0xffff
|
||||
|
||||
#define ERR_BLOCK_ADDR2 0x4f0
|
||||
#define ERR_BLOCK_ADDR2__VALUE 0xffff
|
||||
|
||||
#define INTR_STATUS3 0x500
|
||||
#define INTR_STATUS3__ECC_TRANSACTION_DONE 0x0001
|
||||
#define INTR_STATUS3__ECC_ERR 0x0002
|
||||
#define INTR_STATUS3__DMA_CMD_COMP 0x0004
|
||||
#define INTR_STATUS3__TIME_OUT 0x0008
|
||||
#define INTR_STATUS3__PROGRAM_FAIL 0x0010
|
||||
#define INTR_STATUS3__ERASE_FAIL 0x0020
|
||||
#define INTR_STATUS3__LOAD_COMP 0x0040
|
||||
#define INTR_STATUS3__PROGRAM_COMP 0x0080
|
||||
#define INTR_STATUS3__ERASE_COMP 0x0100
|
||||
#define INTR_STATUS3__PIPE_CPYBCK_CMD_COMP 0x0200
|
||||
#define INTR_STATUS3__LOCKED_BLK 0x0400
|
||||
#define INTR_STATUS3__UNSUP_CMD 0x0800
|
||||
#define INTR_STATUS3__INT_ACT 0x1000
|
||||
#define INTR_STATUS3__RST_COMP 0x2000
|
||||
#define INTR_STATUS3__PIPE_CMD_ERR 0x4000
|
||||
#define INTR_STATUS3__PAGE_XFER_INC 0x8000
|
||||
|
||||
#define INTR_EN3 0x510
|
||||
#define INTR_EN3__ECC_TRANSACTION_DONE 0x0001
|
||||
#define INTR_EN3__ECC_ERR 0x0002
|
||||
#define INTR_EN3__DMA_CMD_COMP 0x0004
|
||||
#define INTR_EN3__TIME_OUT 0x0008
|
||||
#define INTR_EN3__PROGRAM_FAIL 0x0010
|
||||
#define INTR_EN3__ERASE_FAIL 0x0020
|
||||
#define INTR_EN3__LOAD_COMP 0x0040
|
||||
#define INTR_EN3__PROGRAM_COMP 0x0080
|
||||
#define INTR_EN3__ERASE_COMP 0x0100
|
||||
#define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200
|
||||
#define INTR_EN3__LOCKED_BLK 0x0400
|
||||
#define INTR_EN3__UNSUP_CMD 0x0800
|
||||
#define INTR_EN3__INT_ACT 0x1000
|
||||
#define INTR_EN3__RST_COMP 0x2000
|
||||
#define INTR_EN3__PIPE_CMD_ERR 0x4000
|
||||
#define INTR_EN3__PAGE_XFER_INC 0x8000
|
||||
|
||||
#define PAGE_CNT3 0x520
|
||||
#define PAGE_CNT3__VALUE 0x00ff
|
||||
|
||||
#define ERR_PAGE_ADDR3 0x530
|
||||
#define ERR_PAGE_ADDR3__VALUE 0xffff
|
||||
|
||||
#define ERR_BLOCK_ADDR3 0x540
|
||||
#define ERR_BLOCK_ADDR3__VALUE 0xffff
|
||||
|
||||
#define DATA_INTR 0x550
|
||||
#define DATA_INTR__WRITE_SPACE_AV 0x0001
|
||||
#define DATA_INTR__READ_DATA_AV 0x0002
|
||||
|
||||
#define DATA_INTR_EN 0x560
|
||||
#define DATA_INTR_EN__WRITE_SPACE_AV 0x0001
|
||||
#define DATA_INTR_EN__READ_DATA_AV 0x0002
|
||||
|
||||
#define GPREG_0 0x570
|
||||
#define GPREG_0__VALUE 0xffff
|
||||
|
||||
#define GPREG_1 0x580
|
||||
#define GPREG_1__VALUE 0xffff
|
||||
|
||||
#define GPREG_2 0x590
|
||||
#define GPREG_2__VALUE 0xffff
|
||||
|
||||
#define GPREG_3 0x5a0
|
||||
#define GPREG_3__VALUE 0xffff
|
||||
|
||||
#define ECC_THRESHOLD 0x600
|
||||
#define ECC_THRESHOLD__VALUE 0x03ff
|
||||
|
||||
#define ECC_ERROR_BLOCK_ADDRESS 0x610
|
||||
#define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff
|
||||
|
||||
#define ECC_ERROR_PAGE_ADDRESS 0x620
|
||||
#define ECC_ERROR_PAGE_ADDRESS__VALUE 0x0fff
|
||||
#define ECC_ERROR_PAGE_ADDRESS__BANK 0xf000
|
||||
|
||||
#define ECC_ERROR_ADDRESS 0x630
|
||||
#define ECC_ERROR_ADDRESS__OFFSET 0x0fff
|
||||
#define ECC_ERROR_ADDRESS__SECTOR_NR 0xf000
|
||||
|
||||
#define ERR_CORRECTION_INFO 0x640
|
||||
#define ERR_CORRECTION_INFO__BYTEMASK 0x00ff
|
||||
#define ERR_CORRECTION_INFO__DEVICE_NR 0x0f00
|
||||
#define ERR_CORRECTION_INFO__ERROR_TYPE 0x4000
|
||||
#define ERR_CORRECTION_INFO__LAST_ERR_INFO 0x8000
|
||||
|
||||
#define DMA_ENABLE 0x700
|
||||
#define DMA_ENABLE__FLAG 0x0001
|
||||
|
||||
#define IGNORE_ECC_DONE 0x710
|
||||
#define IGNORE_ECC_DONE__FLAG 0x0001
|
||||
|
||||
#define DMA_INTR 0x720
|
||||
#define DMA_INTR__TARGET_ERROR 0x0001
|
||||
#define DMA_INTR__DESC_COMP_CHANNEL0 0x0002
|
||||
#define DMA_INTR__DESC_COMP_CHANNEL1 0x0004
|
||||
#define DMA_INTR__DESC_COMP_CHANNEL2 0x0008
|
||||
#define DMA_INTR__DESC_COMP_CHANNEL3 0x0010
|
||||
#define DMA_INTR__MEMCOPY_DESC_COMP 0x0020
|
||||
|
||||
#define DMA_INTR_EN 0x730
|
||||
#define DMA_INTR_EN__TARGET_ERROR 0x0001
|
||||
#define DMA_INTR_EN__DESC_COMP_CHANNEL0 0x0002
|
||||
#define DMA_INTR_EN__DESC_COMP_CHANNEL1 0x0004
|
||||
#define DMA_INTR_EN__DESC_COMP_CHANNEL2 0x0008
|
||||
#define DMA_INTR_EN__DESC_COMP_CHANNEL3 0x0010
|
||||
#define DMA_INTR_EN__MEMCOPY_DESC_COMP 0x0020
|
||||
|
||||
#define TARGET_ERR_ADDR_LO 0x740
|
||||
#define TARGET_ERR_ADDR_LO__VALUE 0xffff
|
||||
|
||||
#define TARGET_ERR_ADDR_HI 0x750
|
||||
#define TARGET_ERR_ADDR_HI__VALUE 0xffff
|
||||
|
||||
#define CHNL_ACTIVE 0x760
|
||||
#define CHNL_ACTIVE__CHANNEL0 0x0001
|
||||
#define CHNL_ACTIVE__CHANNEL1 0x0002
|
||||
#define CHNL_ACTIVE__CHANNEL2 0x0004
|
||||
#define CHNL_ACTIVE__CHANNEL3 0x0008
|
||||
|
||||
#define ACTIVE_SRC_ID 0x800
|
||||
#define ACTIVE_SRC_ID__VALUE 0x00ff
|
||||
|
||||
#define PTN_INTR 0x810
|
||||
#define PTN_INTR__CONFIG_ERROR 0x0001
|
||||
#define PTN_INTR__ACCESS_ERROR_BANK0 0x0002
|
||||
#define PTN_INTR__ACCESS_ERROR_BANK1 0x0004
|
||||
#define PTN_INTR__ACCESS_ERROR_BANK2 0x0008
|
||||
#define PTN_INTR__ACCESS_ERROR_BANK3 0x0010
|
||||
#define PTN_INTR__REG_ACCESS_ERROR 0x0020
|
||||
|
||||
#define PTN_INTR_EN 0x820
|
||||
#define PTN_INTR_EN__CONFIG_ERROR 0x0001
|
||||
#define PTN_INTR_EN__ACCESS_ERROR_BANK0 0x0002
|
||||
#define PTN_INTR_EN__ACCESS_ERROR_BANK1 0x0004
|
||||
#define PTN_INTR_EN__ACCESS_ERROR_BANK2 0x0008
|
||||
#define PTN_INTR_EN__ACCESS_ERROR_BANK3 0x0010
|
||||
#define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020
|
||||
|
||||
#define PERM_SRC_ID_0 0x830
|
||||
#define PERM_SRC_ID_0__SRCID 0x00ff
|
||||
#define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800
|
||||
#define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000
|
||||
#define PERM_SRC_ID_0__READ_ACTIVE 0x4000
|
||||
#define PERM_SRC_ID_0__PARTITION_VALID 0x8000
|
||||
|
||||
#define MIN_BLK_ADDR_0 0x840
|
||||
#define MIN_BLK_ADDR_0__VALUE 0xffff
|
||||
|
||||
#define MAX_BLK_ADDR_0 0x850
|
||||
#define MAX_BLK_ADDR_0__VALUE 0xffff
|
||||
|
||||
#define MIN_MAX_BANK_0 0x860
|
||||
#define MIN_MAX_BANK_0__MIN_VALUE 0x0003
|
||||
#define MIN_MAX_BANK_0__MAX_VALUE 0x000c
|
||||
|
||||
#define PERM_SRC_ID_1 0x870
|
||||
#define PERM_SRC_ID_1__SRCID 0x00ff
|
||||
#define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800
|
||||
#define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000
|
||||
#define PERM_SRC_ID_1__READ_ACTIVE 0x4000
|
||||
#define PERM_SRC_ID_1__PARTITION_VALID 0x8000
|
||||
|
||||
#define MIN_BLK_ADDR_1 0x880
|
||||
#define MIN_BLK_ADDR_1__VALUE 0xffff
|
||||
|
||||
#define MAX_BLK_ADDR_1 0x890
|
||||
#define MAX_BLK_ADDR_1__VALUE 0xffff
|
||||
|
||||
#define MIN_MAX_BANK_1 0x8a0
|
||||
#define MIN_MAX_BANK_1__MIN_VALUE 0x0003
|
||||
#define MIN_MAX_BANK_1__MAX_VALUE 0x000c
|
||||
|
||||
#define PERM_SRC_ID_2 0x8b0
|
||||
#define PERM_SRC_ID_2__SRCID 0x00ff
|
||||
#define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800
|
||||
#define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000
|
||||
#define PERM_SRC_ID_2__READ_ACTIVE 0x4000
|
||||
#define PERM_SRC_ID_2__PARTITION_VALID 0x8000
|
||||
|
||||
#define MIN_BLK_ADDR_2 0x8c0
|
||||
#define MIN_BLK_ADDR_2__VALUE 0xffff
|
||||
|
||||
#define MAX_BLK_ADDR_2 0x8d0
|
||||
#define MAX_BLK_ADDR_2__VALUE 0xffff
|
||||
|
||||
#define MIN_MAX_BANK_2 0x8e0
|
||||
#define MIN_MAX_BANK_2__MIN_VALUE 0x0003
|
||||
#define MIN_MAX_BANK_2__MAX_VALUE 0x000c
|
||||
|
||||
#define PERM_SRC_ID_3 0x8f0
|
||||
#define PERM_SRC_ID_3__SRCID 0x00ff
|
||||
#define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800
|
||||
#define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000
|
||||
#define PERM_SRC_ID_3__READ_ACTIVE 0x4000
|
||||
#define PERM_SRC_ID_3__PARTITION_VALID 0x8000
|
||||
|
||||
#define MIN_BLK_ADDR_3 0x900
|
||||
#define MIN_BLK_ADDR_3__VALUE 0xffff
|
||||
|
||||
#define MAX_BLK_ADDR_3 0x910
|
||||
#define MAX_BLK_ADDR_3__VALUE 0xffff
|
||||
|
||||
#define MIN_MAX_BANK_3 0x920
|
||||
#define MIN_MAX_BANK_3__MIN_VALUE 0x0003
|
||||
#define MIN_MAX_BANK_3__MAX_VALUE 0x000c
|
||||
|
||||
#define PERM_SRC_ID_4 0x930
|
||||
#define PERM_SRC_ID_4__SRCID 0x00ff
|
||||
#define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800
|
||||
#define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000
|
||||
#define PERM_SRC_ID_4__READ_ACTIVE 0x4000
|
||||
#define PERM_SRC_ID_4__PARTITION_VALID 0x8000
|
||||
|
||||
#define MIN_BLK_ADDR_4 0x940
|
||||
#define MIN_BLK_ADDR_4__VALUE 0xffff
|
||||
|
||||
#define MAX_BLK_ADDR_4 0x950
|
||||
#define MAX_BLK_ADDR_4__VALUE 0xffff
|
||||
|
||||
#define MIN_MAX_BANK_4 0x960
|
||||
#define MIN_MAX_BANK_4__MIN_VALUE 0x0003
|
||||
#define MIN_MAX_BANK_4__MAX_VALUE 0x000c
|
||||
|
||||
#define PERM_SRC_ID_5 0x970
|
||||
#define PERM_SRC_ID_5__SRCID 0x00ff
|
||||
#define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800
|
||||
#define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000
|
||||
#define PERM_SRC_ID_5__READ_ACTIVE 0x4000
|
||||
#define PERM_SRC_ID_5__PARTITION_VALID 0x8000
|
||||
|
||||
#define MIN_BLK_ADDR_5 0x980
|
||||
#define MIN_BLK_ADDR_5__VALUE 0xffff
|
||||
|
||||
#define MAX_BLK_ADDR_5 0x990
|
||||
#define MAX_BLK_ADDR_5__VALUE 0xffff
|
||||
|
||||
#define MIN_MAX_BANK_5 0x9a0
|
||||
#define MIN_MAX_BANK_5__MIN_VALUE 0x0003
|
||||
#define MIN_MAX_BANK_5__MAX_VALUE 0x000c
|
||||
|
||||
#define PERM_SRC_ID_6 0x9b0
|
||||
#define PERM_SRC_ID_6__SRCID 0x00ff
|
||||
#define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800
|
||||
#define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000
|
||||
#define PERM_SRC_ID_6__READ_ACTIVE 0x4000
|
||||
#define PERM_SRC_ID_6__PARTITION_VALID 0x8000
|
||||
|
||||
#define MIN_BLK_ADDR_6 0x9c0
|
||||
#define MIN_BLK_ADDR_6__VALUE 0xffff
|
||||
|
||||
#define MAX_BLK_ADDR_6 0x9d0
|
||||
#define MAX_BLK_ADDR_6__VALUE 0xffff
|
||||
|
||||
#define MIN_MAX_BANK_6 0x9e0
|
||||
#define MIN_MAX_BANK_6__MIN_VALUE 0x0003
|
||||
#define MIN_MAX_BANK_6__MAX_VALUE 0x000c
|
||||
|
||||
#define PERM_SRC_ID_7 0x9f0
|
||||
#define PERM_SRC_ID_7__SRCID 0x00ff
|
||||
#define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800
|
||||
#define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000
|
||||
#define PERM_SRC_ID_7__READ_ACTIVE 0x4000
|
||||
#define PERM_SRC_ID_7__PARTITION_VALID 0x8000
|
||||
|
||||
#define MIN_BLK_ADDR_7 0xa00
|
||||
#define MIN_BLK_ADDR_7__VALUE 0xffff
|
||||
|
||||
#define MAX_BLK_ADDR_7 0xa10
|
||||
#define MAX_BLK_ADDR_7__VALUE 0xffff
|
||||
|
||||
#define MIN_MAX_BANK_7 0xa20
|
||||
#define MIN_MAX_BANK_7__MIN_VALUE 0x0003
|
||||
#define MIN_MAX_BANK_7__MAX_VALUE 0x000c
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* 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_*/
|
Loading…
Reference in New Issue