Fix usb copy data error(all the files have same errors: 32KB data is correct and...
[firefly-linux-kernel-4.4.55.git] / drivers / mtd / rknand / rknand_base_ko.c
1 /*\r
2  *  linux/drivers/mtd/rknand/rknand_base.c\r
3  *\r
4  *  Copyright (C) 2005-2009 Fuzhou Rockchip Electronics\r
5  *  ZYF <zyf@rock-chips.com>\r
6  *\r
7  *   \r
8  */\r
9 \r
10 #include <linux/module.h>\r
11 #include <linux/sched.h>\r
12 #include <linux/delay.h>\r
13 #include <linux/init.h>\r
14 #include <linux/slab.h>\r
15 #include <linux/platform_device.h>\r
16 #include <linux/mtd/mtd.h>\r
17 #include <linux/mtd/partitions.h>\r
18 #include <linux/mutex.h>\r
19 #include <linux/kthread.h>\r
20 #include <linux/reboot.h>\r
21 #include <asm/io.h>\r
22 #include <asm/mach/flash.h>\r
23 //#include "api_flash.h"\r
24 #include "rknand_base.h"\r
25 \r
26 \r
27 #define DRIVER_NAME     "rk29xxnand"\r
28 const char rknand_base_version[] = "rknand_base.c version: 4.30 20111009";\r
29 #define NAND_DEBUG_LEVEL0 0\r
30 #define NAND_DEBUG_LEVEL1 1\r
31 #define NAND_DEBUG_LEVEL2 2\r
32 #define NAND_DEBUG_LEVEL3 3\r
33 \r
34 int g_num_partitions = 0;\r
35 unsigned long SysImageWriteEndAdd = 0;\r
36 struct mtd_info         rknand_mtd;  \r
37 struct mtd_partition *rknand_parts;\r
38 struct rknand_info * gpNandInfo;\r
39 \r
40 #ifdef CONFIG_MTD_NAND_RK29XX_DEBUG\r
41 static int s_debug = CONFIG_MTD_NAND_RK29XX_DEBUG_VERBOSE;\r
42 #undef NAND_DEBUG\r
43 #define NAND_DEBUG(n, format, arg...) \\r
44         if (n <= s_debug) {      \\r
45                 printk(format,##arg); \\r
46         }\r
47 #else\r
48 #undef NAND_DEBUG\r
49 #define NAND_DEBUG(n, arg...)\r
50 static const int s_debug = 0;\r
51 #endif\r
52 \r
53 #include <linux/proc_fs.h>\r
54 #include <linux/version.h>\r
55 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))\r
56 #define NANDPROC_ROOT  (&proc_root)\r
57 #else\r
58 #define NANDPROC_ROOT  NULL\r
59 #endif\r
60 \r
61 #define     DATA_LEN            (1024*8*2/4)              //Êý¾Ý¿éµ¥Î»word\r
62 #define     SPARE_LEN           (32*8*2/4)               //УÑéÊý¾Ý³¤¶È\r
63 #define     PAGE_LEN            (DATA_LEN+SPARE_LEN)    //ÿ¸öÊý¾Ýµ¥Î»µÄ³¤¶È\r
64 #define MAX_BUFFER_SIZE     (long)(2048 * 8) //sector\r
65 long grknand_buf[MAX_BUFFER_SIZE * 512/4] __attribute__((aligned(4096)));\r
66 long grknand_dma_buf[PAGE_LEN*4*5] __attribute__((aligned(4096)));\r
67 \r
68 static struct proc_dir_entry *my_proc_entry;\r
69 extern int rkNand_proc_ftlread(char *page);\r
70 extern int rkNand_proc_bufread(char *page);\r
71 static int rkNand_proc_read(char *page,\r
72                            char **start,\r
73                            off_t offset, int count, int *eof, void *data)\r
74 {\r
75         char *buf = page;\r
76         int step = offset;\r
77         *(int *)start = 1;\r
78         if(step == 0)\r
79         {\r
80         buf += sprintf(buf, "%s\n", rknand_base_version);\r
81         if(gpNandInfo->proc_ftlread)\r
82             buf += gpNandInfo->proc_ftlread(buf);\r
83         if(gpNandInfo->proc_bufread)\r
84             buf += gpNandInfo->proc_bufread(buf);\r
85     }\r
86         return buf - page < count ? buf - page : count;\r
87 }\r
88 \r
89 static void rk28nand_create_procfs(void)\r
90 {\r
91     /* Install the proc_fs entry */\r
92     my_proc_entry = create_proc_entry("rk29xxnand",\r
93                            S_IRUGO | S_IFREG,\r
94                            NANDPROC_ROOT);\r
95 \r
96     if (my_proc_entry) {\r
97         my_proc_entry->write_proc = NULL;\r
98         my_proc_entry->read_proc = rkNand_proc_read;\r
99         my_proc_entry->data = NULL;\r
100     } \r
101 }\r
102 \r
103 void printk_write_log(long lba,int len, const u_char *pbuf)\r
104 {\r
105     char debug_buf[100];\r
106     int i;\r
107     for(i=0;i<len;i++)\r
108     {\r
109         sprintf(debug_buf,"%lx :",lba+i);\r
110         print_hex_dump(KERN_WARNING, debug_buf, DUMP_PREFIX_NONE, 16,4, &pbuf[512*i], 8, 0);\r
111     }\r
112 }\r
113 \r
114 static int rk28xxnand_read(struct mtd_info *mtd, loff_t from, size_t len,\r
115         size_t *retlen, u_char *buf)\r
116 {\r
117         int ret = 0;\r
118         int sector = len>>9;\r
119         int LBA = (int)(from>>9);\r
120         //if(rknand_debug)\r
121     //   printk("rk28xxnand_read: from=%x,sector=%x,\n",(int)LBA,sector);\r
122     if(sector && gpNandInfo->ftl_read)\r
123     {\r
124                 ret = gpNandInfo->ftl_read(LBA, sector, buf);\r
125     }\r
126         *retlen = len;\r
127         return 0;//ret;\r
128 }\r
129 \r
130 static int rk28xxnand_write(struct mtd_info *mtd, loff_t from, size_t len,\r
131         size_t *retlen, const u_char *buf)\r
132 {\r
133         int ret = 0;\r
134         int sector = len>>9;\r
135         int LBA = (int)(from>>9);\r
136         //printk("*");\r
137         //if(rknand_debug)\r
138     //    printk(KERN_NOTICE "write: from=%lx,sector=%x\n",(int)LBA,sector);\r
139     //printk_write_log(LBA,sector,buf);\r
140         if(sector && gpNandInfo->ftl_write)// cmy\r
141         {\r
142                 if(LBA < SysImageWriteEndAdd)//0x4E000)\r
143                 {\r
144                         NAND_DEBUG(NAND_DEBUG_LEVEL0,">>> FtlWriteImage: LBA=0x%08X  sector=%d\n",LBA, sector);\r
145             ret = gpNandInfo->ftl_write(LBA, sector, (void *)buf,1);\r
146         }\r
147                 else\r
148         {\r
149             ret = gpNandInfo->ftl_write(LBA, sector, (void *)buf,0);\r
150         }\r
151         }\r
152         *retlen = len;\r
153         return 0;\r
154 }\r
155 \r
156 static int rk28xxnand_erase(struct mtd_info *mtd, struct erase_info *instr)\r
157 {\r
158         int ret = 0;\r
159     if (instr->callback)\r
160                 instr->callback(instr);\r
161         return ret;\r
162 }\r
163 \r
164 static void rk28xxnand_sync(struct mtd_info *mtd)\r
165 {\r
166         NAND_DEBUG(NAND_DEBUG_LEVEL0,"rk28xxnand_sync: \n");\r
167     if(gpNandInfo->ftl_sync)\r
168         gpNandInfo->ftl_sync();\r
169 }\r
170 \r
171 extern void FtlWriteCacheEn(int);\r
172 static int rk28xxnand_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)\r
173 {\r
174         int sector = len >> 9;\r
175         int LBA = (int)(to >> 9);\r
176 \r
177         if (sector && gpNandInfo->ftl_write_panic) {\r
178             if(gpNandInfo->ftl_cache_en)\r
179                     gpNandInfo->ftl_cache_en(0);\r
180                 gpNandInfo->ftl_write_panic(LBA, sector, (void *)buf);\r
181             if(gpNandInfo->ftl_cache_en)\r
182                     gpNandInfo->ftl_cache_en(1);\r
183         }\r
184         *retlen = len;\r
185         return 0;\r
186 }\r
187 \r
188 \r
189 int GetIdBlockSysData(char * buf, int Sector)\r
190 {\r
191     if(gpNandInfo->GetIdBlockSysData)\r
192            return( gpNandInfo->GetIdBlockSysData( buf,  Sector));\r
193     return 0;\r
194 }\r
195 \r
196 char GetSNSectorInfo(char * pbuf)\r
197 {\r
198     if(gpNandInfo->GetSNSectorInfo)\r
199            return( gpNandInfo->GetSNSectorInfo( pbuf));\r
200     return 0;\r
201 }\r
202 \r
203 char GetChipSectorInfo(char * pbuf)\r
204 {\r
205     if(gpNandInfo->GetChipSectorInfo)\r
206            return( gpNandInfo->GetChipSectorInfo( pbuf));\r
207     return 0;\r
208 }\r
209 \r
210 int  GetParamterInfo(char * pbuf , int len)\r
211 {\r
212     int ret = -1;\r
213         int sector = (len)>>9;\r
214         int LBA = 0;\r
215         if(sector && gpNandInfo->ftl_read)\r
216         {\r
217                 ret = gpNandInfo->ftl_read(LBA, sector, pbuf);\r
218         }\r
219         return ret?-1:(sector<<9);\r
220 }\r
221 \r
222 int  GetflashDataByLba(int lba,char * pbuf , int len)\r
223 {\r
224     int ret = -1;\r
225         int sector = (len)>>9;\r
226         int LBA = lba;\r
227         if(sector && gpNandInfo->ftl_read)\r
228         {\r
229                 ret = gpNandInfo->ftl_read(LBA, sector, pbuf);\r
230         }\r
231         return ret?-1:(sector<<9);\r
232 }\r
233 \r
234 \r
235 static int rk28xxnand_block_isbad(struct mtd_info *mtd, loff_t ofs)\r
236 {\r
237         return 0;\r
238 }\r
239 \r
240 static int rk28xxnand_block_markbad(struct mtd_info *mtd, loff_t ofs)\r
241 {\r
242         return 0;\r
243 }\r
244 \r
245 static int rk28xxnand_init(struct rknand_info *nand_info)\r
246 {\r
247         struct mtd_info    *mtd = &rknand_mtd;\r
248         struct rknand_chip *rknand = &nand_info->rknand;  \r
249 \r
250         rknand->state = FL_READY;\r
251         rknand->rknand_schedule_enable = 1;\r
252         rknand->pFlashCallBack = NULL;\r
253         init_waitqueue_head(&rknand->wq);\r
254 \r
255     mtd->oobsize = 0;\r
256     mtd->oobavail = 0;\r
257     mtd->ecclayout = 0;\r
258     mtd->erasesize = 32*0x200;\r
259     mtd->writesize = 8*0x200;\r
260 \r
261         // Fill in remaining MTD driver data \r
262         mtd->type = MTD_NANDFLASH;\r
263         mtd->flags = (MTD_WRITEABLE|MTD_NO_ERASE);//\r
264         mtd->erase = rk28xxnand_erase;\r
265         mtd->point = NULL;\r
266         mtd->unpoint = NULL;\r
267         mtd->read = rk28xxnand_read;\r
268         mtd->write = rk28xxnand_write;\r
269         mtd->read_oob = NULL;\r
270         mtd->write_oob = NULL;\r
271         mtd->panic_write = rk28xxnand_panic_write;\r
272 \r
273         mtd->sync = rk28xxnand_sync;\r
274         mtd->lock = NULL;\r
275         mtd->unlock = NULL;\r
276         mtd->suspend = NULL;\r
277         mtd->resume = NULL;\r
278         mtd->block_isbad = rk28xxnand_block_isbad;\r
279         mtd->block_markbad = rk28xxnand_block_markbad;\r
280         mtd->owner = THIS_MODULE;\r
281     return 0;\r
282 }\r
283 \r
284 \r
285 /*\r
286  * CMY: Ôö¼ÓÁ˶ÔÃüÁîÐзÖÇøÐÅÏ¢µÄÖ§³Ö\r
287  *              ÈôcmdlineÓÐÌṩ·ÖÇøÐÅÏ¢£¬ÔòʹÓÃcmdlineµÄ·ÖÇøÐÅÏ¢½øÐзÖÇø\r
288  *              ÈôcmdlineûÓÐÌṩ·ÖÇøÐÅÏ¢£¬ÔòʹÓÃĬÈϵķÖÇøÐÅÏ¢(rk28_partition_info)½øÐзÖÇø\r
289  */\r
290 \r
291 #ifdef CONFIG_MTD_CMDLINE_PARTS\r
292 const char *part_probes[] = { "cmdlinepart", NULL }; \r
293 #endif \r
294 \r
295 static int rk29xxnand_add_partitions(struct rknand_info *nand_info)\r
296 {\r
297 #ifdef CONFIG_MTD_CMDLINE_PARTS\r
298     int num_partitions = 0; \r
299 \r
300         // ´ÓÃüÁîÐнâÎö·ÖÇøµÄÐÅÏ¢\r
301     num_partitions = parse_mtd_partitions(&(rknand_mtd), part_probes, &rknand_parts, 0); \r
302     NAND_DEBUG(NAND_DEBUG_LEVEL0,"num_partitions = %d\n",num_partitions);\r
303     if(num_partitions > 0) { \r
304         int i;\r
305         for (i = 0; i < num_partitions; i++) \r
306         {\r
307             rknand_parts[i].offset *= 0x200;\r
308             rknand_parts[i].size   *=0x200;\r
309         }\r
310         rknand_parts[num_partitions - 1].size = rknand_mtd.size - rknand_parts[num_partitions - 1].offset;\r
311         \r
312                 g_num_partitions = num_partitions;\r
313                 return add_mtd_partitions(&(rknand_mtd), rknand_parts, num_partitions);\r
314     } \r
315 #endif \r
316         return 0;\r
317 }\r
318 \r
319 int add_rknand_device(struct rknand_info * prknand_Info)\r
320 {\r
321     struct mtd_partition *parts;\r
322     int i;\r
323     NAND_DEBUG(NAND_DEBUG_LEVEL0,"add_rknand_device: \n");\r
324     \r
325     rknand_mtd.size = (uint64_t)gpNandInfo->nandCapacity*0x200;\r
326     \r
327     rk29xxnand_add_partitions(prknand_Info);\r
328  \r
329     parts = rknand_parts;\r
330     for(i=0;i<g_num_partitions;i++)\r
331     {\r
332         //printk(">>> part[%d]: name=%s offset=0x%012llx\n", i, parts[i].name, parts[i].offset);\r
333         if(strcmp(parts[i].name,"backup") == 0)\r
334         {\r
335             SysImageWriteEndAdd = (unsigned long)(parts[i].offset + parts[i].size)>>9;//sector\r
336             //printk(">>> SysImageWriteEndAdd=0x%lx\n", SysImageWriteEndAdd);\r
337             break;\r
338         }\r
339     }\r
340 \r
341     gpNandInfo->SysImageWriteEndAdd = SysImageWriteEndAdd;\r
342     return 0;\r
343 }\r
344 \r
345 int get_rknand_device(struct rknand_info ** prknand_Info)\r
346 {\r
347     *prknand_Info = gpNandInfo;\r
348     return 0;    \r
349 }\r
350 \r
351 EXPORT_SYMBOL(get_rknand_device);\r
352 \r
353 static int rknand_probe(struct platform_device *pdev)\r
354 {\r
355         struct rknand_info *nand_info;\r
356         int err = 0;\r
357         NAND_DEBUG(NAND_DEBUG_LEVEL0,"rk28xxnand_probe: \n");\r
358         gpNandInfo = kzalloc(sizeof(struct rknand_info), GFP_KERNEL);\r
359         if (!gpNandInfo)\r
360                 return -ENOMEM;\r
361     \r
362     nand_info = gpNandInfo;\r
363 \r
364     memset(gpNandInfo,0,sizeof(struct rknand_info));\r
365 \r
366     gpNandInfo->bufSize = MAX_BUFFER_SIZE * 512;\r
367     gpNandInfo->pbuf = (char *)grknand_buf;\r
368     gpNandInfo->pdmaBuf = (char *)grknand_dma_buf;\r
369     //printk(" gpNandInfo->pdmaBuf=0x%x\n",  gpNandInfo->pdmaBuf); \r
370 #ifdef CONFIG_MTD_EMMC_CLK_POWER_SAVE\r
371     gpNandInfo->emmc_clk_power_save_en = 1;\r
372 #endif\r
373 \r
374         rknand_mtd.name = dev_name(&pdev->dev);\r
375         rknand_mtd.priv = &nand_info->rknand;\r
376         rknand_mtd.owner = THIS_MODULE;\r
377     \r
378         if(rk28xxnand_init(nand_info))\r
379         {\r
380                 err = -ENXIO;\r
381                 goto  exit_free;\r
382         }\r
383         \r
384         nand_info->add_rknand_device = add_rknand_device;\r
385         nand_info->get_rknand_device = get_rknand_device;\r
386 \r
387         rk28nand_create_procfs();\r
388         return 0;\r
389 \r
390 exit_free:\r
391         if(nand_info)\r
392         kfree(nand_info);\r
393 \r
394         return err;\r
395 }\r
396 \r
397 static int rknand_suspend(struct platform_device *pdev, pm_message_t state)\r
398 {\r
399     gpNandInfo->rknand.rknand_schedule_enable = 0;\r
400         NAND_DEBUG(NAND_DEBUG_LEVEL0,"rknand_suspend: \n");\r
401         return 0;\r
402 }\r
403 \r
404 static int rknand_resume(struct platform_device *pdev)\r
405 {\r
406     gpNandInfo->rknand.rknand_schedule_enable = 1;\r
407         NAND_DEBUG(NAND_DEBUG_LEVEL0,"rknand_resume: \n");\r
408         return 0;\r
409 }\r
410 \r
411 void rknand_shutdown(struct platform_device *pdev)\r
412 {\r
413     printk("rknand_shutdown...\n");\r
414     gpNandInfo->rknand.rknand_schedule_enable = 0;\r
415     if(gpNandInfo->rknand_buffer_shutdown)\r
416         gpNandInfo->rknand_buffer_shutdown();    \r
417 }\r
418 \r
419 static struct platform_driver rknand_driver = {\r
420         .probe          = rknand_probe,\r
421         .suspend        = rknand_suspend,\r
422         .resume         = rknand_resume,\r
423         .shutdown   = rknand_shutdown,\r
424         .driver         = {\r
425                 .name   = DRIVER_NAME,\r
426                 .owner  = THIS_MODULE,\r
427         },\r
428 };\r
429 \r
430 \r
431 MODULE_ALIAS(DRIVER_NAME);\r
432 \r
433 static int __init rknand_init(void)\r
434 {\r
435         int ret;\r
436         NAND_DEBUG(NAND_DEBUG_LEVEL0,"rknand_init: \n");\r
437         ret = platform_driver_register(&rknand_driver);\r
438         NAND_DEBUG(NAND_DEBUG_LEVEL0,"platform_driver_register:ret = %x \n",ret);\r
439         return ret;\r
440 }\r
441 \r
442 static void __exit rknand_exit(void)\r
443 {\r
444     platform_driver_unregister(&rknand_driver);\r
445 }\r
446 \r
447 module_init(rknand_init);\r
448 module_exit(rknand_exit);\r
449 \r
450 MODULE_LICENSE("GPL");\r
451 MODULE_AUTHOR("ZYF <zyf@rock-chips.com>");\r
452 MODULE_DESCRIPTION("rknand driver.");\r
453 \r
454 \r