前三个版本都不支持nandflash的读写,这次更新(ver2.2)添加了nandflash驱动及yaffs文件系统的烧写功能。在kasim的建议下我从ver2.2开始用git源代码仓库管理我的源码。并发布上一版本的补丁文件。
你可以点击下面的链接浏览u-boot for tiny210 ver2.2 源码:

Git source u-boot for tiny210 ver2.2

下面的提供了在CSDN资源库的下载链接:

ver2.2源码下载:  u-boot for tiny210 ver2.2

下面的提供了补丁包的下载链接:

ver2.2补丁下载: u-boot-for-tiny210-patch-ver2.2

下面的链接提供了前几次修改的源码:

ver1.0源码下载:u-boot for tiny210 ver1.0
ver2.0源码下载:u-boot for tiny210 ver2.0
ver2.1源码下载:u-boot for tiny210 ver2.1

你还可以参考下三篇blog从头构建自己的u-boot for tiny210

ver1.0   ver2.0  ver2.1

ver2.2的基本功能:

1. SD boot,基于linaro u-boot的SPL功能实现

2. 从SD卡的FAT分区上加载文件到SDRAM

3. 将环境变量保存至SD卡

4. 添加DM9000网卡驱动,开启网络功能(例如:tftp,nfs等)

5. 添加TAB键命令自动补全功能

6.修复bug:

修复bug 1:SD卡保存环境变量出现Writing to MMC(0)... mmc_send_cmd: error during transfer: 0x00208001 mmc write failed。

修复bug 2:每次启动只能保存一次环境变量。

+7.添加NandFlash驱动,开启所有Nand cmd。

+8.添加Yaffs文件系统烧写支持。

参照本文后面内容修改完后:

编译u-boot
$make ARCH=arm CROSS_COMPILE=/opt/FriendlyARM/toolschain/4.5.1/bin/arm-none-linux-gnueabi- tiny210_config
$make ARCH=arm CROSS_COMPILE=/opt/FriendlyARM/toolschain/4.5.1/bin/arm-none-linux-gnueabi- all spl
由于我的系统下装有两套交叉工具链,所以没有把/opt/FriendlyARM/toolschain/4.5.1/bin/ 添加到环境变量,在使用工具链时要指明路径。
将u-boot镜像写入SD卡
将SD卡通过读卡器接上电脑(或直接插入笔记本卡槽),通过"cat /proc/partitions"找出SD卡对应的设备,我的设备节点是/dev/sdb.

执行下面的命令
$sudo dd iflag=dsync oflag=dsync if=spl/tiny210-spl.bin of=/dev/sdb seek=1
$sudo dd iflag=dsync oflag=dsync if=u-boot.bin of=/dev/sdb  seek=49

 
 
将SD卡插入开发板启动:

启动:

部分NAND CMD测试:

下面简要介绍ver2.2的修改步骤:

左边的数字为旧行号,右边的数字为新行号,大家可以对应行号阅读修改部分的源码,或自己从ver2.1修改至ver2.2

1.tiny210-u-boot-version2.1/board/samsung/tiny210/Makefile 在此目录下修改Makefile

(4/0)
       
  31 31
  32 32 ifdef CONFIG_SPL_BUILD
  33 33 COBJS += mmc_boot.o
    34 #COBJS += nand.o
    35 #COBJS += nand_cp.o
  34 36 endif
    37 COBJS += nand.o
    38 COBJS += nand_cp.o
  35 39
  36 40 SOBJS := lowlevel_init.o mem_setup.o
  37 41
  17 int add_mtd_device(struct mtd_info *mtd)
 
 
2.  tiny210-u-boot-version2.1/drivers/mtd/nand/nand.c

修改此目录下的nand.c  (4 / 1)

       
  64 64 * Add MTD device so that we can reference it later
  65 65 * via the mtdcore infrastructure (e.g. ubi).
  66 66 */
  67   sprintf(dev_name[i], "nand%d", i);
    67 #if CONFIG_NAND_NO_USE_CHIP_NAME
    68 sprintf(dev_name[i], "nand%d", i);
  68 69 mtd->name = dev_name[i++];
    70 #endif
  69 71 add_mtd_device(mtd);
    72
  70 73 #endif
  71 74 } else
  72 75 mtd->name = NULL;
 
 
3.tiny210-u-boot-version2.1/include/configs/tiny210.h
修改此目录下的tiny210.h (33 /0)
       
  430 430 #define CONFIG_CMDLINE_EDITING
  431 431 #define CONFIG_AUTO_COMPLETE
  432 432 #define CONFIG_SYS_HUSH_PARSER
    433
    434 /*****************************Modified by lk for nand driver*************/
    435 #define CONFIG_CMD_NAND
    436 #if defined(CONFIG_CMD_NAND)
    437 #define CONFIG_CMD_NAND_YAFFS
    438 #define CONFIG_CMD_MTDPARTS
    439 #define CONFIG_SYS_MAX_NAND_DEVICE 1
    440 #define CONFIG_SYS_NAND_BASE (0xB0E000000)
    441 #define NAND_MAX_CHIPS 1
    442
    443 #define CONFIG_MTD_DEVICE /* needed for mtdparts commands add by lkmcu */
    444
    445 #define NAND_DISABLE_CE() (NFCONT_REG |= (1 << 1))
    446 #define NAND_ENABLE_CE() (NFCONT_REG &= ~(1 << 1))
    447 #define NF_TRANSRnB() do { while(!(NFSTAT_REG & (1 << 0))); } while(0)
    448 #define CONFIG_CMD_NAND_YAFFS_SKIPFB
    449
    450 #define CONFIG_NAND_USE_CHIP_NAME 1
    451
    452 #if 0
    453
    454 #define CONFIG_MTD_DEBUG
    455 #define CONFIG_MTD_DEBUG_VERBOSE
    456
    457 #define CFG_NAND_SKIP_BAD_DOT_I 1
    458 #define CFG_NAND_HWECC
    459
    460 #define CONFIG_NAND_BL1_8BIT_ECC
    461 #endif
    462 #undef CFG_NAND_FLASH_BBT
    463 #endif
    464
    465
  433 466 #endif /* __CONFIG_H */
 
 
