rk30 nand driver.

This commit is contained in:
zhaoyifeng
2012-02-07 15:16:46 +08:00
parent b52a26e732
commit 772be6200f
5 changed files with 218 additions and 70 deletions

32
arch/arm/mach-rk30/board-rk30-sdk.c Normal file → Executable file
View File

@@ -34,6 +34,37 @@
#include <mach/board.h>
#include <mach/hardware.h>
//#include "devices.h"
#include <mach/io.h>
#if defined(CONFIG_MTD_NAND_RK29XX)
static struct resource rk30xxnand_resources[] = {
{
.start = RK30_NANDC_PHYS,
.end = RK30_NANDC_PHYS+RK30_NANDC_SIZE -1,
.flags = IORESOURCE_MEM,
}
};
struct platform_device rk30xx_device_nand = {
.name = "rk30xxnand",
.id = -1,
.resource = rk30xxnand_resources,
.num_resources= ARRAY_SIZE(rk30xxnand_resources),
};
#endif
static struct platform_device *devices[] __initdata = {
#ifdef CONFIG_MTD_NAND_RK29XX
&rk30xx_device_nand,
#endif
};
static void __init machine_rk30_board_init(void)
{
platform_add_devices(devices, ARRAY_SIZE(devices));
}
static void __init rk30_reserve(void)
{
@@ -46,4 +77,5 @@ MACHINE_START(RK30, "RK30board")
.init_irq = rk30_init_irq,
.timer = &rk30_timer,
.reserve = &rk30_reserve,
.init_machine = machine_rk30_board_init,
MACHINE_END

View File

@@ -4,6 +4,6 @@
# $Id: Makefile,v 1.3 2011/01/21 10:12:56 Administrator Exp $
#
obj-$(CONFIG_MTD_NAND_RK29XX) += rknand_base_ko.o
obj-$(CONFIG_MTD_RKNAND_BUFFER) += rk30xxnand_ko.o

View File

@@ -428,67 +428,39 @@ typedef enum _CRU_RST
}eCRU_RST;
//GRF Registers
typedef volatile struct tagGRF_REG
{
uint32 GRF_GPIO0_DIR;
uint32 GRF_GPIO1_DIR;
uint32 GRF_GPIO2_DIR;
uint32 GRF_GPIO3_DIR;
uint32 GRF_GPIO4_DIR;
uint32 GRF_GPIO5_DIR;
uint32 GRF_GPIO0_DO;
uint32 GRF_GPIO1_DO;
uint32 GRF_GPIO2_DO;
uint32 GRF_GPIO3_DO;
uint32 GRF_GPIO4_DO;
uint32 GRF_GPIO5_DO;
uint32 GRF_GPIO0_EN;
uint32 GRF_GPIO1_EN;
uint32 GRF_GPIO2_EN;
uint32 GRF_GPIO3_EN;
uint32 GRF_GPIO4_EN;
uint32 GRF_GPIO5_EN;
uint32 GRF_GPIO0L_IOMUX;
uint32 GRF_GPIO0H_IOMUX;
uint32 GRF_GPIO1L_IOMUX;
uint32 GRF_GPIO1H_IOMUX;
uint32 GRF_GPIO2L_IOMUX;
uint32 GRF_GPIO2H_IOMUX;
uint32 GRF_GPIO3L_IOMUX;
uint32 GRF_GPIO3H_IOMUX;
uint32 GRF_GPIO4L_IOMUX;
uint32 GRF_GPIO4H_IOMUX;
uint32 GRF_GPIO5L_IOMUX;
uint32 GRF_GPIO5H_IOMUX;
uint32 GRF_GPIO0_PULL1;
uint32 GRF_GPIO1_PULL1;
uint32 GRF_GPIO2_PULL1;
uint32 GRF_GPIO3_PULL1;
uint32 GRF_GPIO4_PULL1;
uint32 GRF_GPIO5_PULL1;
uint32 GRF_GPIO6_PULL1;
uint32 GRF_UOC0_CON0;
uint32 GRF_UOC1_CON0;
uint32 GRF_USB_CON;
uint32 GRF_CPU_CON0;
uint32 GRF_CPU_CON1;
uint32 GRF_CPU_STATUS;
uint32 GRF_MEM_CON;
uint32 GRF_MEM_STATUS0;
uint32 GRF_MEM_STATUS1;
uint32 GRF_MEM_STATUS2;
uint32 GRF_SOC_CON0;
uint32 GRF_SOC_CON1;
uint32 GRF_SOC_CON2;
uint32 GRF_SOC_CON3;
uint32 GRF_SOC_CON4;
uint32 GRF_OS_REG0;
uint32 GRF_OS_REG1;
uint32 GRF_OS_REG2;
uint32 GRF_OS_REG3;
typedef struct tagGPIO_LH
{
uint32 GPIOL;
uint32 GPIOH;
}GPIO_LH_T;
typedef struct tagGPIO_IOMUX
{
uint32 GPIOA_IOMUX;
uint32 GPIOB_IOMUX;
uint32 GPIOC_IOMUX;
uint32 GPIOD_IOMUX;
}GPIO_IOMUX_T;
//REG FILE registers
typedef volatile struct tagGRF_REG
{
GPIO_LH_T GRF_GPIO_DIR[7];
GPIO_LH_T GRF_GPIO_DO[7];
GPIO_LH_T GRF_GPIO_EN[7];
GPIO_IOMUX_T GRF_GPIO_IOMUX[7];
GPIO_LH_T GRF_GPIO_PULL[7];
uint32 GRF_SOC_CON[3];
uint32 GRF_SOC_STATUS0;
uint32 GRF_DMAC1_CON[3];
uint32 GRF_DMAC2_CON[4];
uint32 GRF_UOC0_CON[3];
uint32 GRF_UOC1_CON[4];
uint32 GRF_DDRC_CON0;
uint32 GRF_DDRC_STAT;
uint32 reserved[(0x1c8-0x1a0)/4];
uint32 GRF_OS_REG[4];
} GRF_REG, *pGRF_REG;
}GRF_REG, *pGRF_REG,*pAPB_REG, *pREG_FILE;
//TIMER Registers
typedef volatile struct tagTIMER_STRUCT
{
@@ -522,7 +494,7 @@ typedef struct tagSCU_CLK_INFO
uint32 armFreqLast;
}SCU_CLK_INFO,*pSCU_CLK_INFO;
#define g_cruReg ((pCRU_REG)RK29_CRU_BASE)
#define g_cruReg ((pCRU_REG)RK29_CRU_REG_BASE)
#endif

