mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
rk30 nand driver.
This commit is contained in:
32
arch/arm/mach-rk30/board-rk30-sdk.c
Normal file → Executable file
32
arch/arm/mach-rk30/board-rk30-sdk.c
Normal file → Executable 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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user