sharpslpart.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /*
  2. * sharpslpart.c - MTD partition parser for NAND flash using the SHARP FTL
  3. * for logical addressing, as used on the PXA models of the SHARP SL Series.
  4. *
  5. * Copyright (C) 2017 Andrea Adami <andrea.adami@gmail.com>
  6. *
  7. * Based on SHARP GPL 2.4 sources:
  8. * http://support.ezaurus.com/developer/source/source_dl.asp
  9. * drivers/mtd/nand/sharp_sl_logical.c
  10. * linux/include/asm-arm/sharp_nand_logical.h
  11. *
  12. * Copyright (C) 2002 SHARP
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation; either version 2 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. */
  25. #include <linux/kernel.h>
  26. #include <linux/slab.h>
  27. #include <linux/module.h>
  28. #include <linux/types.h>
  29. #include <linux/bitops.h>
  30. #include <linux/sizes.h>
  31. #include <linux/mtd/mtd.h>
  32. #include <linux/mtd/partitions.h>
  33. /* oob structure */
  34. #define NAND_NOOB_LOGADDR_00 8
  35. #define NAND_NOOB_LOGADDR_01 9
  36. #define NAND_NOOB_LOGADDR_10 10
  37. #define NAND_NOOB_LOGADDR_11 11
  38. #define NAND_NOOB_LOGADDR_20 12
  39. #define NAND_NOOB_LOGADDR_21 13
  40. #define BLOCK_IS_RESERVED 0xffff
  41. #define BLOCK_UNMASK_COMPLEMENT 1
  42. /* factory defaults */
  43. #define SHARPSL_NAND_PARTS 3
  44. #define SHARPSL_FTL_PART_SIZE (7 * SZ_1M)
  45. #define SHARPSL_PARTINFO1_LADDR 0x00060000
  46. #define SHARPSL_PARTINFO2_LADDR 0x00064000
  47. #define BOOT_MAGIC 0x424f4f54
  48. #define FSRO_MAGIC 0x4653524f
  49. #define FSRW_MAGIC 0x46535257
  50. /**
  51. * struct sharpsl_ftl - Sharp FTL Logical Table
  52. * @logmax: number of logical blocks
  53. * @log2phy: the logical-to-physical table
  54. *
  55. * Structure containing the logical-to-physical translation table
  56. * used by the SHARP SL FTL.
  57. */
  58. struct sharpsl_ftl {
  59. unsigned int logmax;
  60. unsigned int *log2phy;
  61. };
  62. /* verify that the OOB bytes 8 to 15 are free and available for the FTL */
  63. static int sharpsl_nand_check_ooblayout(struct mtd_info *mtd)
  64. {
  65. u8 freebytes = 0;
  66. int section = 0;
  67. while (true) {
  68. struct mtd_oob_region oobfree = { };
  69. int ret, i;
  70. ret = mtd_ooblayout_free(mtd, section++, &oobfree);
  71. if (ret)
  72. break;
  73. if (!oobfree.length || oobfree.offset > 15 ||
  74. (oobfree.offset + oobfree.length) < 8)
  75. continue;
  76. i = oobfree.offset >= 8 ? oobfree.offset : 8;
  77. for (; i < oobfree.offset + oobfree.length && i < 16; i++)
  78. freebytes |= BIT(i - 8);
  79. if (freebytes == 0xff)
  80. return 0;
  81. }
  82. return -ENOTSUPP;
  83. }
  84. static int sharpsl_nand_read_oob(struct mtd_info *mtd, loff_t offs, u8 *buf)
  85. {
  86. struct mtd_oob_ops ops = { };
  87. int ret;
  88. ops.mode = MTD_OPS_PLACE_OOB;
  89. ops.ooblen = mtd->oobsize;
  90. ops.oobbuf = buf;
  91. ret = mtd_read_oob(mtd, offs, &ops);
  92. if (ret != 0 || mtd->oobsize != ops.oobretlen)
  93. return -1;
  94. return 0;
  95. }
  96. /*
  97. * The logical block number assigned to a physical block is stored in the OOB
  98. * of the first page, in 3 16-bit copies with the following layout:
  99. *
  100. * 01234567 89abcdef
  101. * -------- --------
  102. * ECC BB xyxyxy
  103. *
  104. * When reading we check that the first two copies agree.
  105. * In case of error, matching is tried using the following pairs.
  106. * Reserved values 0xffff mean the block is kept for wear leveling.
  107. *
  108. * 01234567 89abcdef
  109. * -------- --------
  110. * ECC BB xyxy oob[8]==oob[10] && oob[9]==oob[11] -> byte0=8 byte1=9
  111. * ECC BB xyxy oob[10]==oob[12] && oob[11]==oob[13] -> byte0=10 byte1=11
  112. * ECC BB xy xy oob[12]==oob[8] && oob[13]==oob[9] -> byte0=12 byte1=13
  113. */
  114. static int sharpsl_nand_get_logical_num(u8 *oob)
  115. {
  116. u16 us;
  117. int good0, good1;
  118. if (oob[NAND_NOOB_LOGADDR_00] == oob[NAND_NOOB_LOGADDR_10] &&
  119. oob[NAND_NOOB_LOGADDR_01] == oob[NAND_NOOB_LOGADDR_11]) {
  120. good0 = NAND_NOOB_LOGADDR_00;
  121. good1 = NAND_NOOB_LOGADDR_01;
  122. } else if (oob[NAND_NOOB_LOGADDR_10] == oob[NAND_NOOB_LOGADDR_20] &&
  123. oob[NAND_NOOB_LOGADDR_11] == oob[NAND_NOOB_LOGADDR_21]) {
  124. good0 = NAND_NOOB_LOGADDR_10;
  125. good1 = NAND_NOOB_LOGADDR_11;
  126. } else if (oob[NAND_NOOB_LOGADDR_20] == oob[NAND_NOOB_LOGADDR_00] &&
  127. oob[NAND_NOOB_LOGADDR_21] == oob[NAND_NOOB_LOGADDR_01]) {
  128. good0 = NAND_NOOB_LOGADDR_20;
  129. good1 = NAND_NOOB_LOGADDR_21;
  130. } else {
  131. return -EINVAL;
  132. }
  133. us = oob[good0] | oob[good1] << 8;
  134. /* parity check */
  135. if (hweight16(us) & BLOCK_UNMASK_COMPLEMENT)
  136. return -EINVAL;
  137. /* reserved */
  138. if (us == BLOCK_IS_RESERVED)
  139. return BLOCK_IS_RESERVED;
  140. return (us >> 1) & GENMASK(9, 0);
  141. }
  142. static int sharpsl_nand_init_ftl(struct mtd_info *mtd, struct sharpsl_ftl *ftl)
  143. {
  144. unsigned int block_num, phymax;
  145. int i, ret, log_num;
  146. loff_t block_adr;
  147. u8 *oob;
  148. oob = kzalloc(mtd->oobsize, GFP_KERNEL);
  149. if (!oob)
  150. return -ENOMEM;
  151. phymax = mtd_div_by_eb(SHARPSL_FTL_PART_SIZE, mtd);
  152. /* FTL reserves 5% of the blocks + 1 spare */
  153. ftl->logmax = ((phymax * 95) / 100) - 1;
  154. ftl->log2phy = kmalloc_array(ftl->logmax, sizeof(*ftl->log2phy),
  155. GFP_KERNEL);
  156. if (!ftl->log2phy) {
  157. ret = -ENOMEM;
  158. goto exit;
  159. }
  160. /* initialize ftl->log2phy */
  161. for (i = 0; i < ftl->logmax; i++)
  162. ftl->log2phy[i] = UINT_MAX;
  163. /* create physical-logical table */
  164. for (block_num = 0; block_num < phymax; block_num++) {
  165. block_adr = (loff_t)block_num * mtd->erasesize;
  166. if (mtd_block_isbad(mtd, block_adr))
  167. continue;
  168. if (sharpsl_nand_read_oob(mtd, block_adr, oob))
  169. continue;
  170. /* get logical block */
  171. log_num = sharpsl_nand_get_logical_num(oob);
  172. /* cut-off errors and skip the out-of-range values */
  173. if (log_num > 0 && log_num < ftl->logmax) {
  174. if (ftl->log2phy[log_num] == UINT_MAX)
  175. ftl->log2phy[log_num] = block_num;
  176. }
  177. }
  178. pr_info("Sharp SL FTL: %d blocks used (%d logical, %d reserved)\n",
  179. phymax, ftl->logmax, phymax - ftl->logmax);
  180. ret = 0;
  181. exit:
  182. kfree(oob);
  183. return ret;
  184. }
  185. static void sharpsl_nand_cleanup_ftl(struct sharpsl_ftl *ftl)
  186. {
  187. kfree(ftl->log2phy);
  188. }
  189. static int sharpsl_nand_read_laddr(struct mtd_info *mtd,
  190. loff_t from,
  191. size_t len,
  192. void *buf,
  193. struct sharpsl_ftl *ftl)
  194. {
  195. unsigned int log_num, final_log_num;
  196. unsigned int block_num;
  197. loff_t block_adr;
  198. loff_t block_ofs;
  199. size_t retlen;
  200. int err;
  201. log_num = mtd_div_by_eb((u32)from, mtd);
  202. final_log_num = mtd_div_by_eb(((u32)from + len - 1), mtd);
  203. if (len <= 0 || log_num >= ftl->logmax || final_log_num > log_num)
  204. return -EINVAL;
  205. block_num = ftl->log2phy[log_num];
  206. block_adr = (loff_t)block_num * mtd->erasesize;
  207. block_ofs = mtd_mod_by_eb((u32)from, mtd);
  208. err = mtd_read(mtd, block_adr + block_ofs, len, &retlen, buf);
  209. /* Ignore corrected ECC errors */
  210. if (mtd_is_bitflip(err))
  211. err = 0;
  212. if (!err && retlen != len)
  213. err = -EIO;
  214. if (err)
  215. pr_err("sharpslpart: error, read failed at %#llx\n",
  216. block_adr + block_ofs);
  217. return err;
  218. }
  219. /*
  220. * MTD Partition Parser
  221. *
  222. * Sample values read from SL-C860
  223. *
  224. * # cat /proc/mtd
  225. * dev: size erasesize name
  226. * mtd0: 006d0000 00020000 "Filesystem"
  227. * mtd1: 00700000 00004000 "smf"
  228. * mtd2: 03500000 00004000 "root"
  229. * mtd3: 04400000 00004000 "home"
  230. *
  231. * PARTITIONINFO1
  232. * 0x00060000: 00 00 00 00 00 00 70 00 42 4f 4f 54 00 00 00 00 ......p.BOOT....
  233. * 0x00060010: 00 00 70 00 00 00 c0 03 46 53 52 4f 00 00 00 00 ..p.....FSRO....
  234. * 0x00060020: 00 00 c0 03 00 00 00 04 46 53 52 57 00 00 00 00 ........FSRW....
  235. */
  236. struct sharpsl_nand_partinfo {
  237. __le32 start;
  238. __le32 end;
  239. __be32 magic;
  240. u32 reserved;
  241. };
  242. static int sharpsl_nand_read_partinfo(struct mtd_info *master,
  243. loff_t from,
  244. size_t len,
  245. struct sharpsl_nand_partinfo *buf,
  246. struct sharpsl_ftl *ftl)
  247. {
  248. int ret;
  249. ret = sharpsl_nand_read_laddr(master, from, len, buf, ftl);
  250. if (ret)
  251. return ret;
  252. /* check for magics */
  253. if (be32_to_cpu(buf[0].magic) != BOOT_MAGIC ||
  254. be32_to_cpu(buf[1].magic) != FSRO_MAGIC ||
  255. be32_to_cpu(buf[2].magic) != FSRW_MAGIC) {
  256. pr_err("sharpslpart: magic values mismatch\n");
  257. return -EINVAL;
  258. }
  259. /* fixup for hardcoded value 64 MiB (for older models) */
  260. buf[2].end = cpu_to_le32(master->size);
  261. /* extra sanity check */
  262. if (le32_to_cpu(buf[0].end) <= le32_to_cpu(buf[0].start) ||
  263. le32_to_cpu(buf[1].start) < le32_to_cpu(buf[0].end) ||
  264. le32_to_cpu(buf[1].end) <= le32_to_cpu(buf[1].start) ||
  265. le32_to_cpu(buf[2].start) < le32_to_cpu(buf[1].end) ||
  266. le32_to_cpu(buf[2].end) <= le32_to_cpu(buf[2].start)) {
  267. pr_err("sharpslpart: partition sizes mismatch\n");
  268. return -EINVAL;
  269. }
  270. return 0;
  271. }
  272. static int sharpsl_parse_mtd_partitions(struct mtd_info *master,
  273. const struct mtd_partition **pparts,
  274. struct mtd_part_parser_data *data)
  275. {
  276. struct sharpsl_ftl ftl;
  277. struct sharpsl_nand_partinfo buf[SHARPSL_NAND_PARTS];
  278. struct mtd_partition *sharpsl_nand_parts;
  279. int err;
  280. /* check that OOB bytes 8 to 15 used by the FTL are actually free */
  281. err = sharpsl_nand_check_ooblayout(master);
  282. if (err)
  283. return err;
  284. /* init logical mgmt (FTL) */
  285. err = sharpsl_nand_init_ftl(master, &ftl);
  286. if (err)
  287. return err;
  288. /* read and validate first partition table */
  289. pr_info("sharpslpart: try reading first partition table\n");
  290. err = sharpsl_nand_read_partinfo(master,
  291. SHARPSL_PARTINFO1_LADDR,
  292. sizeof(buf), buf, &ftl);
  293. if (err) {
  294. /* fallback: read second partition table */
  295. pr_warn("sharpslpart: first partition table is invalid, retry using the second\n");
  296. err = sharpsl_nand_read_partinfo(master,
  297. SHARPSL_PARTINFO2_LADDR,
  298. sizeof(buf), buf, &ftl);
  299. }
  300. /* cleanup logical mgmt (FTL) */
  301. sharpsl_nand_cleanup_ftl(&ftl);
  302. if (err) {
  303. pr_err("sharpslpart: both partition tables are invalid\n");
  304. return err;
  305. }
  306. sharpsl_nand_parts = kcalloc(SHARPSL_NAND_PARTS,
  307. sizeof(*sharpsl_nand_parts),
  308. GFP_KERNEL);
  309. if (!sharpsl_nand_parts)
  310. return -ENOMEM;
  311. /* original names */
  312. sharpsl_nand_parts[0].name = "smf";
  313. sharpsl_nand_parts[0].offset = le32_to_cpu(buf[0].start);
  314. sharpsl_nand_parts[0].size = le32_to_cpu(buf[0].end) -
  315. le32_to_cpu(buf[0].start);
  316. sharpsl_nand_parts[1].name = "root";
  317. sharpsl_nand_parts[1].offset = le32_to_cpu(buf[1].start);
  318. sharpsl_nand_parts[1].size = le32_to_cpu(buf[1].end) -
  319. le32_to_cpu(buf[1].start);
  320. sharpsl_nand_parts[2].name = "home";
  321. sharpsl_nand_parts[2].offset = le32_to_cpu(buf[2].start);
  322. sharpsl_nand_parts[2].size = le32_to_cpu(buf[2].end) -
  323. le32_to_cpu(buf[2].start);
  324. *pparts = sharpsl_nand_parts;
  325. return SHARPSL_NAND_PARTS;
  326. }
  327. static struct mtd_part_parser sharpsl_mtd_parser = {
  328. .parse_fn = sharpsl_parse_mtd_partitions,
  329. .name = "sharpslpart",
  330. };
  331. module_mtd_part_parser(sharpsl_mtd_parser);
  332. MODULE_LICENSE("GPL");
  333. MODULE_AUTHOR("Andrea Adami <andrea.adami@gmail.com>");
  334. MODULE_DESCRIPTION("MTD partitioning for NAND flash on Sharp SL Series");