rknand driver compiled as a module. need updata android soft code...
authorzhaoyifeng <zyf@rock-chips.com>
Mon, 13 Jun 2011 10:08:57 +0000 (18:08 +0800)
committerzhaoyifeng <zyf@rock-chips.com>
Mon, 13 Jun 2011 10:08:57 +0000 (18:08 +0800)
drivers/mtd/rknand/Kconfig
drivers/mtd/rknand/Makefile
drivers/mtd/rknand/rknand_base.h [new file with mode: 0755]
drivers/mtd/rknand/rknand_base_ko.c [new file with mode: 0755]

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