From: zhaoyifeng Date: Mon, 13 Jun 2011 10:08:57 +0000 (+0800) Subject: rknand driver compiled as a module. need updata android soft code... X-Git-Tag: firefly_0821_release~10203 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=32c1ee749e49fa6ddef5c3f875e1942f687e7434;p=firefly-linux-kernel-4.4.55.git rknand driver compiled as a module. need updata android soft code... --- diff --git a/drivers/mtd/rknand/Kconfig b/drivers/mtd/rknand/Kconfig index 71618f084d69..a3a99d9e956a 100755 --- a/drivers/mtd/rknand/Kconfig +++ b/drivers/mtd/rknand/Kconfig @@ -17,13 +17,6 @@ config MTD_NAND_RK29XX help This enables the RK28xx on-chip NAND flash controller and NFTL driver. -config RKFTL_PAGECACHE_SIZE - int "config page remap mtd part size(MB),MAX is 128MB,this mtd part will mount in /data/data" - depends on MTD_RKNAND - default "64" - help - default size is 64MB,and "swap" size is (128 - 64)MB.if you config this size up to 128MB,then "swap" funtion will disable. - config MTD_RKNAND_BUFFER tristate "RK29 Nand buffer write enables" depends on MTD_RKNAND diff --git a/drivers/mtd/rknand/Makefile b/drivers/mtd/rknand/Makefile index d27bb8c61e1c..c10b5b616541 100755 --- a/drivers/mtd/rknand/Makefile +++ b/drivers/mtd/rknand/Makefile @@ -1,15 +1,9 @@ # -# linux/drivers/nand/Makefile +# linux/drivers/rknand/Makefile # -# $Id: Makefile,v 1.2 2010/12/27 08:46:52 Administrator Exp $ +# $Id: Makefile,v 1.3 2011/01/21 10:12:56 Administrator Exp $ # -obj-$(CONFIG_MTD_NAND_RK29XX) += flash.o ftl.o rknand_base.o emmc.o -obj-$(CONFIG_MTD_RKNAND_BUFFER) += rknand_buffer.o +obj-$(CONFIG_MTD_NAND_RK29XX) += rknand_base_ko.o + + -#obj-$(CONFIG_MTD_UBI) += ubi/ -$(obj)/flash.o: $(obj)/flash.uu - uudecode $(obj)/flash.uu -o $(obj)/flash.o -$(obj)/ftl.o: $(obj)/ftl.uu - uudecode $(obj)/ftl.uu -o $(obj)/ftl.o -$(obj)/rknand_buffer.o: $(obj)/rknand_buffer.uu - uudecode $(obj)/rknand_buffer.uu -o $(obj)/rknand_buffer.o \ No newline at end of file diff --git a/drivers/mtd/rknand/rknand_base.h b/drivers/mtd/rknand/rknand_base.h new file mode 100755 index 000000000000..2bc4f7aa32b6 --- /dev/null +++ b/drivers/mtd/rknand/rknand_base.h @@ -0,0 +1,77 @@ +/* + * linux/drivers/mtd/rknand/rknand_base.c + * + * Copyright (C) 2005-2009 Fuzhou Rockchip Electronics + * ZYF + * + * + */ + +//#include "api_flash.h" + +#define DRIVER_NAME "rk29xxnand" + +#define NAND_DEBUG_LEVEL0 0 +#define NAND_DEBUG_LEVEL1 1 +#define NAND_DEBUG_LEVEL2 2 +#define NAND_DEBUG_LEVEL3 3 +//#define PAGE_REMAP + +#ifndef CONFIG_RKFTL_PAGECACHE_SIZE +#define CONFIG_RKFTL_PAGECACHE_SIZE 64 //¶¨ÒåpageÓ³ÉäÇø´óС£¬µ¥Î»ÎªMB,mount ÔÚ/data/dataÏ¡£ +#endif + +extern unsigned long SysImageWriteEndAdd; +extern int g_num_partitions; + +/* + * rknand_state_t - chip states + * Enumeration for Rknand flash chip state + */ +typedef enum { + FL_READY, + FL_READING, + FL_WRITING, + FL_ERASING, + FL_SYNCING, + FL_UNVALID, +} rknand_state_t; + +struct rknand_chip { + wait_queue_head_t wq; + rknand_state_t state; + int rknand_schedule_enable;//1 enable ,0 disable + void (*pFlashCallBack)(void);//call back funtion +}; + +struct rknand_info { + int enable; + char *pbuf; + int bufSize; + unsigned int SysImageWriteEndAdd; + unsigned int nandCapacity; + struct rknand_chip rknand; + int (*ftl_cache_en)(int en); + int (*ftl_read) (int Index, int nSec, void *buf); + int (*ftl_write) (int Index, int nSec, void *buf ,int mode); + int (*ftl_write_panic) (int Index, int nSec, void *buf); + int (*ftl_close)(void); + int (*ftl_sync)(void); + int (*proc_bufread)(char *page); + int (*proc_ftlread)(char *page); + int (*rknand_schedule_enable)(int en); + int (*add_rknand_device)(struct rknand_info * prknand_Info); + int (*get_rknand_device)(struct rknand_info ** prknand_Info); + void (*rknand_buffer_shutdown)(void); + int (*GetIdBlockSysData)(char * buf, int Sector); + char (*GetSNSectorInfo)(char * pbuf); + char (*GetChipSectorInfo)(char * pbuf); +}; + +extern int rknand_queue_read(int Index, int nSec, void *buf); +extern int rknand_queue_write(int Index, int nSec, void *buf,int mode); +extern int rknand_buffer_init(char * pbuf,int size); +extern void rknand_buffer_shutdown(void); +extern int add_rknand_device(struct rknand_info * prknand_Info); +extern int get_rknand_device(struct rknand_info ** prknand_Info); +extern void rknand_buffer_sync(void); \ No newline at end of file diff --git a/drivers/mtd/rknand/rknand_base_ko.c b/drivers/mtd/rknand/rknand_base_ko.c new file mode 100755 index 000000000000..f8b6c48c18a3 --- /dev/null +++ b/drivers/mtd/rknand/rknand_base_ko.c @@ -0,0 +1,418 @@ +/* + * linux/drivers/mtd/rknand/rknand_base.c + * + * Copyright (C) 2005-2009 Fuzhou Rockchip Electronics + * ZYF + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include "api_flash.h" +#include "rknand_base.h" + + +#define DRIVER_NAME "rk29xxnand" +const char rknand_base_version[] = "rknand_base.c version: 4.26 20110610"; +#define NAND_DEBUG_LEVEL0 0 +#define NAND_DEBUG_LEVEL1 1 +#define NAND_DEBUG_LEVEL2 2 +#define NAND_DEBUG_LEVEL3 3 + +int g_num_partitions = 0; +unsigned long SysImageWriteEndAdd = 0; +struct mtd_info rknand_mtd; +struct mtd_partition *rknand_parts; +struct rknand_info * gpNandInfo; + +#ifdef CONFIG_MTD_NAND_RK29XX_DEBUG +static int s_debug = CONFIG_MTD_NAND_RK29XX_DEBUG_VERBOSE; +#undef NAND_DEBUG +#define NAND_DEBUG(n, format, arg...) \ + if (n <= s_debug) { \ + printk(format,##arg); \ + } +#else +#undef NAND_DEBUG +#define NAND_DEBUG(n, arg...) +static const int s_debug = 0; +#endif + +#include +#include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)) +#define NANDPROC_ROOT (&proc_root) +#else +#define NANDPROC_ROOT NULL +#endif + +#define MAX_BUFFER_SIZE (long)(2048 * 8) //sector +long grknand_buf[MAX_BUFFER_SIZE * 512/4] __attribute__((aligned(4096))); + +static struct proc_dir_entry *my_proc_entry; +extern int rkNand_proc_ftlread(char *page); +extern int rkNand_proc_bufread(char *page); +static int rkNand_proc_read(char *page, + char **start, + off_t offset, int count, int *eof, void *data) +{ + char *buf = page; + int step = offset; + *(int *)start = 1; + if(step == 0) + { + buf += sprintf(buf, "%s\n", rknand_base_version); + if(gpNandInfo->proc_ftlread) + buf += gpNandInfo->proc_ftlread(buf); + if(gpNandInfo->proc_bufread) + buf += gpNandInfo->proc_bufread(buf); + } + return buf - page < count ? buf - page : count; +} + +static void rk28nand_create_procfs(void) +{ + /* Install the proc_fs entry */ + my_proc_entry = create_proc_entry("rk29xxnand", + S_IRUGO | S_IFREG, + NANDPROC_ROOT); + + if (my_proc_entry) { + my_proc_entry->write_proc = NULL; + my_proc_entry->read_proc = rkNand_proc_read; + my_proc_entry->data = NULL; + } +} + +void printk_write_log(long lba,int len, const u_char *pbuf) +{ + char debug_buf[100]; + int i; + for(i=0;i>9; + int LBA = (int)(from>>9); + //printk("rk28xxnand_read: from=%x,len=%x,\n",(int)from,len); + if(sector && gpNandInfo->ftl_read) + { + ret = gpNandInfo->ftl_read(LBA, sector, buf); + } + *retlen = len; + return 0;//ret; +} + +static int rk28xxnand_write(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, const u_char *buf) +{ + int ret = 0; + int sector = len>>9; + int LBA = (int)(from>>9); + //printk("*"); + //printk(KERN_NOTICE "write: from=%lx,len=%x\n",(int)LBA,sector); + //printk_write_log(LBA,sector,buf); + if(sector && gpNandInfo->ftl_write)// cmy + { + if(LBA < SysImageWriteEndAdd)//0x4E000) + { + NAND_DEBUG(NAND_DEBUG_LEVEL0,">>> FtlWriteImage: LBA=0x%08X sector=%d\n",LBA, sector); + ret = gpNandInfo->ftl_write(LBA, sector, (void *)buf,1); + } + else + { + ret = gpNandInfo->ftl_write(LBA, sector, (void *)buf,0); + } + } + *retlen = len; + return 0; +} + +static int rk28xxnand_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + int ret = 0; + if (instr->callback) + instr->callback(instr); + return ret; +} + +static void rk28xxnand_sync(struct mtd_info *mtd) +{ + NAND_DEBUG(NAND_DEBUG_LEVEL0,"rk28xxnand_sync: \n"); + if(gpNandInfo->ftl_sync) + gpNandInfo->ftl_sync(); +} + +extern void FtlWriteCacheEn(int); +static int rk28xxnand_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + int sector = len >> 9; + int LBA = (int)(to >> 9); + + if (sector && gpNandInfo->ftl_write_panic) { + if(gpNandInfo->ftl_cache_en) + gpNandInfo->ftl_cache_en(0); + gpNandInfo->ftl_write_panic(LBA, sector, (void *)buf); + if(gpNandInfo->ftl_cache_en) + gpNandInfo->ftl_cache_en(1); + } + *retlen = len; + return 0; +} + + +int GetIdBlockSysData(char * buf, int Sector) +{ + if(gpNandInfo->GetIdBlockSysData) + return( gpNandInfo->GetIdBlockSysData( buf, Sector)); + return 0; +} + +char GetSNSectorInfo(char * pbuf) +{ + if(gpNandInfo->GetSNSectorInfo) + return( gpNandInfo->GetSNSectorInfo( pbuf)); + return 0; +} + +char GetChipSectorInfo(char * pbuf) +{ + if(gpNandInfo->GetChipSectorInfo) + return( gpNandInfo->GetChipSectorInfo( pbuf)); + return 0; +} + +static int rk28xxnand_block_isbad(struct mtd_info *mtd, loff_t ofs) +{ + return 0; +} + +static int rk28xxnand_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + return 0; +} + +static int rk28xxnand_init(struct rknand_info *nand_info) +{ + struct mtd_info *mtd = &rknand_mtd; + struct rknand_chip *rknand = &nand_info->rknand; + + rknand->state = FL_READY; + rknand->rknand_schedule_enable = 1; + rknand->pFlashCallBack = NULL; + init_waitqueue_head(&rknand->wq); + + mtd->oobsize = 0; + mtd->oobavail = 0; + mtd->ecclayout = 0; + mtd->erasesize = 8*0x200; + mtd->writesize = 8*0x200; + + // Fill in remaining MTD driver data + mtd->type = MTD_NANDFLASH; + mtd->flags = (MTD_WRITEABLE|MTD_NO_ERASE);// + mtd->erase = rk28xxnand_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = rk28xxnand_read; + mtd->write = rk28xxnand_write; + mtd->read_oob = NULL; + mtd->write_oob = NULL; + mtd->panic_write = rk28xxnand_panic_write; + + mtd->sync = rk28xxnand_sync; + mtd->lock = NULL; + mtd->unlock = NULL; + mtd->suspend = NULL; + mtd->resume = NULL; + mtd->block_isbad = rk28xxnand_block_isbad; + mtd->block_markbad = rk28xxnand_block_markbad; + mtd->owner = THIS_MODULE; + return 0; +} + + +/* + * CMY: Ôö¼ÓÁ˶ÔÃüÁîÐзÖÇøÐÅÏ¢µÄÖ§³Ö + * ÈôcmdlineÓÐÌṩ·ÖÇøÐÅÏ¢£¬ÔòʹÓÃcmdlineµÄ·ÖÇøÐÅÏ¢½øÐзÖÇø + * ÈôcmdlineûÓÐÌṩ·ÖÇøÐÅÏ¢£¬ÔòʹÓÃĬÈϵķÖÇøÐÅÏ¢(rk28_partition_info)½øÐзÖÇø + */ + +#ifdef CONFIG_MTD_CMDLINE_PARTS +const char *part_probes[] = { "cmdlinepart", NULL }; +#endif + +static int rk29xxnand_add_partitions(struct rknand_info *nand_info) +{ +#ifdef CONFIG_MTD_CMDLINE_PARTS + int num_partitions = 0; + + // ´ÓÃüÁîÐнâÎö·ÖÇøµÄÐÅÏ¢ + num_partitions = parse_mtd_partitions(&(rknand_mtd), part_probes, &rknand_parts, 0); + NAND_DEBUG(NAND_DEBUG_LEVEL0,"num_partitions = %d\n",num_partitions); + if(num_partitions > 0) { + int i; + for (i = 0; i < num_partitions; i++) + { + rknand_parts[i].offset *= 0x200; + rknand_parts[i].size *=0x200; + } + rknand_parts[num_partitions - 1].size = rknand_mtd.size - rknand_parts[num_partitions - 1].offset; + + g_num_partitions = num_partitions; + return add_mtd_partitions(&(rknand_mtd), rknand_parts, num_partitions); + } +#endif + return 0; +} + +int add_rknand_device(struct rknand_info * prknand_Info) +{ + struct mtd_partition *parts; + int i; + NAND_DEBUG(NAND_DEBUG_LEVEL0,"add_rknand_device: \n"); + + rknand_mtd.size = (uint64_t)gpNandInfo->nandCapacity*0x200; + + rk29xxnand_add_partitions(prknand_Info); + + parts = rknand_parts; + for(i=0;i>> part[%d]: name=%s offset=0x%012llx\n", i, parts[i].name, parts[i].offset); + if(strcmp(parts[i].name,"backup") == 0) + { + SysImageWriteEndAdd = (unsigned long)(parts[i].offset + parts[i].size)>>9;//sector + //printk(">>> SysImageWriteEndAdd=0x%lx\n", SysImageWriteEndAdd); + break; + } + } + + gpNandInfo->SysImageWriteEndAdd = SysImageWriteEndAdd; + return 0; +} + +int get_rknand_device(struct rknand_info ** prknand_Info) +{ + *prknand_Info = gpNandInfo; + return 0; +} + +EXPORT_SYMBOL(get_rknand_device); + +static int rknand_probe(struct platform_device *pdev) +{ + struct rknand_info *nand_info; + int err = 0; + NAND_DEBUG(NAND_DEBUG_LEVEL0,"rk28xxnand_probe: \n"); + gpNandInfo = kzalloc(sizeof(struct rknand_info), GFP_KERNEL); + if (!gpNandInfo) + return -ENOMEM; + + nand_info = gpNandInfo; + + memset(gpNandInfo,0,sizeof(struct rknand_info)); + + gpNandInfo->bufSize = MAX_BUFFER_SIZE * 512; + gpNandInfo->pbuf = grknand_buf; + + rknand_mtd.name = dev_name(&pdev->dev); + rknand_mtd.priv = &nand_info->rknand; + rknand_mtd.owner = THIS_MODULE; + + if(rk28xxnand_init(nand_info)) + { + err = -ENXIO; + goto exit_free; + } + + nand_info->add_rknand_device = add_rknand_device; + nand_info->get_rknand_device = get_rknand_device; + + rk28nand_create_procfs(); + return 0; + +exit_free: + if(nand_info) + kfree(nand_info); + + return err; +} + +static int rknand_suspend(struct platform_device *pdev, pm_message_t state) +{ + gpNandInfo->rknand.rknand_schedule_enable = 0; + NAND_DEBUG(NAND_DEBUG_LEVEL0,"rknand_suspend: \n"); + return 0; +} + +static int rknand_resume(struct platform_device *pdev) +{ + gpNandInfo->rknand.rknand_schedule_enable = 1; + NAND_DEBUG(NAND_DEBUG_LEVEL0,"rknand_resume: \n"); + return 0; +} + +void rknand_shutdown(struct platform_device *pdev) +{ + printk("rknand_shutdown...\n"); + gpNandInfo->rknand.rknand_schedule_enable = 0; + if(gpNandInfo->rknand_buffer_shutdown) + gpNandInfo->rknand_buffer_shutdown(); +} + +static struct platform_driver rknand_driver = { + .probe = rknand_probe, + .suspend = rknand_suspend, + .resume = rknand_resume, + .shutdown = rknand_shutdown, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + + +MODULE_ALIAS(DRIVER_NAME); + +static int __init rknand_init(void) +{ + int ret; + NAND_DEBUG(NAND_DEBUG_LEVEL0,"rknand_init: \n"); + ret = platform_driver_register(&rknand_driver); + NAND_DEBUG(NAND_DEBUG_LEVEL0,"platform_driver_register:ret = %x \n",ret); + return ret; +} + +static void __exit rknand_exit(void) +{ + platform_driver_unregister(&rknand_driver); +} + +module_init(rknand_init); +module_exit(rknand_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ZYF "); +MODULE_DESCRIPTION("rknand driver."); + +