import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / nand / mt8127 / partition_mt.c
1 /******************************************************************************
2 * partition_mt.c - MT6516 NAND partition managment Driver
3 *
4 * Copyright 2009-2010 MediaTek Co.,Ltd.
5 *
6 * DESCRIPTION:
7 * This file provid the other drivers partition relative functions
8 *
9 * modification history
10 * ----------------------------------------
11 * v1.0, 28 Feb 2011, mtk80134 written
12 * ----------------------------------------
13 ******************************************************************************/
14
15 #include <linux/slab.h>
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/delay.h>
19 #include <linux/errno.h>
20 #include <linux/sched.h>
21 #include <linux/types.h>
22 #include <linux/wait.h>
23 #include <linux/spinlock.h>
24 #include <linux/mtd/nand_ecc.h>
25 #include <linux/platform_device.h>
26 #include <linux/proc_fs.h>
27 #include <linux/time.h>
28 #include <linux/miscdevice.h>
29
30 #include <linux/mtd/mtd.h>
31 #include <linux/mtd/nand.h>
32 #include <linux/mtd/partitions.h>
33
34 #include <asm/io.h>
35 #include <asm/cacheflush.h>
36 #include <asm/uaccess.h>
37
38 #include <mach/mt_typedefs.h>
39 #include <mach/mt_clkmgr.h>
40 #include <mach/mtk_nand.h>
41 #include "board-custom.h"
42 #include "pmt.h"
43 //#include "partition.h"
44 #include <mach/board.h>
45
46 #define PMT 1
47 #ifdef PMT
48
49 #if defined(MTK_MLC_NAND_SUPPORT)
50 extern bool MLC_DEVICE;// to build pass xiaolei
51 #endif
52
53 unsigned long long partition_type_array[PART_MAX_COUNT];
54
55 pt_resident new_part[PART_MAX_COUNT];
56 pt_resident lastest_part[PART_MAX_COUNT];
57 unsigned char part_name[PART_MAX_COUNT][MAX_PARTITION_NAME_LEN];
58 struct mtd_partition g_pasStatic_Partition[PART_MAX_COUNT];
59 int part_num;
60 //struct excel_info PartInfo[PART_MAX_COUNT];
61
62 #define MTD_SECFG_STR "seccnfg"
63 #define MTD_BOOTIMG_STR "boot"
64 #define MTD_ANDROID_STR "system"
65 #define MTD_SECRO_STR "secstatic"
66 #define MTD_USRDATA_STR "userdata"
67
68 int block_size;
69 int page_size;
70 pt_info pi;
71 u8 sig_buf[PT_SIG_SIZE];
72 //not support add new partition automatically.
73
74 extern struct mtd_partition g_pasStatic_Partition[];
75 extern int part_num;
76
77 DM_PARTITION_INFO_PACKET pmtctl;
78 struct mtd_partition g_exist_Partition[PART_MAX_COUNT];
79
80 //#define LPAGE 2048
81 //char page_buf[LPAGE+64];
82 //char page_readbuf[LPAGE];
83 char *page_buf;
84 char *page_readbuf;
85
86 #define PMT_MAGIC 'p'
87 #define PMT_READ _IOW(PMT_MAGIC, 1, int)
88 #define PMT_WRITE _IOW(PMT_MAGIC, 2, int)
89 #define PMT_VERSION _IOW(PMT_MAGIC, 3, int)
90
91
92 extern bool g_bInitDone;
93 extern struct mtk_nand_host *host;
94
95 #if defined(MTK_SPI_NAND_SUPPORT)
96 extern snand_flashdev_info devinfo;
97 #else
98 extern flashdev_info_t devinfo;
99 #endif
100 typedef u32 (*GetLowPageNumber)(u32 pageNo);
101 extern GetLowPageNumber functArray[];
102 #if 0
103 struct pmt_config
104 {
105 int (*read_pmt) (char *buf);
106 int (*write_pmt) (char *buf);
107 }
108 static struct pmt_config g_partition_fuc;
109 #endif
110 static bool init_pmt_done = FALSE;
111 int new_part_tab(u8 * buf, struct mtd_info *mtd);
112 int update_part_tab(struct mtd_info *mtd);
113 static int read_pmt(void __user *arg);
114 void get_part_tab_from_complier(void)
115 {
116 int index=0;
117 printk(KERN_INFO "get_pt_from_complier \n");
118
119 memcpy(&g_exist_Partition, &g_pasStatic_Partition, sizeof(struct mtd_partition) * PART_MAX_COUNT);
120
121 #if 0
122 while (g_pasStatic_Partition[index].size != MTDPART_SIZ_FULL) //the last partition sizefull ==0
123 {
124
125 memcpy(lastest_part[index].name, g_pasStatic_Partition[index].name, MAX_PARTITION_NAME_LEN);
126 lastest_part[index].size = g_pasStatic_Partition[index].size;
127 lastest_part[index].offset = g_pasStatic_Partition[index].offset;
128 lastest_part[index].mask_flags = g_pasStatic_Partition[index].mask_flags; //this flag in kernel should be fufilled even though in flash is 0.
129 printk(KERN_INFO "get_ptr %s %llx \n", lastest_part[index].name, lastest_part[index].offset);
130 index++;
131 }
132 //get last partition info
133 memcpy(lastest_part[index].name, g_pasStatic_Partition[index].name, MAX_PARTITION_NAME_LEN);
134 lastest_part[index].size = g_pasStatic_Partition[index].size;
135 lastest_part[index].offset = g_pasStatic_Partition[index].offset;
136 lastest_part[index].mask_flags = g_pasStatic_Partition[index].mask_flags; //this flag in kernel should be fufilled even though in flash is 0.
137 printk(KERN_INFO "get_ptr %s %llx \n", lastest_part[index].name, lastest_part[index].offset);
138 #endif
139 }
140
141 u64 part_get_startaddress(u64 byte_address, u32 *idx)
142 {
143 int index = 0;
144 if(TRUE == init_pmt_done)
145 {
146 while (index < part_num) {
147 //MSG(INIT, "g_exist_Partition[%d].offset %x\n",index, g_exist_Partition[index].offset);
148 if(g_exist_Partition[index].offset > byte_address)
149 {
150 //MSG(INIT, "find g_exist_Partition[%d].offset %x\n",index-1, g_exist_Partition[index-1].offset);
151 *idx = index-1;
152 return g_exist_Partition[index-1].offset;
153 }
154 index++;
155 }
156 }
157 *idx = part_num-1;
158 return byte_address;
159 }
160
161 bool raw_partition(u32 index)
162 {
163 if(partition_type_array[index] == REGION_LOW_PAGE)
164 return TRUE;
165
166 return FALSE;
167 }
168
169 int find_empty_page_from_top(u64 start_addr, struct mtd_info *mtd)
170 {
171 int page_offset;//,i;
172 u64 current_add;
173 #if defined(MTK_MLC_NAND_SUPPORT)
174 int i;
175 #endif
176 struct mtd_oob_ops ops_pt;
177 struct erase_info ei;
178
179 ei.mtd = mtd;
180 ei.len = mtd->erasesize;
181 ei.time = 1000;
182 ei.retries = 2;
183 ei.callback = NULL;
184
185 ops_pt.datbuf = (uint8_t *) page_buf;
186 ops_pt.mode = MTD_OPS_AUTO_OOB;
187 ops_pt.len = mtd->writesize;
188 ops_pt.retlen = 0;
189 ops_pt.ooblen = 16;
190 ops_pt.oobretlen = 0;
191 ops_pt.oobbuf = page_buf + page_size;
192 ops_pt.ooboffs = 0;
193 memset(page_buf, 0xFF, page_size + mtd->oobsize);
194 memset(page_readbuf, 0xFF, page_size);
195 //mt6577_nand_erase(start_addr); //for test
196 #if defined(MTK_MLC_NAND_SUPPORT)
197 for (page_offset = 0,i=0; page_offset < (block_size / page_size); page_offset = functArray[devinfo.feature_set.ptbl_idx](i++))
198 #else
199 for (page_offset = 0; page_offset < (block_size / page_size); page_offset++)
200 #endif
201 {
202 current_add = start_addr + (page_offset * page_size);
203 if (mtd->_read_oob(mtd, (loff_t) current_add, &ops_pt) != 0)
204 {
205 printk(KERN_INFO "find_emp read failed %llx \n", current_add);
206 continue;
207 } else
208 {
209 if (memcmp(page_readbuf, page_buf, page_size) || memcmp(page_buf + page_size, page_readbuf, 32))
210 {
211 continue;
212 } else
213 {
214 printk(KERN_INFO "find_emp at %x \n", page_offset);
215 break;
216 }
217
218 }
219 }
220 printk(KERN_INFO "find_emp find empty at %x \n", page_offset);
221
222 //i=(0x40);
223 //printk (KERN_INFO "test code %x \n",i);
224 //page_offset = 0x40;
225 if (page_offset != 0x40)
226 {
227 printk(KERN_INFO "find_emp at %x\n", page_offset);
228 return page_offset;
229 } else
230 {
231 printk(KERN_INFO "find_emp no empty \n");
232 ei.addr = start_addr;
233 if (mtd->_erase(mtd, &ei) != 0)
234 { //no good block for used in replace pool
235 printk(KERN_INFO "find_emp erase mirror failed %llx\n", start_addr);
236 pi.mirror_pt_has_space = 0;
237 return 0xFFFF;
238 } else
239 {
240 return 0; //the first page is empty
241 }
242
243 }
244 }
245
246 bool find_mirror_pt_from_bottom(u64 *start_addr, struct mtd_info * mtd)
247 {
248 int mpt_locate,i;
249 u64 mpt_start_addr;
250 u64 current_start_addr = 0;
251 u8 pmt_spare[4];
252 struct mtd_oob_ops ops_pt;
253
254 mpt_start_addr = ((mtd->size) + block_size);
255 //mpt_start_addr=MPT_LOCATION*block_size-page_size;
256 memset(page_buf, 0xFF, page_size + mtd->oobsize);
257
258 ops_pt.datbuf = (uint8_t *) page_buf;
259 ops_pt.mode = MTD_OPS_AUTO_OOB;
260 ops_pt.len = mtd->writesize;
261 ops_pt.retlen = 0;
262 ops_pt.ooblen = 16;
263 ops_pt.oobretlen = 0;
264 ops_pt.oobbuf = page_buf + page_size;
265 ops_pt.ooboffs = 0;
266 printk(KERN_INFO "find_mirror find begain at %llx \n", mpt_start_addr);
267
268 for (mpt_locate = ((block_size / page_size) - 1),i = ((block_size / page_size) - 1); mpt_locate >= 0; mpt_locate--)//mpt_locate--)
269 {
270 memset(pmt_spare, 0xFF, PT_SIG_SIZE);
271
272 current_start_addr = mpt_start_addr + mpt_locate * page_size;
273 if (mtd->_read_oob(mtd, (loff_t) current_start_addr, &ops_pt) != 0)
274 {
275 printk(KERN_INFO "find_mirror read failed %llx %x \n", current_start_addr, mpt_locate);
276 }
277 memcpy(pmt_spare, &page_buf[page_size], PT_SIG_SIZE); //auto do need skip bad block
278 //need enhance must be the larget sequnce number
279 #if 0
280 {
281 int i;
282 for (i = 0; i < 8; i++)
283 {
284 printk(KERN_INFO "%x %x \n", page_buf[i], page_buf[2048 + i]);
285 }
286
287 }
288 #endif
289 if (is_valid_mpt(page_buf) && is_valid_mpt(pmt_spare))
290 {
291 //if no pt, pt.has space is 0;
292 pi.sequencenumber = page_buf[PT_SIG_SIZE + page_size];
293 printk(KERN_INFO "find_mirror find valid pt at %llx sq %x \n", current_start_addr, pi.sequencenumber);
294 break;
295 } else
296 {
297 continue;
298 }
299 }
300 if (mpt_locate == -1)
301 {
302 printk(KERN_INFO "no valid mirror page\n");
303 pi.sequencenumber = 0;
304 return FALSE;
305 } else
306 {
307 *start_addr = current_start_addr;
308 return TRUE;
309 }
310 }
311
312 //int load_exist_part_tab(u8 *buf,struct mtd_info *mtd)
313 int load_exist_part_tab(u8 * buf)
314 {
315 u64 pt_start_addr;
316 u64 pt_cur_addr;
317 int pt_locate,i;
318 int reval = DM_ERR_OK;
319 u64 mirror_address;
320
321 //u8 pmt_spare[PT_SIG_SIZE];
322 struct mtd_oob_ops ops_pt;
323 struct mtd_info *mtd;
324 mtd = &host->mtd;
325
326
327 block_size = mtd->erasesize; // devinfo.blocksize*1024;
328 page_size = mtd->writesize; // devinfo.pagesize;
329 //if(host->hw->nand_sec_shift == 10) //MLC
330 // block_size = block_size >> 1;
331 pt_start_addr = (mtd->size);
332 //pt_start_addr=PT_LOCATION*block_size;
333 printk(KERN_INFO "load_exist_part_tab %llx\n", pt_start_addr);
334 ops_pt.datbuf = (uint8_t *) page_buf;
335 ops_pt.mode = MTD_OPS_AUTO_OOB;
336 ops_pt.len = mtd->writesize;
337 ops_pt.retlen = 0;
338 ops_pt.ooblen = 16;
339 ops_pt.oobretlen = 0;
340 ops_pt.oobbuf = (page_buf + page_size);
341 ops_pt.ooboffs = 0;
342
343 printk(KERN_INFO "ops_pt.len %x \n", ops_pt.len);
344 if (mtd->_read_oob == NULL)
345 {
346 printk(KERN_INFO "shoud not happpen \n");
347 }
348
349 for (pt_locate = 0,i = 0; pt_locate < (block_size / page_size); pt_locate++)
350 {
351 pt_cur_addr = pt_start_addr + pt_locate * page_size;
352 //memset(pmt_spare,0xFF,PT_SIG_SIZE);
353
354 //printk (KERN_INFO "load_pt read pt %x \n",pt_cur_addr);
355
356 if (mtd->_read_oob(mtd, (loff_t) pt_cur_addr, &ops_pt) != 0)
357 {
358 printk(KERN_INFO "load_pt read pt failded: %llx\n", (u64) pt_cur_addr);
359 }
360 #if 0
361 {
362 int i;
363 for (i = 0; i < 8; i++)
364 {
365 printk(KERN_INFO "%x %x \n", *(page_buf + i), *(page_buf + 2048 + i));
366 }
367
368 }
369 #endif
370 //memcpy(pmt_spare,&page_buf[LPAGE] ,PT_SIG_SIZE); //do not need skip bad block flag
371 if (is_valid_pt(page_buf) && is_valid_pt(page_buf + mtd->writesize))
372 {
373 pi.sequencenumber = page_buf[PT_SIG_SIZE + page_size];
374 printk(KERN_INFO "load_pt find valid pt at %llx sq %x \n", pt_start_addr, pi.sequencenumber);
375 break;
376 } else
377 {
378 continue;
379 }
380 }
381 //for test
382 //pt_locate=(block_size/page_size);
383 if (pt_locate == (block_size / page_size))
384 {
385 //first download or download is not compelte after erase or can not download last time
386 printk(KERN_INFO "load_pt find pt failed \n");
387 pi.pt_has_space = 0; //or before download pt power lost
388
389 if (!find_mirror_pt_from_bottom(&mirror_address, mtd))
390 {
391 printk(KERN_INFO "First time download \n");
392 reval = ERR_NO_EXIST;
393 return reval;
394 } else
395 {
396 //used the last valid mirror pt, at lease one is valid.
397 mtd->_read_oob(mtd, (loff_t) mirror_address, &ops_pt);
398 }
399 }
400 memcpy(&lastest_part, &page_buf[PT_SIG_SIZE], sizeof(lastest_part));
401
402 return reval;
403 }
404
405 static int pmt_open(struct inode *inode, struct file *filp)
406 {
407 printk(KERN_INFO "[%s]:(MAJOR)%d:(MINOR)%d\n", __func__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
408 //filp->private_data = (int*);
409 return 0;
410 }
411
412 static int pmt_release(struct inode *inode, struct file *filp)
413 {
414 printk(KERN_INFO "[%s]:(MAJOR)%d:(MINOR)%d\n", __func__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
415 return 0;
416 }
417
418 static long pmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
419 {
420 long ret = 0; // , i=0;
421 ulong version = PT_SIG;
422
423 void __user *uarg = (void __user *)arg;
424 printk(KERN_INFO "PMT IOCTL: Enter\n");
425
426
427 if (false == g_bInitDone)
428 {
429 printk(KERN_INFO "ERROR: NAND Flash Not initialized !!\n");
430 ret = -EFAULT;
431 goto exit;
432 }
433
434 switch (cmd)
435 {
436 case PMT_READ:
437 printk(KERN_INFO "PMT IOCTL: PMT_READ\n");
438 ret = read_pmt(uarg);
439 break;
440 case PMT_WRITE:
441 printk(KERN_INFO "PMT IOCTL: PMT_WRITE\n");
442 if (copy_from_user(&pmtctl, uarg, sizeof(DM_PARTITION_INFO_PACKET)))
443 {
444 ret = -EFAULT;
445 goto exit;
446 }
447 new_part_tab((u8 *) & pmtctl, (struct mtd_info *)&host->mtd);
448 update_part_tab((struct mtd_info *)&host->mtd);
449
450 break;
451 case PMT_VERSION:
452 if(copy_to_user((void __user *)arg,&version,PT_SIG_SIZE))
453 ret= -EFAULT;
454 else
455 ret=0;
456 break;
457 default:
458 ret = -EINVAL;
459 }
460 exit:
461 return ret;
462 }
463 static int read_pmt(void __user *arg)
464 {
465 printk(KERN_ERR "read_pmt\n");
466
467 if(copy_to_user(arg,&lastest_part,sizeof(pt_resident)*PART_MAX_COUNT))
468 return -EFAULT;
469 return 0;
470 }
471
472 static struct file_operations pmt_fops = {
473 .owner = THIS_MODULE,
474 .unlocked_ioctl = pmt_ioctl,
475 .open = pmt_open,
476 .release = pmt_release,
477 };
478
479 static struct miscdevice pmt_dev = {
480 .minor = MISC_DYNAMIC_MINOR,
481 .name = "pmt",
482 .fops = &pmt_fops,
483 };
484
485 static int lowercase(int c)
486 {
487 if((c >= 'A') && (c <= 'Z'))
488 c += 'a' - 'A';
489 return c;
490 }
491
492 void construct_mtd_partition(struct mtd_info *mtd)
493 {
494 int i,j;
495 for(i = 0; i < PART_MAX_COUNT; i++)
496 {
497 //if((lastest_part[i].size == 0) && (strcmp(lastest_part[i].name,"BMTPOOL")))
498 // break;
499 if(!strcmp(lastest_part[i-1].name,"BMTPOOL"))
500 break;
501
502 for(j=0; j < MAX_PARTITION_NAME_LEN; j++)
503 {
504 if(lastest_part[i].name[j] == 0)
505 break;
506 part_name[i][j] = lowercase(lastest_part[i].name[j]);
507 }
508 PartInfo[i].name = part_name[i];
509 g_exist_Partition[i].name = part_name[i];
510 if(!strcmp(lastest_part[i].name,"SECCFG"))
511 g_exist_Partition[i].name = MTD_SECFG_STR;
512
513 if(!strcmp(lastest_part[i].name,"BOOTIMG"))
514 g_exist_Partition[i].name = MTD_BOOTIMG_STR;
515
516 if(!strcmp(lastest_part[i].name,"SEC_RO"))
517 g_exist_Partition[i].name = MTD_SECRO_STR;
518
519 if(!strcmp(lastest_part[i].name,"ANDROID"))
520 g_exist_Partition[i].name = MTD_ANDROID_STR;
521
522 if(!strcmp(lastest_part[i].name,"USRDATA"))
523 g_exist_Partition[i].name = MTD_USRDATA_STR;
524
525 g_exist_Partition[i].size = (uint64_t) lastest_part[i].size;//mtd partition
526 g_exist_Partition[i].offset = (uint64_t) lastest_part[i].offset;
527
528 g_exist_Partition[i].mask_flags = lastest_part[i].mask_flags;
529
530 //PartInfo[i].name = part_name[i]; //dumchar
531 PartInfo[i].type = NAND;
532 PartInfo[i].start_address = lastest_part[i].offset;
533 PartInfo[i].size = lastest_part[i].size;
534 partition_type_array[i]= lastest_part[i].part_id;
535 printk("partition %s %s size %llx\n", lastest_part[i].name,PartInfo[i].name, g_exist_Partition[i].offset);
536
537 #if 1
538 if(MLC_DEVICE == TRUE)
539 {
540 mtd->eraseregions[i].offset = lastest_part[i].offset;
541 mtd->eraseregions[i].erasesize = mtd->erasesize;
542
543 if(partition_type_array[i] == REGION_LOW_PAGE)
544 {
545 mtd->eraseregions[i].erasesize = mtd->erasesize/2;
546 }
547
548 mtd->numeraseregions++;
549 }
550 #endif
551 }
552 part_num = i;
553 g_exist_Partition[i-1].size = MTDPART_SIZ_FULL;
554 }
555
556 void part_init_pmt(struct mtd_info *mtd, u8 * buf)
557 {
558 struct mtd_partition *part;
559 u64 lastblk;
560 int retval = 0;
561 int i = 0;
562 int err = 0;
563 printk(KERN_INFO "part_init_pmt %s\n", __TIME__);
564 page_buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
565 page_readbuf = kzalloc(mtd->writesize, GFP_KERNEL);
566 #if 0
567 part = &g_pasStatic_Partition[0];
568 lastblk = part->offset + part->size;
569 printk(KERN_INFO "offset %llx part->size %llx %s\n", part->offset, part->size, part->name);
570
571 while (1)
572 {
573 part++;
574 if(part->offset == MTDPART_OFS_APPEND)
575 part->offset = lastblk;
576 lastblk = part->offset + part->size;
577 printk(KERN_INFO "mt_part_init_pmt %llx\n", part->offset);
578 if (part->size == 0) ////the last partition sizefull ==0
579 {
580 break;
581 }
582 }
583 #endif
584
585 memset(&pi, 0xFF, sizeof(pi));
586 memset(&lastest_part, 0, PART_MAX_COUNT * sizeof(pt_resident));
587 retval = load_exist_part_tab(buf);
588
589 if (retval == ERR_NO_EXIST) //first run preloader before dowload
590 {
591 //and valid mirror last download or first download
592 printk(KERN_INFO "%s no pt \n", __func__);
593 get_part_tab_from_complier(); //get from complier
594 if(MLC_DEVICE == TRUE)
595 mtd->numeraseregions = 0;
596 for (i = 0; i < part_num; i++)
597 {
598 #if 1
599 if(MLC_DEVICE == TRUE)
600 {
601 mtd->eraseregions[i].offset = lastest_part[i].offset;
602 mtd->eraseregions[i].erasesize = mtd->erasesize;
603 if(partition_type_array[i] == REGION_LOW_PAGE)
604 {
605 mtd->eraseregions[i].erasesize = mtd->erasesize/2;
606 }
607
608 mtd->numeraseregions++;
609 }
610 #endif
611 }
612 } else
613 {
614 printk(KERN_INFO "Find pt or mpt \n");
615 if(MLC_DEVICE == TRUE)
616 mtd->numeraseregions = 0;
617 #if 0
618 memcpy(&g_exist_Partition, &g_pasStatic_Partition, sizeof(struct mtd_partition) * part_num);
619 for (i = 0; i < part_num; i++)
620 {
621 printk(KERN_INFO "partition %s size %llx %llx \n", lastest_part[i].name, lastest_part[i].offset, lastest_part[i].size);
622 //still use the name in g_pasSatic_partition
623 g_exist_Partition[i].size = lastest_part[i].size;
624 g_exist_Partition[i].offset = lastest_part[i].offset;
625 #if 1
626 if(MLC_DEVICE == TRUE)
627 {
628 mtd->eraseregions[i].offset = lastest_part[i].offset;
629 mtd->eraseregions[i].erasesize = mtd->erasesize;
630 #if 0//to build pass xiaolei
631 if(partition_type_array[i] == TYPE_RAW)
632 {
633 mtd->eraseregions[i].erasesize = mtd->erasesize/2;
634 }
635 #endif
636 mtd->numeraseregions++;
637 }
638 #endif
639 //still use the mask flag in g_pasSatic_partition
640 if (i == (part_num - 1))
641 {
642 g_exist_Partition[i].size = MTDPART_SIZ_FULL;
643 }
644 printk(KERN_INFO "partition %s size %llx\n", lastest_part[i].name, g_exist_Partition[i].offset);
645 }
646 #endif
647 construct_mtd_partition(mtd);
648 }
649 init_pmt_done = TRUE;
650
651 printk(KERN_INFO ": register NAND PMT device ...\n");
652 #ifndef MTK_EMMC_SUPPORT
653
654 err = misc_register(&pmt_dev);
655 if (unlikely(err))
656 {
657 printk(KERN_INFO "PMT failed to register device!\n");
658 //return err;
659 }
660 #endif
661 }
662
663 int new_part_tab(u8 * buf, struct mtd_info *mtd)
664 {
665 DM_PARTITION_INFO_PACKET *dm_part = (DM_PARTITION_INFO_PACKET *) buf;
666 int part_num, change_index, i = 0;
667 int retval;
668 int pageoffset;
669 u64 start_addr = (u64)((mtd->size) + block_size);
670 u64 current_addr = 0;
671 struct mtd_oob_ops ops_pt;
672
673 pi.pt_changed = 0;
674 pi.tool_or_sd_update = 2; //tool download is 1.
675
676 ops_pt.mode = MTD_OPS_AUTO_OOB;
677 ops_pt.len = mtd->writesize;
678 ops_pt.retlen = 0;
679 ops_pt.ooblen = 16;
680 ops_pt.oobretlen = 0;
681 ops_pt.oobbuf = page_buf + page_size;
682 ops_pt.ooboffs = 0;
683 //the first image is ?
684 #if 1
685 for (part_num = 0; part_num < PART_MAX_COUNT; part_num++)
686 {
687 memcpy(new_part[part_num].name, dm_part->part_info[part_num].part_name, MAX_PARTITION_NAME_LEN);
688 new_part[part_num].offset = dm_part->part_info[part_num].start_addr;
689 new_part[part_num].size = dm_part->part_info[part_num].part_len;
690 new_part[part_num].mask_flags = 0;
691 //MSG (INIT, "DM_PARTITION_INFO_PACKET %s size %x %x \n",dm_part->part_info[part_num].part_name,dm_part->part_info[part_num].part_len,part_num);
692 printk(KERN_INFO "new_pt %s size %llx \n", new_part[part_num].name, new_part[part_num].size);
693 if (dm_part->part_info[part_num].part_len == 0)
694 {
695 printk(KERN_INFO "new_pt last %x \n", part_num);
696 break;
697 }
698 }
699 #endif
700 //++++++++++for test
701 #if 0
702 part_num = 13;
703 memcpy(&new_part[0], &lastest_part[0], sizeof(new_part));
704 MSG(INIT, "new_part %x size \n", sizeof(new_part));
705 for (i = 0; i < part_num; i++)
706 {
707 MSG(INIT, "npt partition %s size \n", new_part[i].name);
708 //MSG (INIT, "npt %x size \n",new_part[i].offset);
709 //MSG (INIT, "npt %x size \n",lastest_part[i].offset);
710 //MSG (INIT, "npt %x size \n",new_part[i].size);
711 dm_part->part_info[5].part_visibility = 1;
712 dm_part->part_info[5].dl_selected = 1;
713 new_part[5].size = lastest_part[5].size + 0x100000;
714 }
715 #endif
716 //------------for test
717 //Find the first changed partition, whether is visible
718 for (change_index = 0; change_index <= part_num; change_index++)
719 {
720 if ((new_part[change_index].size != lastest_part[change_index].size) || (new_part[change_index].offset != lastest_part[change_index].offset))
721 {
722 printk(KERN_INFO "new_pt %x size changed from %llx to %llx\n", change_index, lastest_part[change_index].size, new_part[change_index].size);
723 pi.pt_changed = 1;
724 break;
725 }
726 }
727
728 if (pi.pt_changed == 1)
729 {
730 //Is valid image update
731 for (i = change_index; i <= part_num; i++)
732 {
733
734 if (dm_part->part_info[i].dl_selected == 0 && dm_part->part_info[i].part_visibility == 1)
735 {
736 printk(KERN_INFO "Full download is need %x \n", i);
737 retval = DM_ERR_NO_VALID_TABLE;
738 return retval;
739 }
740 }
741
742 pageoffset = find_empty_page_from_top(start_addr, mtd);
743 //download partition used the new partition
744 //write mirror at the same 2 page
745 memset(page_buf, 0xFF, page_size + 64);
746 *(int *)sig_buf = MPT_SIG;
747 memcpy(page_buf, &sig_buf, PT_SIG_SIZE);
748 memcpy(&page_buf[PT_SIG_SIZE], &new_part[0], sizeof(new_part));
749 memcpy(&page_buf[page_size], &sig_buf, PT_SIG_SIZE);
750 pi.sequencenumber += 1;
751 memcpy(&page_buf[page_size + PT_SIG_SIZE], &pi, PT_SIG_SIZE);
752
753 if (pageoffset != 0xFFFF)
754 {
755 if ((pageoffset % 2) != 0)
756 {
757 printk(KERN_INFO "new_pt mirror block may destroy last time%x\n", pageoffset);
758 pageoffset += 1;
759 }
760 for (i = 0; i < 2; i++)
761 {
762 current_addr = start_addr + (pageoffset + i) * page_size;
763 ops_pt.datbuf = (uint8_t *) page_buf;
764 if (mtd->_write_oob(mtd, (loff_t) current_addr, &ops_pt) != 0)
765 {
766 printk(KERN_INFO "new_pt write m first page failed %llx\n", current_addr);
767 } else
768 {
769 printk(KERN_INFO "new_pt write mirror at %llx\n", current_addr);
770 ops_pt.datbuf = (uint8_t *) page_readbuf;
771 //read back verify
772 if ((mtd->_read_oob(mtd, (loff_t) current_addr, &ops_pt) != 0) || memcmp(page_buf, page_readbuf, page_size))
773 {
774 printk(KERN_INFO "new_pt read or verify first mirror page failed %llx \n", current_addr);
775 ops_pt.datbuf = (uint8_t *) page_buf;
776 memset(page_buf, 0, PT_SIG_SIZE);
777 if (mtd->_read_oob(mtd, (loff_t) current_addr, &ops_pt) != 0)
778 {
779 printk(KERN_INFO "new_pt mark failed %llx\n", current_addr);
780 }
781 } else
782 {
783 printk(KERN_INFO "new_pt write mirror ok %x\n", i);
784 //any one success set this flag?
785 pi.mirror_pt_dl = 1;
786 }
787 }
788 }
789 }
790 } else
791 {
792 printk(KERN_INFO "new_part_tab no pt change %x\n", i);
793 }
794
795 retval = DM_ERR_OK;
796 return retval;
797 }
798
799 int update_part_tab(struct mtd_info *mtd)
800 {
801 int retval = 0;
802 int retry_w;
803 int retry_r;
804 u64 start_addr = (u64)(mtd->size); //PT_LOCATION*block_size;
805 u64 current_addr = 0;
806 struct erase_info ei;
807 struct mtd_oob_ops ops_pt;
808
809 memset(page_buf, 0xFF, page_size + 64);
810
811 ei.mtd = mtd;
812 ei.len = mtd->erasesize;
813 ei.time = 1000;
814 ei.retries = 2;
815 ei.callback = NULL;
816
817 ops_pt.mode = MTD_OPS_AUTO_OOB;
818 ops_pt.len = mtd->writesize;
819 ops_pt.retlen = 0;
820 ops_pt.ooblen = 16;
821 ops_pt.oobretlen = 0;
822 ops_pt.oobbuf = page_buf + page_size;
823 ops_pt.ooboffs = 0;
824
825 if ((pi.pt_changed == 1 || pi.pt_has_space == 0) && pi.tool_or_sd_update == 2)
826 {
827 printk(KERN_INFO "update_pt pt changes\n");
828
829 ei.addr = start_addr;
830 if (mtd->_erase(mtd, &ei) != 0)
831 { //no good block for used in replace pool
832 printk(KERN_INFO "update_pt erase failed %llx\n", start_addr);
833 if (pi.mirror_pt_dl == 0)
834 retval = DM_ERR_NO_SPACE_FOUND;
835 return retval;
836 }
837
838 for (retry_r = 0; retry_r < RETRY_TIMES; retry_r++)
839 {
840 for (retry_w = 0; retry_w < RETRY_TIMES; retry_w++)
841 {
842 current_addr = start_addr + (retry_w + retry_r * RETRY_TIMES) * page_size;
843 *(int *)sig_buf = PT_SIG;
844 memcpy(page_buf, &sig_buf, PT_SIG_SIZE);
845 memcpy(&page_buf[PT_SIG_SIZE], &new_part[0], sizeof(new_part));
846 memcpy(&page_buf[page_size], &sig_buf, PT_SIG_SIZE);
847 memcpy(&page_buf[page_size + PT_SIG_SIZE], &pi, PT_SIG_SIZE);
848
849 ops_pt.datbuf = (uint8_t *) page_buf;
850 if (mtd->_write_oob(mtd, (loff_t) current_addr, &ops_pt) != 0)
851 { //no good block for used in replace pool . still used the original ones
852 printk(KERN_INFO "update_pt write failed %x\n", retry_w);
853 memset(page_buf, 0, PT_SIG_SIZE);
854 if (mtd->_write_oob(mtd, (loff_t) current_addr, &ops_pt) != 0)
855 {
856 printk(KERN_INFO "write error mark failed\n");
857 //continue retry
858 continue;
859 }
860 } else
861 {
862 printk(KERN_INFO "write pt success %llx %x \n", current_addr, retry_w);
863 break; // retry_w should not count.
864 }
865 }
866 if (retry_w == RETRY_TIMES)
867 {
868 printk(KERN_INFO "update_pt retry w failed\n");
869 if (pi.mirror_pt_dl == 0) //mirror also can not write down
870 {
871 retval = DM_ERR_NO_SPACE_FOUND;
872 return retval;
873 } else
874 {
875 return DM_ERR_OK;
876 }
877 }
878 current_addr = (start_addr + (((retry_w) + retry_r * RETRY_TIMES) * page_size));
879 ops_pt.datbuf = (uint8_t *) page_readbuf;
880 if ((mtd->_read_oob(mtd, (loff_t) current_addr, &ops_pt) != 0) || memcmp(page_buf, page_readbuf, page_size))
881 {
882
883 printk(KERN_INFO "v or r failed %x\n", retry_r);
884 memset(page_buf, 0, PT_SIG_SIZE);
885 ops_pt.datbuf = (uint8_t *) page_buf;
886 if (mtd->_write_oob(mtd, (loff_t) current_addr, &ops_pt) != 0)
887 {
888 printk(KERN_INFO "read error mark failed\n");
889 //continue retryp
890 continue;
891 }
892
893 } else
894 {
895 printk(KERN_INFO "update_pt r&v ok%llx\n", current_addr);
896 break;
897 }
898 }
899 } else
900 {
901 printk(KERN_INFO "update_pt no change \n");
902 }
903 return DM_ERR_OK;
904 }
905
906 int get_part_num_nand()
907 {
908 return part_num;
909 }
910
911 EXPORT_SYMBOL(get_part_num_nand);
912
913 #endif