partition_mt.c 27 KB

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