View File

@@ -23,10 +23,16 @@ Revision: 1.00
#include <mach/board.h>
#include <mach/gpio.h>
#include <asm/dma.h>
#include <mach/rk29-dma-pl330.h>
#include "typedef.h"
#ifdef CONFIG_MACH_RK30_SDK
#include <mach/io.h>
#include <mach/irqs.h>
#else
#include <mach/rk29_iomap.h>
#include <mach/iomux.h>
#endif
#include <linux/interrupt.h>
#include "epphal.h"
@@ -64,7 +70,7 @@ extern void rkNand_cond_resched(void);
extern unsigned long rk_dma_mem_alloc(int size);
extern unsigned long rk_dma_mem_free(unsigned long buf);
#undef PRINTF
#define PRINTF RKNAND_DEBUG
#endif

View File

@@ -24,8 +24,8 @@
#include "rknand_base.h"
#define DRIVER_NAME "rk29xxnand"
const char rknand_base_version[] = "rknand_base.c version: 4.30 20111009";
#define DRIVER_NAME "rk30xxnand"
const char rknand_base_version[] = "rknand_base.c version: 4.32 20120103";
#define NAND_DEBUG_LEVEL0 0
#define NAND_DEBUG_LEVEL1 1
#define NAND_DEBUG_LEVEL2 2
@@ -58,10 +58,50 @@ static const int s_debug = 0;
#define NANDPROC_ROOT NULL
#endif
//#define RKNAND_TRAC_EN
#ifdef RKNAND_TRAC_EN
static struct proc_dir_entry *my_trac_proc_entry;
#define MAX_TRAC_BUFFER_SIZE (long)(2048 * 8 * 512) //sector
static char grknand_trac_buf[MAX_TRAC_BUFFER_SIZE];
static char *ptrac_buf = grknand_trac_buf;
void trac_log(long lba,int len, int mod)
{
if(mod)
ptrac_buf += sprintf(ptrac_buf,"W %d %d \n",lba,len);
else
ptrac_buf += sprintf(ptrac_buf,"R %d %d \n",lba,len);
}
static int rkNand_trac_read(char *page, char **start, off_t off, int count, int *eof,
void *data)
{
char *p = page;
int len;
len = ptrac_buf - grknand_trac_buf - off;
printk("rkNand_trac_read: page=%x,off=%x,count=%x ,len=%x \n",(int)page,(int)off,count,len);
if (len < 0)
len = 0;
if(len > count)
len = count;
memcpy(p,grknand_trac_buf + off,len);
*eof = (len < count) ? 1 : 0;
*start = page;
if(len < count)
ptrac_buf = grknand_trac_buf;
return len;
}
#endif
#define DATA_LEN (1024*8*2/4) //<2F><><EFBFBD>ݿ鵥λword
#define SPARE_LEN (32*8*2/4) //У<><D0A3><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
#define PAGE_LEN (DATA_LEN+SPARE_LEN) //ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>λ<EFBFBD>ij<EFBFBD><C4B3><EFBFBD>
#define MAX_BUFFER_SIZE (long)(2048 * 8) //sector
#define MAX_BUFFER_SIZE (long)(2048 * 8) //sector
long grknand_buf[MAX_BUFFER_SIZE * 512/4] __attribute__((aligned(4096)));
long grknand_dma_buf[PAGE_LEN*4*5] __attribute__((aligned(4096)));
@@ -82,6 +122,9 @@ static int rkNand_proc_read(char *page,
buf += gpNandInfo->proc_ftlread(buf);
if(gpNandInfo->proc_bufread)
buf += gpNandInfo->proc_bufread(buf);
#ifdef RKNAND_TRAC_EN
buf += sprintf(buf, "trac data len:%d\n", ptrac_buf - grknand_trac_buf);
#endif
}
return buf - page < count ? buf - page : count;
}
@@ -98,6 +141,17 @@ static void rk28nand_create_procfs(void)
my_proc_entry->read_proc = rkNand_proc_read;
my_proc_entry->data = NULL;
}
#ifdef RKNAND_TRAC_EN
/* Install the proc_fs entry */
my_trac_proc_entry = create_proc_entry("rknand_trac",
S_IRUGO | S_IFREG,
NANDPROC_ROOT);
if (my_trac_proc_entry) {
my_trac_proc_entry->write_proc = NULL;
my_trac_proc_entry->read_proc = rkNand_trac_read;
my_trac_proc_entry->data = NULL;
}
#endif
}
void printk_write_log(long lba,int len, const u_char *pbuf)
@@ -117,6 +171,10 @@ static int rk28xxnand_read(struct mtd_info *mtd, loff_t from, size_t len,
int ret = 0;
int sector = len>>9;
int LBA = (int)(from>>9);
#ifdef RKNAND_TRAC_EN
//trac_log(LBA,sector,0);
#endif
//printk("R %d %d \n",(int)LBA,sector);
//if(rknand_debug)
// printk("rk28xxnand_read: from=%x,sector=%x,\n",(int)LBA,sector);
if(sector && gpNandInfo->ftl_read)
@@ -133,6 +191,11 @@ static int rk28xxnand_write(struct mtd_info *mtd, loff_t from, size_t len,
int ret = 0;
int sector = len>>9;
int LBA = (int)(from>>9);
#ifdef RKNAND_TRAC_EN
trac_log(LBA,sector,1);
#endif
//printk("W %d %d \n",(int)LBA,sector);
//return 0;
//printk("*");
//if(rknand_debug)
// printk(KERN_NOTICE "write: from=%lx,sector=%x\n",(int)LBA,sector);
@@ -141,7 +204,7 @@ static int rk28xxnand_write(struct mtd_info *mtd, loff_t from, size_t len,
{
if(LBA < SysImageWriteEndAdd)//0x4E000)
{
NAND_DEBUG(NAND_DEBUG_LEVEL0,">>> FtlWriteImage: LBA=0x%08X sector=%d\n",LBA, sector);
//NAND_DEBUG(NAND_DEBUG_LEVEL0,">>> FtlWriteImage: LBA=0x%08X sector=%d\n",LBA, sector);
ret = gpNandInfo->ftl_write(LBA, sector, (void *)buf,1);
}
else
@@ -163,7 +226,7 @@ static int rk28xxnand_erase(struct mtd_info *mtd, struct erase_info *instr)
static void rk28xxnand_sync(struct mtd_info *mtd)
{
NAND_DEBUG(NAND_DEBUG_LEVEL0,"rk28xxnand_sync: \n");
NAND_DEBUG(NAND_DEBUG_LEVEL0,"rk30xxnand_sync: \n");
if(gpNandInfo->ftl_sync)
gpNandInfo->ftl_sync();
}
@@ -291,6 +354,68 @@ static int rk28xxnand_init(struct rknand_info *nand_info)
#ifdef CONFIG_MTD_CMDLINE_PARTS
const char *part_probes[] = { "cmdlinepart", NULL };
#endif
static struct mtd_partition rk30_partition_info[] = {
{
name: "misc",
offset: 0x2000*0x200,
size: 0x2000*0x200,//100MB
},
{
name: "kernel",
offset: 0x4000*0x200,
size: 0x4000*0x200,//200MB
},
{
name: "boot",
offset: 0x8000*0x200,
size: 0x8000*0x200,//200MB
},
{
name: "recovery",
offset: 0x10000*0x200,
size: 0x8000*0x200,//200MB
},
{
name: "backup",
offset: 0x00018000*0x200,
size: 0x000C0000*0x200,//200MB
},
{
name: "cache",
offset: 0x000D8000*0x200,
size: 0x00040000*0x200,//200MB
},
{
name: "userdata",
offset: 0x00118000*0x200,
size: 0x00100000*0x200,//200MB
},
{
name: "kpanic",
offset: 0x00218000*0x200,
size: 0x00002000*0x200,//200MB
},
{
name: "system",
offset: 0x0021A000*0x200,
size: 0x000A0000*0x200,//200MB
},
{
name: "user",
offset: 0x002BA000*0x200,
size: 0x000A0000*0x200,//200MB
},
};
static int rk29xxnand_add_partitions(struct rknand_info *nand_info)
{
@@ -317,6 +442,14 @@ static int rk29xxnand_add_partitions(struct rknand_info *nand_info)
#endif
}
#endif
g_num_partitions = 10;
rknand_parts = rk30_partition_info;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
return mtd_device_register(&rknand_mtd, rknand_parts, g_num_partitions);
#else
return add_mtd_partitions(&(rknand_mtd), rknand_parts, g_num_partitions);
#endif
return 0;
}
@@ -343,6 +476,10 @@ int add_rknand_device(struct rknand_info * prknand_Info)
}
gpNandInfo->SysImageWriteEndAdd = SysImageWriteEndAdd;
//if(gpNandInfo->nand_timing_config)
// gpNandInfo->nand_timing_config(100*1000);
return 0;
}
@@ -358,7 +495,8 @@ static int rknand_probe(struct platform_device *pdev)
{
struct rknand_info *nand_info;
int err = 0;
NAND_DEBUG(NAND_DEBUG_LEVEL0,"rk28xxnand_probe: \n");
printk("nand init...\n");
NAND_DEBUG(NAND_DEBUG_LEVEL0,"rk30xxnand_probe: \n");
gpNandInfo = kzalloc(sizeof(struct rknand_info), GFP_KERNEL);
if (!gpNandInfo)
return -ENOMEM;