4.tiny210-u-boot-version2.1/include/linux/mtd/mtd-abi.h
修改此目录下的mtd-abi.h(2 /0)
       
  126 126 uint32_t eccpos[128];
  127 127 uint32_t oobavail;
  128 128 struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
    129 uint32_t useecc;
    130 uint32_t reserved;
  129 131 };
  130 132
  131 133 /**
5.在tiny210-u-boot-version2.1/board/samsung/tiny210/ 目录下添加nand.c nand_cp.c(本版本未启用nand_cp.c文件)。nand.c文件内容如下:

[csharp]view plaincopyprint?
  1. #include <common.h>
  2. #if defined(CONFIG_CMD_NAND)
  3. #include <nand.h>
  4. #include <bedbug/regs.h>
  5. #include <s5pc110.h>
  6. #include <asm/io.h>
  7. #include <asm/errno.h>
  8. /* Nand flash definition values by jsgood */
  9. #define S3C_NAND_TYPE_UNKNOWN   0x0
  10. #define S3C_NAND_TYPE_SLC   0x1
  11. #define S3C_NAND_TYPE_MLC   0x2
  12. #undef  S3C_NAND_DEBUG
  13. /* Nand flash global values by jsgood */
  14. int cur_ecc_mode = 0;
  15. int nand_type = S3C_NAND_TYPE_UNKNOWN;
  16. /* Nand flash oob definition for SLC 512b page size by jsgood */
  17. static struct nand_ecclayout s3c_nand_oob_16 = {
  18. .useecc = MTD_NANDECC_AUTOPLACE,    /* Only for U-Boot */
  19. .eccbytes = 4,
  20. .eccpos = {1, 2, 3, 4},
  21. .oobfree = {
  22. {.offset = 6,
  23. . length = 10}}
  24. };
  25. /* Nand flash oob definition for SLC 2k page size by jsgood */
  26. static struct nand_ecclayout s3c_nand_oob_64 = {
  27. .useecc = MTD_NANDECC_AUTOPLACE,    /* Only for U-Boot */
  28. .eccbytes = 16,
  29. .eccpos = {40, 41, 42, 43, 44, 45, 46, 47,
  30. 48, 49, 50, 51, 52, 53, 54, 55},
  31. .oobfree = {
  32. {.offset = 2,
  33. .length = 38}}
  34. };
  35. /* Nand flash oob definition for MLC 2k page size by jsgood */
  36. static struct nand_ecclayout s3c_nand_oob_mlc_64 = {
  37. .useecc = MTD_NANDECC_AUTOPLACE,    /* Only for U-Boot */
  38. .eccbytes = 32,
  39. .eccpos = {
  40. 32, 33, 34, 35, 36, 37, 38, 39,
  41. 40, 41, 42, 43, 44, 45, 46, 47,
  42. 48, 49, 50, 51, 52, 53, 54, 55,
  43. 56, 57, 58, 59, 60, 61, 62, 63},
  44. .oobfree = {
  45. {.offset = 2,
  46. .length = 28}}
  47. };
  48. /* Nand flash oob definition for 4Kb page size with 8_bit ECC */
  49. static struct nand_ecclayout s3c_nand_oob_128 = {
  50. .useecc = MTD_NANDECC_AUTOPLACE,
  51. .eccbytes = 104,
  52. .eccpos = {
  53. 24, 25, 26, 27, 28, 29, 30, 31,
  54. 32, 33, 34, 35, 36, 37, 38, 39,
  55. 40, 41, 42, 43, 44, 45, 46, 47,
  56. 48, 49, 50, 51, 52, 53, 54, 55,
  57. 56, 57, 58, 59, 60, 61, 62, 63,
  58. 64, 65, 66, 67, 68, 69, 70, 71,
  59. 72, 73, 74, 75, 76, 77, 78, 79,
  60. 80, 81, 82, 83, 84, 85, 86, 87,
  61. 88, 89, 90, 91, 92, 93, 94, 95,
  62. 96, 97, 98, 99, 100, 101, 102, 103,
  63. 104, 105, 106, 107, 108, 109, 110, 111,
  64. 112, 113, 114, 115, 116, 117, 118, 119,
  65. 120, 121, 122, 123, 124, 125, 126, 127},
  66. .oobfree = {
  67. {.offset = 2,
  68. .length = 22}}
  69. };
  70. #if defined(S3C_NAND_DEBUG)
  71. /*
  72. * Function to print out oob buffer for debugging
  73. * Written by jsgood
  74. */
  75. static void print_oob(const char *header, struct mtd_info *mtd)
  76. {
  77. int i;
  78. struct nand_chip *chip = mtd->priv;
  79. printk("%s:\t", header);
  80. for(i = 0; i < 64; i++)
  81. printk("%02x ", chip->oob_poi[i]);
  82. printk("\n");
  83. }
  84. #endif
  85. /*
  86. * Hardware specific access to control-lines function
  87. * Written by jsgood
  88. */
  89. static void s3c_nand_hwcontrol(struct mtd_info *mtd, int dat, unsigned int ctrl)
  90. {
  91. unsigned int cur;
  92. #if 1
  93. if (ctrl & NAND_CTRL_CHANGE) {
  94. if (ctrl & NAND_NCE) {
  95. if (dat != NAND_CMD_NONE) {
  96. cur = readl(NFCONT);
  97. /* Forced Enable CS */
  98. cur &= ~NFCONT_CS;
  99. writel(cur, NFCONT);
  100. }
  101. } else {
  102. cur = readl(NFCONT);
  103. /* Forced Enable CS */
  104. cur |= NFCONT_CS;
  105. writel(cur, NFCONT);
  106. }
  107. }
  108. if (dat != NAND_CMD_NONE) {
  109. if (ctrl & NAND_CLE)
  110. writeb(dat, NFCMMD);
  111. else if (ctrl & NAND_ALE)
  112. writeb(dat, NFADDR);
  113. }
  114. #endif
  115. }
  116. /*
  117. * Function for checking device ready pin
  118. * Written by jsgood
  119. */
  120. static int s3c_nand_device_ready(struct mtd_info *mtdinfo)
  121. {
  122. while (!(readl(NFSTAT) & NFSTAT_RnB)) {}
  123. return 1;
  124. }
  125. /*
  126. * We don't use bad block table
  127. */
  128. static int s3c_nand_scan_bbt(struct mtd_info *mtdinfo)
  129. {
  130. return nand_default_bbt(mtdinfo);
  131. }
  132. #if defined(CFG_NAND_HWECC)
  133. /*
  134. * Function for checking ECCEncDone in NFSTAT
  135. * Written by jsgood
  136. */
  137. static void s3c_nand_wait_enc(void)
  138. {
  139. while (!(readl(NFECCSTAT) & NFSTAT_ECCENCDONE)) {}
  140. }
  141. /*
  142. * Function for checking ECCDecDone in NFSTAT
  143. * Written by jsgood
  144. */
  145. static void s3c_nand_wait_dec(void)
  146. {
  147. while (!(readl(NFECCSTAT) & NFSTAT_ECCDECDONE)) {}
  148. }
  149. /*
  150. * Function for checking ECC Busy
  151. * Written by jsgood
  152. */
  153. static void s3c_nand_wait_ecc_busy(void)
  154. {
  155. while (readl(NFECCSTAT) & NFESTAT0_ECCBUSY) {}
  156. }
  157. /*
  158. * This function is called before encoding ecc codes to ready ecc engine.
  159. * Written by jsgood
  160. */
  161. static void s3c_nand_enable_hwecc(struct mtd_info *mtd, int mode)
  162. {
  163. u_long nfcont, nfconf;
  164. cur_ecc_mode = mode;
  165. nfconf = readl(NFCONF);
  166. if (nand_type == S3C_NAND_TYPE_SLC)
  167. nfconf &= ~NFCONF_ECC_MLC;  /* SLC */
  168. else
  169. nfconf |= NFCONF_ECC_MLC;   /* MLC */
  170. writel(nfconf, NFCONF);
  171. printf("NFCONF = %x\n",nfconf);
  172. /* Initialize & unlock */
  173. nfcont = readl(NFCONT);
  174. nfcont |= NFCONT_INITMECC;
  175. nfcont &= ~NFCONT_MECCLOCK;
  176. if (nand_type == S3C_NAND_TYPE_MLC) {
  177. if (mode == NAND_ECC_WRITE)
  178. nfcont |= NFCONT_ECC_ENC;
  179. else if (mode == NAND_ECC_READ)
  180. nfcont &= ~NFCONT_ECC_ENC;
  181. }
  182. writel(nfcont, NFCONT);
  183. }
  184. /*
  185. * This function is called immediately after encoding ecc codes.
  186. * This function returns encoded ecc codes.
  187. * Written by jsgood
  188. */
  189. static int s3c_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
  190. {
  191. u_long nfcont, nfmecc0, nfmecc1;
  192. /* Lock */
  193. nfcont = readl(NFCONT);
  194. nfcont |= NFCONT_MECCLOCK;
  195. writel(nfcont, NFCONT);
  196. if (nand_type == S3C_NAND_TYPE_SLC) {
  197. nfmecc0 = readl(NFMECC0);
  198. ecc_code[0] = nfmecc0 & 0xff;
  199. ecc_code[1] = (nfmecc0 >> 8) & 0xff;
  200. ecc_code[2] = (nfmecc0 >> 16) & 0xff;
  201. ecc_code[3] = (nfmecc0 >> 24) & 0xff;
  202. } else {
  203. if (cur_ecc_mode == NAND_ECC_READ)
  204. s3c_nand_wait_dec();
  205. else {
  206. s3c_nand_wait_enc();
  207. nfmecc0 = readl(NFMECC0);
  208. nfmecc1 = readl(NFMECC1);
  209. ecc_code[0] = nfmecc0 & 0xff;
  210. ecc_code[1] = (nfmecc0 >> 8) & 0xff;
  211. ecc_code[2] = (nfmecc0 >> 16) & 0xff;
  212. ecc_code[3] = (nfmecc0 >> 24) & 0xff;
  213. ecc_code[4] = nfmecc1 & 0xff;
  214. ecc_code[5] = (nfmecc1 >> 8) & 0xff;
  215. ecc_code[6] = (nfmecc1 >> 16) & 0xff;
  216. ecc_code[7] = (nfmecc1 >> 24) & 0xff;
  217. }
  218. }
  219. return 0;
  220. }
  221. /*
  222. * This function determines whether read data is good or not.
  223. * If SLC, must write ecc codes to controller before reading status bit.
  224. * If MLC, status bit is already set, so only reading is needed.
  225. * If status bit is good, return 0.
  226. * If correctable errors occured, do that.
  227. * If uncorrectable errors occured, return -1.
  228. * Written by jsgood
  229. */
  230. static int s3c_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
  231. {
  232. int ret = -1;
  233. u_long nfestat0, nfestat1, nfmeccdata0, nfmeccdata1, nfmlcbitpt;
  234. u_char err_type;
  235. if (nand_type == S3C_NAND_TYPE_SLC) {
  236. /* SLC: Write ecc to compare */
  237. nfmeccdata0 = (read_ecc[1] << 16) | read_ecc[0];
  238. nfmeccdata1 = (read_ecc[3] << 16) | read_ecc[2];
  239. writel(nfmeccdata0, NFMECCDATA0);
  240. writel(nfmeccdata1, NFMECCDATA1);
  241. /* Read ecc status */
  242. nfestat0 = readl(NFESTAT0);
  243. err_type = nfestat0 & 0x3;
  244. switch (err_type) {
  245. case 0: /* No error */
  246. ret = 0;
  247. break;
  248. case 1: /* 1 bit error (Correctable)
  249. (nfestat0 >> 7) & 0x7ff    :error byte number
  250. (nfestat0 >> 4) & 0x7  :error bit number */
  251. printk("s3c-nand: 1 bit error detected at byte %ld, correcting from "
  252. "0x%02x ", (nfestat0 >> 7) & 0x7ff, dat[(nfestat0 >> 7) & 0x7ff]);
  253. dat[(nfestat0 >> 7) & 0x7ff] ^= (1 << ((nfestat0 >> 4) & 0x7));
  254. printk("to 0x%02x...OK\n", dat[(nfestat0 >> 7) & 0x7ff]);
  255. ret = 1;
  256. break;
  257. case 2: /* Multiple error */
  258. case 3: /* ECC area error */
  259. printk("s3c-nand: ECC uncorrectable error detected\n");
  260. ret = -1;
  261. break;
  262. }
  263. } else {
  264. /* MLC: */
  265. s3c_nand_wait_ecc_busy();
  266. nfestat0 = readl(NFESTAT0);
  267. nfestat1 = readl(NFESTAT1);
  268. nfmlcbitpt = readl(NFMLCBITPT);
  269. err_type = (nfestat0 >> 26) & 0x7;
  270. /* No error, If free page (all 0xff) */
  271. if ((nfestat0 >> 29) & 0x1) {
  272. err_type = 0;
  273. } else {
  274. /* No error, If all 0xff from 17th byte in oob (in case of JFFS2 format) */
  275. if (dat) {
  276. if (dat[17] == 0xff && dat[26] == 0xff && dat[35] == 0xff && dat[44] == 0xff && dat[54] == 0xff)
  277. err_type = 0;
  278. }
  279. }
  280. switch (err_type) {
  281. case 5: /* Uncorrectable */
  282. printk("s3c-nand: ECC uncorrectable error detected\n");
  283. ret = -1;
  284. break;
  285. case 4: /* 4 bit error (Correctable) */
  286. dat[(nfestat1 >> 16) & 0x3ff] ^= ((nfmlcbitpt >> 24) & 0xff);
  287. case 3: /* 3 bit error (Correctable) */
  288. dat[nfestat1 & 0x3ff] ^= ((nfmlcbitpt >> 16) & 0xff);
  289. case 2: /* 2 bit error (Correctable) */
  290. dat[(nfestat0 >> 16) & 0x3ff] ^= ((nfmlcbitpt >> 8) & 0xff);
  291. case 1: /* 1 bit error (Correctable) */
  292. printk("s3c-nand: %d bit(s) error detected, corrected successfully\n", err_type);
  293. dat[nfestat0 & 0x3ff] ^= (nfmlcbitpt & 0xff);
  294. ret = err_type;
  295. break;
  296. case 0: /* No error */
  297. ret = 0;
  298. break;
  299. }
  300. }
  301. return ret;
  302. }
  303. #if defined(CONFIG_NAND_BL1_8BIT_ECC) && defined(CONFIG_S5PC110)
  304. /***************************************************************
  305. * jsgood: Temporary 8 Bit H/W ECC supports for BL1 (6410/6430 only)
  306. ***************************************************************/
  307. static void s3c_nand_wait_ecc_busy_8bit(void)
  308. {
  309. while (readl(NFECCSTAT) & NFESTAT0_ECCBUSY) {
  310. }
  311. }
  312. void s3c_nand_enable_hwecc_8bit(struct mtd_info *mtd, int mode)
  313. {
  314. u_long nfreg;
  315. cur_ecc_mode = mode;
  316. if(cur_ecc_mode == NAND_ECC_WRITE){
  317. /* 8 bit selection */
  318. nfreg = readl(NFCONF);
  319. nfreg &= ~(0x3 << 23);
  320. nfreg |= (0x3<< 23);
  321. writel(nfreg, NFCONF);
  322. /* Set ECC type */
  323. nfreg = readl(NFECCCONF);
  324. nfreg &= 0xf;
  325. nfreg |= 0x3;
  326. writel(nfreg, NFECCCONF);
  327. /* set 8/12/16bit Ecc direction to Encoding */
  328. nfreg = readl(NFECCCONT);
  329. nfreg &= ~(0x1 << 16);
  330. nfreg |= (0x1 << 16);
  331. writel(nfreg, NFECCCONT);
  332. /* set 8/12/16bit ECC message length  to msg */
  333. nfreg = readl(NFECCCONF);
  334. nfreg &= ~((0x3ff<<16));
  335. nfreg |= (0x1ff << 16);
  336. writel(nfreg, NFECCCONF);
  337. /* write '1' to clear this bit. */
  338. /* clear illegal access status bit */
  339. nfreg = readl(NFSTAT);
  340. nfreg |= (0x1 << 4);
  341. nfreg |= (0x1 << 5);
  342. writel(nfreg, NFSTAT);
  343. /* clear 8/12/16bit ecc encode done */
  344. nfreg = readl(NFECCSTAT);
  345. nfreg |= (0x1 << 25);
  346. writel(nfreg, NFECCSTAT);
  347. nfreg = readl(NFCONT);
  348. nfreg &= ~(0x1 << 1);
  349. writel(nfreg, NFCONT);
  350. /* Initialize & unlock */
  351. nfreg = readl(NFCONT);
  352. nfreg &= ~NFCONT_MECCLOCK;
  353. nfreg |= NFCONT_INITECC;
  354. writel(nfreg, NFCONT);
  355. /* Reset ECC value. */
  356. nfreg = readl(NFECCCONT);
  357. nfreg |= (0x1 << 2);
  358. writel(nfreg, NFECCCONT);
  359. }else{
  360. /* set 8/12/16bit ECC message length  to msg */
  361. nfreg = readl(NFECCCONF);
  362. nfreg &= ~((0x3ff<<16));
  363. nfreg |= (0x1ff << 16);
  364. writel(nfreg, NFECCCONF);
  365. /* set 8/12/16bit Ecc direction to Decoding */
  366. nfreg = readl(NFECCCONT);
  367. nfreg &= ~(0x1 << 16);
  368. writel(nfreg, NFECCCONT);
  369. /* write '1' to clear this bit. */
  370. /* clear illegal access status bit */
  371. nfreg = readl(NFSTAT);
  372. nfreg |= (0x1 << 4);
  373. nfreg |= (0x1 << 5);
  374. writel(nfreg, NFSTAT);
  375. /* Lock */
  376. nfreg = readl(NFCONT);
  377. nfreg |= NFCONT_MECCLOCK;
  378. writel(nfreg, NFCONT);
  379. nfreg = readl(NFCONT);
  380. nfreg &= ~(0x1 << 1);
  381. writel(nfreg, NFCONT);
  382. /* clear 8/12/16bit ecc decode done */
  383. nfreg = readl(NFECCSTAT);
  384. nfreg |= (0x1 << 24);
  385. writel(nfreg, NFECCSTAT);
  386. /* Initialize & lock */
  387. nfreg = readl(NFCONT);
  388. nfreg &= ~NFCONT_MECCLOCK;
  389. nfreg |= NFCONT_MECCLOCK;
  390. writel(nfreg, NFCONT);
  391. /* write '1' to clear this bit. */
  392. nfreg = readl(NFSTAT);
  393. nfreg &= ~(1<<4);
  394. nfreg |= (1<<4);
  395. writel(nfreg, NFSTAT);
  396. while(!(nfreg &(1<<4))){
  397. nfreg = readl(NFSTAT);
  398. }
  399. /* write '1' to clear this bit. */
  400. nfreg = readl(NFSTAT);
  401. nfreg &= ~(1<<4);
  402. nfreg |= (1<<4);
  403. writel(nfreg, NFSTAT);
  404. /* Initialize & unlock */
  405. nfreg = readl(NFCONT);
  406. nfreg &= ~NFCONT_MECCLOCK;
  407. nfreg |= NFCONT_INITECC;
  408. writel(nfreg, NFCONT);
  409. /* Reset ECC value. */
  410. nfreg = readl(NFECCCONT);
  411. nfreg |= (0x1 << 2);
  412. writel(nfreg, NFECCCONT);
  413. }
  414. }
  415. int s3c_nand_calculate_ecc_8bit(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
  416. {
  417. u_long nfcont, nfeccprgecc0, nfeccprgecc1, nfeccprgecc2, nfeccprgecc3;
  418. if (cur_ecc_mode == NAND_ECC_READ) {
  419. /* Lock */
  420. nfcont = readl(NFCONT);
  421. nfcont |= NFCONT_MECCLOCK;
  422. writel(nfcont, NFCONT);
  423. s3c_nand_wait_dec();
  424. /* clear 8/12/16bit ecc decode done */
  425. nfcont = readl(NFECCSTAT);
  426. nfcont |= (1<<24);
  427. writel(nfcont, NFECCSTAT);
  428. s3c_nand_wait_ecc_busy_8bit();
  429. if(readl(NFSTAT)&(1<<5))
  430. {
  431. /* clear illegal access status bit */
  432. nfcont = readl(NFSTAT);
  433. nfcont |= (1<<5);
  434. writel(nfcont, NFSTAT);
  435. printf("\n Accessed locked area!! \n");
  436. nfcont = readl(NFCONT);
  437. nfcont |= (1<<1);
  438. writel(nfcont, NFCONT);
  439. return -1;
  440. }
  441. nfcont = readl(NFCONT);
  442. nfcont |= (1<<1);
  443. writel(nfcont, NFCONT);
  444. } else {
  445. /* Lock */
  446. nfcont = readl(NFCONT);
  447. nfcont |= NFCONT_MECCLOCK;
  448. writel(nfcont, NFCONT);
  449. s3c_nand_wait_enc();
  450. /* clear 8/12/16bit ecc encode done */
  451. nfcont = readl(NFECCSTAT);
  452. nfcont |= (1<<25);
  453. writel(nfcont, NFECCSTAT);
  454. nfeccprgecc0 = readl(NFECCPRGECC0);
  455. nfeccprgecc1 = readl(NFECCPRGECC1);
  456. nfeccprgecc2 = readl(NFECCPRGECC2);
  457. nfeccprgecc3 = readl(NFECCPRGECC3);
  458. ecc_code[0] = nfeccprgecc0 & 0xff;
  459. ecc_code[1] = (nfeccprgecc0 >> 8) & 0xff;
  460. ecc_code[2] = (nfeccprgecc0 >> 16) & 0xff;
  461. ecc_code[3] = (nfeccprgecc0 >> 24) & 0xff;
  462. ecc_code[4] = nfeccprgecc1 & 0xff;
  463. ecc_code[5] = (nfeccprgecc1 >> 8) & 0xff;
  464. ecc_code[6] = (nfeccprgecc1 >> 16) & 0xff;
  465. ecc_code[7] = (nfeccprgecc1 >> 24) & 0xff;
  466. ecc_code[8] = nfeccprgecc2 & 0xff;
  467. ecc_code[9] = (nfeccprgecc2 >> 8) & 0xff;
  468. ecc_code[10] = (nfeccprgecc2 >> 16) & 0xff;
  469. ecc_code[11] = (nfeccprgecc2 >> 24) & 0xff;
  470. ecc_code[12] = nfeccprgecc3 & 0xff;
  471. }
  472. return 0;
  473. }
  474. int s3c_nand_correct_data_8bit(struct mtd_info *mtd, u_char *dat)
  475. {
  476. int ret = -1;
  477. u_long nf8eccerr0, nf8eccerr1, nf8eccerr2, nf8eccerr3, nf8eccerr4, nfmlc8bitpt0, nfmlc8bitpt1;
  478. u_char err_type;
  479. s3c_nand_wait_ecc_busy_8bit();
  480. nf8eccerr0 = readl(NFECCSECSTAT);
  481. nf8eccerr1 = readl(NFECCERL0);
  482. nf8eccerr2 = readl(NFECCERL1);
  483. nf8eccerr3 = readl(NFECCERL2);
  484. nf8eccerr4 = readl(NFECCERL3);
  485. nfmlc8bitpt0 = readl(NFECCERP0);
  486. nfmlc8bitpt1 = readl(NFECCERP1);
  487. err_type = (nf8eccerr0) & 0xf;
  488. /* No error, If free page (all 0xff) */
  489. if ((nf8eccerr0 >> 29) & 0x1)
  490. err_type = 0;
  491. switch (err_type) {
  492. case 9: /* Uncorrectable */
  493. printk("s3c-nand: ECC uncorrectable error detected\n");
  494. ret = -1;
  495. break;
  496. case 8: /* 8 bit error (Correctable) */
  497. dat[(nf8eccerr4 >> 16) & 0x3ff] ^= ((nfmlc8bitpt1 >> 24) & 0xff);
  498. case 7: /* 7 bit error (Correctable) */
  499. dat[(nf8eccerr4) & 0x3ff] ^= ((nfmlc8bitpt1 >> 16) & 0xff);
  500. case 6: /* 6 bit error (Correctable) */
  501. dat[(nf8eccerr3 >> 16) & 0x3ff] ^= ((nfmlc8bitpt1 >> 8) & 0xff);
  502. case 5: /* 5 bit error (Correctable) */
  503. dat[(nf8eccerr3) & 0x3ff] ^= ((nfmlc8bitpt1) & 0xff);
  504. case 4: /* 8 bit error (Correctable) */
  505. dat[(nf8eccerr2 >> 16) & 0x3ff] ^= ((nfmlc8bitpt0 >> 24) & 0xff);
  506. case 3: /* 7 bit error (Correctable) */
  507. dat[(nf8eccerr2) & 0x3ff] ^= ((nfmlc8bitpt0>> 16) & 0xff);
  508. case 2: /* 6 bit error (Correctable) */
  509. dat[(nf8eccerr1 >> 16) & 0x3ff] ^= ((nfmlc8bitpt0>> 8) & 0xff);
  510. case 1: /* 1 bit error (Correctable) */
  511. printk("s3c-nand: %d bit(s) error detected, corrected successfully\n", err_type);
  512. dat[(nf8eccerr1) & 0x3ff] ^= ((nfmlc8bitpt0) & 0xff);
  513. ret = err_type;
  514. break;
  515. case 0: /* No error */
  516. ret = 0;
  517. break;
  518. }
  519. return ret;
  520. }
  521. void s3c_nand_write_page_8bit(struct mtd_info *mtd, struct nand_chip *chip,
  522. const uint8_t *buf)
  523. {
  524. u_long nfreg;
  525. int i, eccsize = 512;
  526. int eccbytes = 13;
  527. int eccsteps = mtd->writesize / eccsize;
  528. int badoffs = mtd->writesize == 512 ? NAND_SMALL_BADBLOCK_POS : NAND_LARGE_BADBLOCK_POS;
  529. uint8_t *ecc_calc = chip->buffers->ecccalc;
  530. uint8_t *p = buf;
  531. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  532. s3c_nand_enable_hwecc_8bit(mtd, NAND_ECC_WRITE);
  533. chip->write_buf(mtd, p, eccsize);
  534. s3c_nand_calculate_ecc_8bit(mtd, p, &ecc_calc[i]);
  535. }
  536. chip->oob_poi[badoffs] = 0xff;
  537. for (i = 0; i <= eccbytes * (mtd->writesize / eccsize); i++) {
  538. #if defined(CONFIG_EVT1)
  539. chip->oob_poi[i+12] = ecc_calc[i];
  540. #else
  541. chip->oob_poi[i] = ecc_calc[i];
  542. #endif
  543. }
  544. chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
  545. }
  546. int s3c_nand_read_page_8bit(struct mtd_info *mtd, struct nand_chip *chip,
  547. uint8_t *buf)
  548. {
  549. u_long nfreg;
  550. int i, stat, eccsize = 512;
  551. int eccbytes = 13;
  552. int eccsteps = mtd->writesize / eccsize;
  553. int col = 0;
  554. uint8_t *p = buf;
  555. /* Step1: read whole oob */
  556. col = mtd->writesize;
  557. #if defined(CONFIG_EVT1)
  558. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col+12, -1);
  559. #else
  560. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);
  561. #endif
  562. chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
  563. col = 0;
  564. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  565. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);
  566. s3c_nand_enable_hwecc_8bit(mtd, NAND_ECC_READ);
  567. chip->read_buf(mtd, p, eccsize);
  568. chip->write_buf(mtd, chip->oob_poi + (((mtd->writesize / eccsize) - eccsteps) * eccbytes), eccbytes);
  569. s3c_nand_calculate_ecc_8bit(mtd, 0, 0);
  570. stat = s3c_nand_correct_data_8bit(mtd, p);
  571. if (stat == -1)
  572. mtd->ecc_stats.failed++;
  573. col = eccsize * ((mtd->writesize / eccsize) + 1 - eccsteps);
  574. }
  575. return 0;
  576. }
  577. int s3c_nand_read_oob_8bit(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd)
  578. {
  579. int eccbytes = chip->ecc.bytes;
  580. int secc_start = mtd->oobsize - eccbytes;
  581. if (sndcmd) {
  582. chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
  583. sndcmd = 0;
  584. }
  585. chip->read_buf(mtd, chip->oob_poi, 0); //secc_start);
  586. return sndcmd;
  587. }
  588. int s3c_nand_write_oob_8bit(struct mtd_info *mtd, struct nand_chip *chip, int page)
  589. {
  590. int status = 0;
  591. int eccbytes = chip->ecc.bytes;
  592. int secc_start = mtd->oobsize - eccbytes;
  593. chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
  594. /* spare area */
  595. chip->write_buf(mtd, chip->oob_poi, 0); //secc_start);
  596. /* Send command to program the OOB data */
  597. chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
  598. status = chip->waitfunc(mtd, chip);
  599. return status & NAND_STATUS_FAIL ? -EIO : 0;
  600. }
  601. /********************************************************/
  602. #endif
  603. static int s3c_nand_write_oob_1bit(struct mtd_info *mtd, struct nand_chip *chip,
  604. int page)
  605. {
  606. uint8_t *ecc_calc = chip->buffers->ecccalc;
  607. int status = 0;
  608. int eccbytes = chip->ecc.bytes;
  609. int secc_start = mtd->oobsize - eccbytes;
  610. int i;
  611. chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
  612. /* spare area */
  613. chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
  614. chip->write_buf(mtd, chip->oob_poi, secc_start);
  615. chip->ecc.calculate(mtd, 0, &ecc_calc[chip->ecc.total]);
  616. for (i = 0; i < eccbytes; i++)
  617. chip->oob_poi[secc_start + i] = ecc_calc[chip->ecc.total + i];
  618. chip->write_buf(mtd, chip->oob_poi + secc_start, eccbytes);
  619. /* Send command to program the OOB data */
  620. chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
  621. status = chip->waitfunc(mtd, chip);
  622. return status & NAND_STATUS_FAIL ? -EIO : 0;
  623. }
  624. static int s3c_nand_read_oob_1bit(struct mtd_info *mtd, struct nand_chip *chip,
  625. int page, int sndcmd)
  626. {
  627. uint8_t *ecc_calc = chip->buffers->ecccalc;
  628. int eccbytes = chip->ecc.bytes;
  629. int secc_start = mtd->oobsize - eccbytes;
  630. if (sndcmd) {
  631. chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
  632. sndcmd = 0;
  633. }
  634. chip->ecc.hwctl(mtd, NAND_ECC_READ);
  635. chip->read_buf(mtd, chip->oob_poi, secc_start);
  636. chip->ecc.calculate(mtd, 0, &ecc_calc[chip->ecc.total]);
  637. chip->read_buf(mtd, chip->oob_poi + secc_start, eccbytes);
  638. /* jffs2 special case */
  639. if (!(chip->oob_poi[2] == 0x85 && chip->oob_poi[3] == 0x19))
  640. chip->ecc.correct(mtd, chip->oob_poi, chip->oob_poi + secc_start, 0);
  641. return sndcmd;
  642. }
  643. static void s3c_nand_write_page_1bit(struct mtd_info *mtd, struct nand_chip *chip,
  644. const uint8_t *buf)
  645. {
  646. int i, eccsize = chip->ecc.size;
  647. int eccbytes = chip->ecc.bytes;
  648. int eccsteps = chip->ecc.steps;
  649. int secc_start = mtd->oobsize - eccbytes;
  650. uint8_t *ecc_calc = chip->buffers->ecccalc;
  651. const uint8_t *p = buf;
  652. uint32_t *eccpos = chip->ecc.layout->eccpos;
  653. /* main area */
  654. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  655. chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
  656. chip->write_buf(mtd, p, eccsize);
  657. chip->ecc.calculate(mtd, p, &ecc_calc[i]);
  658. }
  659. for (i = 0; i < chip->ecc.total; i++)
  660. chip->oob_poi[eccpos[i]] = ecc_calc[i];
  661. /* spare area */
  662. chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
  663. chip->write_buf(mtd, chip->oob_poi, secc_start);
  664. chip->ecc.calculate(mtd, p, &ecc_calc[chip->ecc.total]);
  665. for (i = 0; i < eccbytes; i++)
  666. chip->oob_poi[secc_start + i] = ecc_calc[chip->ecc.total + i];
  667. chip->write_buf(mtd, chip->oob_poi + secc_start, eccbytes);
  668. }
  669. static int s3c_nand_read_page_1bit(struct mtd_info *mtd, struct nand_chip *chip,
  670. uint8_t *buf)
  671. {
  672. int i, stat, eccsize = chip->ecc.size;
  673. int eccbytes = chip->ecc.bytes;
  674. int eccsteps = chip->ecc.steps;
  675. int secc_start = mtd->oobsize - eccbytes;
  676. int col = 0;
  677. uint8_t *p = buf;
  678. uint32_t *mecc_pos = chip->ecc.layout->eccpos;
  679. uint8_t *ecc_calc = chip->buffers->ecccalc;
  680. col = mtd->writesize;
  681. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);
  682. /* spare area */
  683. chip->ecc.hwctl(mtd, NAND_ECC_READ);
  684. chip->read_buf(mtd, chip->oob_poi, secc_start);
  685. chip->ecc.calculate(mtd, p, &ecc_calc[chip->ecc.total]);
  686. chip->read_buf(mtd, chip->oob_poi + secc_start, eccbytes);
  687. /* jffs2 special case */
  688. if (!(chip->oob_poi[2] == 0x85 && chip->oob_poi[3] == 0x19))
  689. chip->ecc.correct(mtd, chip->oob_poi, chip->oob_poi + secc_start, 0);
  690. col = 0;
  691. /* main area */
  692. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  693. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);
  694. chip->ecc.hwctl(mtd, NAND_ECC_READ);
  695. chip->read_buf(mtd, p, eccsize);
  696. chip->ecc.calculate(mtd, p, &ecc_calc[i]);
  697. stat = chip->ecc.correct(mtd, p, chip->oob_poi + mecc_pos[0] + ((chip->ecc.steps - eccsteps) * eccbytes), 0);
  698. if (stat == -1)
  699. mtd->ecc_stats.failed++;
  700. col = eccsize * (chip->ecc.steps + 1 - eccsteps);
  701. }
  702. return 0;
  703. }
  704. /*
  705. * Hardware specific page read function for MLC.
  706. * Written by jsgood
  707. */
  708. static int s3c_nand_read_page_4bit(struct mtd_info *mtd, struct nand_chip *chip,
  709. uint8_t *buf)
  710. {
  711. int i, stat, eccsize = chip->ecc.size;
  712. int eccbytes = chip->ecc.bytes;
  713. int eccsteps = chip->ecc.steps;
  714. int col = 0;
  715. uint8_t *p = buf;
  716. uint32_t *mecc_pos = chip->ecc.layout->eccpos;
  717. /* Step1: read whole oob */
  718. col = mtd->writesize;
  719. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);
  720. chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
  721. col = 0;
  722. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  723. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);
  724. chip->ecc.hwctl(mtd, NAND_ECC_READ);
  725. chip->read_buf(mtd, p, eccsize);
  726. chip->write_buf(mtd, chip->oob_poi + mecc_pos[0] + ((chip->ecc.steps - eccsteps) * eccbytes), eccbytes);
  727. chip->ecc.calculate(mtd, 0, 0);
  728. stat = chip->ecc.correct(mtd, p, 0, 0);
  729. if (stat == -1)
  730. mtd->ecc_stats.failed++;
  731. col = eccsize * (chip->ecc.steps + 1 - eccsteps);
  732. }
  733. return 0;
  734. }
  735. /*
  736. * Hardware specific page write function for MLC.
  737. * Written by jsgood
  738. */
  739. static void s3c_nand_write_page_4bit(struct mtd_info *mtd, struct nand_chip *chip,
  740. const uint8_t *buf)
  741. {
  742. int i, eccsize = chip->ecc.size;
  743. int eccbytes = chip->ecc.bytes;
  744. int eccsteps = chip->ecc.steps;
  745. const uint8_t *p = buf;
  746. uint8_t *ecc_calc = chip->buffers->ecccalc;
  747. uint32_t *mecc_pos = chip->ecc.layout->eccpos;
  748. /* Step1: write main data and encode mecc */
  749. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  750. chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
  751. chip->write_buf(mtd, p, eccsize);
  752. chip->ecc.calculate(mtd, p, &ecc_calc[i]);
  753. }
  754. /* Step2: save encoded mecc */
  755. for (i = 0; i < chip->ecc.total; i++)
  756. chip->oob_poi[mecc_pos[i]] = ecc_calc[i];
  757. chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
  758. }
  759. #endif
  760. /*
  761. * Board-specific NAND initialization. The following members of the
  762. * argument are board-specific (per include/linux/mtd/nand.h):
  763. * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
  764. * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
  765. * - hwcontrol: hardwarespecific function for accesing control-lines
  766. * - dev_ready: hardwarespecific function for  accesing device ready/busy line
  767. * - enable_hwecc?: function to enable (reset)  hardware ecc generator. Must
  768. *   only be provided if a hardware ECC is available
  769. * - eccmode: mode of ecc, see defines
  770. * - chip_delay: chip dependent delay for transfering data from array to
  771. *   read regs (tR)
  772. * - options: various chip options. They can partly be set to inform
  773. *   nand_scan about special functionality. See the defines for further
  774. *   explanation
  775. * Members with a "?" were not set in the merged testing-NAND branch,
  776. * so they are not set here either.
  777. */
  778. int board_nand_init(struct nand_chip *nand)
  779. {   unsigned int  cur;
  780. #if defined(CFG_NAND_HWECC)
  781. int i;
  782. u_char tmp;
  783. struct nand_flash_dev *type = NULL;
  784. #endif
  785. /*Modified by lk*/
  786. cur = MP01CON_REG;
  787. cur = (0x3<<12)|(0x3<<8)|(cur&(~(0xff<<8)));
  788. MP01CON_REG = cur;
  789. cur = MP03CON_REG;
  790. cur = (cur&(~(0xfff<<0)));
  791. cur = (cur&(~(0xf<<16)));
  792. cur |= (0x2<<16)|(0x2<<8)|(0x2<<4)|(0x2<<0);
  793. MP03CON_REG = cur;
  794. NFCONF_REG |= (7<<12)|(7<<8)|(7<<4)|(2<<23)|(1<<1);//NFCONF_VAL;
  795. NFCONT_REG |= (3<<4)|(1<<0);//NFCONT_VAL;
  796. NFCONT_REG              &= ~((0x1<<16)|(0x1<<6)|(0x1<<7));
  797. /*Modified by lk*/
  798. nand->IO_ADDR_R      = (void __iomem *)(NFDATA);
  799. nand->IO_ADDR_W      = (void __iomem *)(NFDATA);
  800. nand->cmd_ctrl       = s3c_nand_hwcontrol;
  801. nand->dev_ready      = s3c_nand_device_ready;
  802. nand->scan_bbt       = s3c_nand_scan_bbt;
  803. nand->options        = 0;
  804. #if defined(CFG_NAND_FLASH_BBT)
  805. nand->options        |= NAND_USE_FLASH_BBT;
  806. #else
  807. nand->options        |= NAND_SKIP_BBTSCAN;
  808. #endif
  809. #if defined(CFG_NAND_HWECC)
  810. nand->ecc.mode       = NAND_ECC_HW;
  811. nand->ecc.hwctl      = s3c_nand_enable_hwecc;
  812. nand->ecc.calculate  = s3c_nand_calculate_ecc;
  813. nand->ecc.correct    = s3c_nand_correct_data;
  814. s3c_nand_hwcontrol(0, NAND_CMD_READID, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
  815. s3c_nand_hwcontrol(0, 0x00, NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE);
  816. s3c_nand_hwcontrol(0, 0x00, NAND_NCE | NAND_ALE);
  817. s3c_nand_hwcontrol(0, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
  818. s3c_nand_device_ready(0);
  819. tmp = readb(nand->IO_ADDR_R); /* Maf. ID */
  820. tmp = readb(nand->IO_ADDR_R); /* Device ID */
  821. for (i = 0; nand_flash_ids[i].name != NULL; i++) {
  822. if (tmp == nand_flash_ids[i].id) {
  823. type = &nand_flash_ids[i];
  824. break;
  825. }
  826. }
  827. printf("id = %x\n",nand_flash_ids[i].id);
  828. nand->cellinfo = readb(nand->IO_ADDR_R);  /* 3rd byte */
  829. tmp = readb(nand->IO_ADDR_R);            /* 4th byte */
  830. if (!type->pagesize) {
  831. if (((nand->cellinfo >> 2) & 0x3) == 0) {
  832. nand_type = S3C_NAND_TYPE_SLC;
  833. nand->ecc.size = 512;
  834. nand->ecc.bytes  = 4;
  835. if ((1024 << (tmp & 0x3)) > 512) {
  836. nand->ecc.read_page = s3c_nand_read_page_1bit;
  837. nand->ecc.write_page = s3c_nand_write_page_1bit;
  838. nand->ecc.read_oob = s3c_nand_read_oob_1bit;
  839. nand->ecc.write_oob = s3c_nand_write_oob_1bit;
  840. nand->ecc.layout = &s3c_nand_oob_64;
  841. nand->ecc.hwctl = s3c_nand_enable_hwecc;
  842. nand->ecc.calculate = s3c_nand_calculate_ecc;
  843. nand->ecc.correct = s3c_nand_correct_data;
  844. nand->options |= NAND_NO_SUBPAGE_WRITE;
  845. } else {
  846. nand->ecc.layout = &s3c_nand_oob_16;
  847. }
  848. } else {
  849. nand_type = S3C_NAND_TYPE_MLC;
  850. nand->options |= NAND_NO_SUBPAGE_WRITE;  /* NOP = 1 if MLC */
  851. nand->ecc.read_page = s3c_nand_read_page_4bit;
  852. nand->ecc.write_page = s3c_nand_write_page_4bit;
  853. nand->ecc.size = 512;
  854. nand->ecc.bytes = 8; /* really 7 bytes */
  855. nand->ecc.layout = &s3c_nand_oob_mlc_64;
  856. }
  857. } else {
  858. nand_type = S3C_NAND_TYPE_SLC;
  859. nand->ecc.size = 512;
  860. nand->cellinfo = 0;
  861. nand->ecc.bytes = 4;
  862. nand->ecc.layout = &s3c_nand_oob_16;
  863. }
  864. #else
  865. nand->ecc.mode = NAND_ECC_SOFT;
  866. #endif
  867. return 0;
  868. }
  869. #endif /* (CONFIG_CMD_NAND) */
添加nand_cp.c
[csharp]view plaincopyprint?
  1. /*
  2. * $Id: nand_cp.c,v 1.1 2008/11/20 01:08:36 boyko Exp $
  3. *
  4. * (C) Copyright 2006 Samsung Electronics
  5. *
  6. * See file CREDITS for list of people who contributed to this
  7. * project.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22. * MA 02111-1307 USA
  23. */
  24. /*
  25. * You must make sure that all functions in this file are designed
  26. * to load only U-Boot image.
  27. *
  28. * So, DO NOT USE in common read.
  29. *
  30. * By scsuh.
  31. */
  32. #include <common.h>
  33. #ifdef CONFIG_S5PC11X
  34. #include <asm/io.h>
  35. #include <linux/mtd/nand.h>
  36. #include <regs.h>
  37. #define NAND_CONTROL_ENABLE()   (NFCONT_REG |= (1 << 0))
  38. /*
  39. * address format
  40. *              17 16         9 8            0
  41. * --------------------------------------------
  42. * | block(12bit) | page(5bit) | offset(9bit) |
  43. * --------------------------------------------
  44. */
  45. static int nandll_read_page (uchar *buf, ulong addr, int large_block)
  46. {
  47. int i;
  48. int page_size = 512;
  49. if (large_block)
  50. page_size = 2048;
  51. NAND_ENABLE_CE();
  52. NFCMD_REG = NAND_CMD_READ0;
  53. /* Write Address */
  54. NFADDR_REG = 0;
  55. if (large_block)
  56. NFADDR_REG = 0;
  57. NFADDR_REG = (addr) & 0xff;
  58. NFADDR_REG = (addr >> 8) & 0xff;
  59. NFADDR_REG = (addr >> 16) & 0xff;
  60. if (large_block)
  61. NFCMD_REG = NAND_CMD_READSTART;
  62. NF_TRANSRnB();
  63. /* for compatibility(2460). u32 cannot be used. by scsuh */
  64. for(i=0; i < page_size; i++) {
  65. *buf++ = NFDATA8_REG;
  66. }
  67. NAND_DISABLE_CE();
  68. return 0;
  69. }
  70. /*
  71. * Read data from NAND.
  72. */
  73. static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
  74. {
  75. uchar *buf = (uchar *)dst_addr;
  76. int i;
  77. uint page_shift = 9;
  78. if (large_block)
  79. page_shift = 11;
  80. /* Read pages */
  81. for (i = 0; i < (size>>page_shift); i++, buf+=(1<<page_shift)) {
  82. nandll_read_page(buf, i, large_block);
  83. }
  84. return 0;
  85. }
  86. int copy_uboot_to_ram (void)
  87. {
  88. int large_block = 0;
  89. int i;
  90. vu_char id;
  91. NAND_CONTROL_ENABLE();
  92. NAND_ENABLE_CE();
  93. NFCMD_REG = NAND_CMD_READID;
  94. NFADDR_REG =  0x00;
  95. /* wait for a while */
  96. for (i=0; i<200; i++);
  97. id = NFDATA8_REG;
  98. id = NFDATA8_REG;
  99. if (id > 0x80)
  100. large_block = 1;
  101. /* read NAND Block.
  102. * 128KB ->240KB because of U-Boot size increase. by scsuh
  103. * So, read 0x3c000 bytes not 0x20000(128KB).
  104. */
  105. return nandll_read_blocks(CFG_PHY_UBOOT_BASE, COPY_BL2_SIZE, large_block);
  106. }
  107. #endif

u-boot for tiny210 ver2.2(by liukun321咕唧咕唧)相关推荐

  1. u-boot for tiny210 ver1.0(by liukun321咕唧咕唧)

    新版本下载: 下面的链接提供了较新版本的源码 ver4.0源码下载:u-boot for tiny210 ver4.0 ver3.1源码下载: u-boot for tiny210 ver3.1 ve ...

  2. u-boot for tiny210 ver2.2.1(by liukun321咕唧咕唧)

    这次更新没有增加具体功能,只修复了小bug.另外用一定篇幅说明如何解决u-boot for tiny210 在启动友善提供的mini210 linux内核/android出现卡死在Uncompress ...

  3. u-boot for tiny210 ver3.1 (by liukun321咕唧咕唧)

    这次更新,实现了自动识别Nand或MMC/SD启动(环境变量统一存放于Nandflash中),统一SD及Nand启动模式的nandflash驱动均为8bit HW ECC校验,并调整部分源码文件的结构 ...

  4. u-boot for tiny210 version2.0(by liukun321咕唧咕唧)

    version2.0是根据我上一个版本的uboot修改而来的,可以下载源码u-boot for tiny210 version1 后参照下面的内容进行修改 . 也可以参照 version1 从头构建t ...

  5. S5PV210之UBOOT-2011.06启动过程解析-基于u-boot for tiny210 ver3.1 (by liukun321咕唧咕唧)

    //主题:S5PV210之UBOOT-2011.06启动过程解析 //作者:kevinjz2010@gmail.com //版权:kevinjz原创 //平台:S5PV210 ARMV7 TINY21 ...

  6. FT5X06 如何应用在10寸电容屏(linux-3.5电容屏驱动简析移植10寸电容屏驱动到Android4.2) (by liukun321咕唧咕唧)

    这是几个月以前的东西了,在彻底遗忘之前拿出来好好写写.做个笔记,也算是造福后来人了.在做这个项目之前,没有做过电容屏的驱动,印象中的电容触摸屏是不需要校正的.IC支持多大的屏就要配多大的屏.但是拿到需 ...

  7. 教你如何用路由器连接网页登陆式校园网(by liukun321 咕唧咕唧)

    在百度搜了相关内容不少,方法也五花八门,就是没找到能用的.还是自己来比较靠谱. 我用的是水星路由器,哪个牌子的路由器并不重要,反正配置界面大都类似.下面我就简单说一下配置步骤: 1.找到你路由其背面的 ...

  8. 解决无线网卡工作一段时间USB就自动断开连接(by liukun321咕唧咕唧)

    我用的TP-LINK TL-WN721N无线网卡 ,开发板和主机能互相ping通 但是有偶尔会有丢包. 无线网卡工作时会不定时的断开USB连接,然后立马有自己连上了, 信息如下: [root@Frie ...

  9. 移植TP-LINK TL-WN721N 驱动到micro2440(by liukun321咕唧咕唧)

    内核版本:linux-3.1.4 我先把 无线网卡(TP-LINK  TL-WN721N)插到了我的PC上 用 lsusb 命令打印无线网卡ID :Bus 001 Device 003: ID 148 ...

最新文章

  1. Python第二周 str的方法
  2. 智取风控特征—巧用PBOC落地额度模型
  3. 51nod 1092 回文字符串【LCS】
  4. 数据实验室:让您的数据获得真正的价值
  5. 基于内容的图像检索概述
  6. Hugging Face Course-Introduction学习小记 (part2)
  7. Windows各个系统勒索补丁下载地址
  8. 如何在EngineeringVillage(EI Compendex)检索中文期刊
  9. wmctf2022 两题PvsZ
  10. 一篇文章带你解决 Unable to infer base url. This is common when using dynamic servlet registra
  11. PHP 互亿无线语音通知
  12. ApacheCN 计算机视觉译文集 20210218 更新
  13. 【C语言】输入英文标题,统计大写字母、小写字母、数字和其他字符的个数。
  14. C++ 小帅真的饿了
  15. PID控制器中的常见问题
  16. 3d游戏建模基础教程:3D建模应用领域和四种常用建模方法
  17. 图像分割技术与MATLAB仿真剖析
  18. codeforces1166E. The LCMs Must be Large
  19. 经常掉头发吃什么好?吃什么食物可防脱发
  20. 高中单招计算机专业面试稿,2020高中单招面试自我介绍范文

热门文章

  1. 混沌交易策略(鳄鱼线)
  2. iOS百度地图SDK之实时绘制轨迹(后台仍执行)
  3. NCH PhotoPad Pro for Mac(轻量级照片编辑软件)
  4. ThankPHP5.0增加中英文转换(tp5语言翻译)
  5. EDG为何刷爆你的朋友圈?是什么让年轻人那么激动?作为程序员你关注了么?
  6. NSN HLR simulator for provisioning in expect
  7. WIN7系统安装及动态分区详解步骤
  8. 简易费诺算法的C语言实现
  9. JWT实战 Spring Security Oauth2整合JWT 整合SSO单点登录
  10. 看美剧学英语:《老友记》20句实用英语口语