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

前三个版本都不支持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)
    
 3131
 3232ifdef CONFIG_SPL_BUILD
 3333COBJS += mmc_boot.o
  34#COBJS += nand.o
  35#COBJS += nand_cp.o
 3436endif
  37COBJS += nand.o
  38COBJS += nand_cp.o
 3539
 3640SOBJS := lowlevel_init.o mem_setup.o
 3741
 17int add_mtd_device(struct mtd_info *mtd)
修改此目录下的nand.c  (4 / 1)
    
 6464* Add MTD device so that we can reference it later
 6565* via the mtdcore infrastructure (e.g. ubi).
 6666*/
 67 sprintf(dev_name[i], "nand%d", i);
  67#if CONFIG_NAND_NO_USE_CHIP_NAME
  68sprintf(dev_name[i], "nand%d", i);
 6869mtd->name = dev_name[i++];
  70#endif
 6971add_mtd_device(mtd);
  72
 7073#endif
 7174} else
 7275mtd->name = NULL;
 
 
修改此目录下的tiny210.h (33 /0)
    
 430430#define CONFIG_CMDLINE_EDITING
 431431#define CONFIG_AUTO_COMPLETE
 432432#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
 433466#endif /* __CONFIG_H */
 
 
修改此目录下的mtd-abi.h(2 /0)
    
 126126uint32_t eccpos[128];
 127127uint32_t oobavail;
 128128struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
  129uint32_t useecc;
  130uint32_t reserved;
 129131};
 130132
 131133/**
 
5.在 tiny210-u-boot-version2.1/board/samsung/tiny210/  目录下添加nand.c nand_cp.c(本版本未启用nand_cp.c文件)。nand.c文件内容如下:
[csharp]   view plain copy print ?
  1. #include <common.h>  
  2.  
  3. #if defined(CONFIG_CMD_NAND)  
  4. #include <nand.h>  
  5. #include <bedbug/regs.h>  
  6. #include <s5pc110.h>  
  7.  
  8. #include <asm/io.h>  
  9. #include <asm/errno.h>  
  10.   
  11. /* Nand flash definition values by jsgood */  
  12. #define S3C_NAND_TYPE_UNKNOWN   0x0  
  13. #define S3C_NAND_TYPE_SLC   0x1  
  14. #define S3C_NAND_TYPE_MLC   0x2  
  15. #undef  S3C_NAND_DEBUG  
  16.   
  17. /* Nand flash global values by jsgood */  
  18. int cur_ecc_mode = 0;  
  19. int nand_type = S3C_NAND_TYPE_UNKNOWN;  
  20.   
  21. /* Nand flash oob definition for SLC 512b page size by jsgood */  
  22. static struct nand_ecclayout s3c_nand_oob_16 = {  
  23.     .useecc = MTD_NANDECC_AUTOPLACE,    /* Only for U-Boot */  
  24.     .eccbytes = 4,  
  25.     .eccpos = {1, 2, 3, 4},  
  26.     .oobfree = {  
  27.         {.offset = 6,  
  28.          . length = 10}}  
  29. };  
  30.   
  31. /* Nand flash oob definition for SLC 2k page size by jsgood */  
  32. static struct nand_ecclayout s3c_nand_oob_64 = {  
  33.     .useecc = MTD_NANDECC_AUTOPLACE,    /* Only for U-Boot */  
  34.     .eccbytes = 16,  
  35.     .eccpos = {40, 41, 42, 43, 44, 45, 46, 47,  
  36.            48, 49, 50, 51, 52, 53, 54, 55},  
  37.     .oobfree = {  
  38.         {.offset = 2,  
  39.          .length = 38}}  
  40. };  
  41.    
  42. /* Nand flash oob definition for MLC 2k page size by jsgood */  
  43. static struct nand_ecclayout s3c_nand_oob_mlc_64 = {  
  44.     .useecc = MTD_NANDECC_AUTOPLACE,    /* Only for U-Boot */  
  45.     .eccbytes = 32,  
  46.     .eccpos = {  
  47.            32, 33, 34, 35, 36, 37, 38, 39,  
  48.            40, 41, 42, 43, 44, 45, 46, 47,  
  49.            48, 49, 50, 51, 52, 53, 54, 55,  
  50.            56, 57, 58, 59, 60, 61, 62, 63},  
  51.     .oobfree = {  
  52.         {.offset = 2,  
  53.          .length = 28}}  
  54. };  
  55.   
  56. /* Nand flash oob definition for 4Kb page size with 8_bit ECC */  
  57. static struct nand_ecclayout s3c_nand_oob_128 = {  
  58.         .useecc = MTD_NANDECC_AUTOPLACE,  
  59.         .eccbytes = 104,  
  60.         .eccpos = {  
  61.                    24, 25, 26, 27, 28, 29, 30, 31,  
  62.                    32, 33, 34, 35, 36, 37, 38, 39,  
  63.                    40, 41, 42, 43, 44, 45, 46, 47,  
  64.                    48, 49, 50, 51, 52, 53, 54, 55,  
  65.                    56, 57, 58, 59, 60, 61, 62, 63,  
  66.                    64, 65, 66, 67, 68, 69, 70, 71,  
  67.                    72, 73, 74, 75, 76, 77, 78, 79,  
  68.                    80, 81, 82, 83, 84, 85, 86, 87,  
  69.                    88, 89, 90, 91, 92, 93, 94, 95,  
  70.                    96, 97, 98, 99, 100, 101, 102, 103,  
  71.                    104, 105, 106, 107, 108, 109, 110, 111,  
  72.                    112, 113, 114, 115, 116, 117, 118, 119,  
  73.                    120, 121, 122, 123, 124, 125, 126, 127},  
  74.         .oobfree = {  
  75.                 {.offset = 2,  
  76.                  .length = 22}}  
  77. };  
  78. #if defined(S3C_NAND_DEBUG)  
  79. /* 
  80.  * Function to print out oob buffer for debugging 
  81.  * Written by jsgood 
  82.  */  
  83. static void print_oob(const char *header, struct mtd_info *mtd)  
  84. {  
  85.     int i;  
  86.     struct nand_chip *chip = mtd->priv;  
  87.   
  88.     printk("%s:\t", header);  
  89.   
  90.     for(i = 0; i < 64; i++)  
  91.         printk("%02x ", chip->oob_poi[i]);  
  92.   
  93.     printk("\n");  
  94. }  
  95. #endif  
  96.   
  97. /* 
  98.  * Hardware specific access to control-lines function 
  99.  * Written by jsgood 
  100.  */  
  101. static void s3c_nand_hwcontrol(struct mtd_info *mtd, int dat, unsigned int ctrl)  
  102. {  
  103.     unsigned int cur;  
  104.  
  105. #if 1  
  106.     if (ctrl & NAND_CTRL_CHANGE) {  
  107.         if (ctrl & NAND_NCE) {  
  108.             if (dat != NAND_CMD_NONE) {  
  109.                 cur = readl(NFCONT);  
  110.                 /* Forced Enable CS */  
  111.                 cur &= ~NFCONT_CS;  
  112.   
  113.                 writel(cur, NFCONT);  
  114.             }  
  115.         } else {  
  116.             cur = readl(NFCONT);  
  117.             /* Forced Enable CS */  
  118.             cur |= NFCONT_CS;  
  119.   
  120.             writel(cur, NFCONT);  
  121.         }  
  122.     }  
  123.   
  124.     if (dat != NAND_CMD_NONE) {  
  125.         if (ctrl & NAND_CLE)  
  126.             writeb(dat, NFCMMD);  
  127.         else if (ctrl & NAND_ALE)  
  128.             writeb(dat, NFADDR);  
  129.     }  
  130. #endif  
  131. }  
  132.   
  133. /* 
  134.  * Function for checking device ready pin 
  135.  * Written by jsgood 
  136.  */  
  137. static int s3c_nand_device_ready(struct mtd_info *mtdinfo)  
  138. {  
  139.     while (!(readl(NFSTAT) & NFSTAT_RnB)) {}  
  140.     return 1;  
  141. }  
  142.   
  143. /* 
  144.  * We don't use bad block table 
  145.  */  
  146. static int s3c_nand_scan_bbt(struct mtd_info *mtdinfo)  
  147. {  
  148.     return nand_default_bbt(mtdinfo);  
  149. }  
  150.  
  151. #if defined(CFG_NAND_HWECC)  
  152.   
  153. /* 
  154.  * Function for checking ECCEncDone in NFSTAT 
  155.  * Written by jsgood 
  156.  */  
  157. static void s3c_nand_wait_enc(void)  
  158. {  
  159.     while (!(readl(NFECCSTAT) & NFSTAT_ECCENCDONE)) {}  
  160. }  
  161.   
  162. /* 
  163.  * Function for checking ECCDecDone in NFSTAT 
  164.  * Written by jsgood 
  165.  */  
  166. static void s3c_nand_wait_dec(void)  
  167. {  
  168.     while (!(readl(NFECCSTAT) & NFSTAT_ECCDECDONE)) {}  
  169. }  
  170.   
  171. /* 
  172.  * Function for checking ECC Busy 
  173.  * Written by jsgood 
  174.  */  
  175. static void s3c_nand_wait_ecc_busy(void)  
  176. {  
  177.     while (readl(NFECCSTAT) & NFESTAT0_ECCBUSY) {}  
  178. }  
  179.   
  180. /* 
  181.  * This function is called before encoding ecc codes to ready ecc engine. 
  182.  * Written by jsgood 
  183.  */  
  184. static void s3c_nand_enable_hwecc(struct mtd_info *mtd, int mode)  
  185. {  
  186.     u_long nfcont, nfconf;  
  187.   
  188.     cur_ecc_mode = mode;  
  189.   
  190.     nfconf = readl(NFCONF);  
  191.   
  192.     if (nand_type == S3C_NAND_TYPE_SLC)  
  193.         nfconf &= ~NFCONF_ECC_MLC;  /* SLC */  
  194.     else  
  195.         nfconf |= NFCONF_ECC_MLC;   /* MLC */  
  196.   
  197.     writel(nfconf, NFCONF);  
  198.     printf("NFCONF = %x\n",nfconf);  
  199.     /* Initialize & unlock */  
  200.     nfcont = readl(NFCONT);  
  201.     nfcont |= NFCONT_INITMECC;  
  202.     nfcont &= ~NFCONT_MECCLOCK;  
  203.   
  204.     if (nand_type == S3C_NAND_TYPE_MLC) {  
  205.         if (mode == NAND_ECC_WRITE)  
  206.             nfcont |= NFCONT_ECC_ENC;  
  207.         else if (mode == NAND_ECC_READ)  
  208.             nfcont &= ~NFCONT_ECC_ENC;  
  209.     }  
  210.   
  211.     writel(nfcont, NFCONT);  
  212. }  
  213.   
  214. /* 
  215.  * This function is called immediately after encoding ecc codes. 
  216.  * This function returns encoded ecc codes. 
  217.  * Written by jsgood 
  218.  */  
  219. static int s3c_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)  
  220. {  
  221.     u_long nfcont, nfmecc0, nfmecc1;  
  222.   
  223.     /* Lock */  
  224.     nfcont = readl(NFCONT);  
  225.     nfcont |= NFCONT_MECCLOCK;  
  226.     writel(nfcont, NFCONT);  
  227.   
  228.     if (nand_type == S3C_NAND_TYPE_SLC) {  
  229.         nfmecc0 = readl(NFMECC0);  
  230.   
  231.         ecc_code[0] = nfmecc0 & 0xff;  
  232.         ecc_code[1] = (nfmecc0 >> 8) & 0xff;  
  233.         ecc_code[2] = (nfmecc0 >> 16) & 0xff;  
  234.         ecc_code[3] = (nfmecc0 >> 24) & 0xff;  
  235.     } else {  
  236.         if (cur_ecc_mode == NAND_ECC_READ)  
  237.             s3c_nand_wait_dec();  
  238.         else {  
  239.             s3c_nand_wait_enc();  
  240.   
  241.             nfmecc0 = readl(NFMECC0);  
  242.             nfmecc1 = readl(NFMECC1);  
  243.   
  244.             ecc_code[0] = nfmecc0 & 0xff;  
  245.             ecc_code[1] = (nfmecc0 >> 8) & 0xff;  
  246.             ecc_code[2] = (nfmecc0 >> 16) & 0xff;  
  247.             ecc_code[3] = (nfmecc0 >> 24) & 0xff;  
  248.             ecc_code[4] = nfmecc1 & 0xff;  
  249.             ecc_code[5] = (nfmecc1 >> 8) & 0xff;  
  250.             ecc_code[6] = (nfmecc1 >> 16) & 0xff;  
  251.             ecc_code[7] = (nfmecc1 >> 24) & 0xff;  
  252.         }  
  253.     }  
  254.   
  255.     return 0;  
  256. }  
  257.   
  258. /* 
  259.  * This function determines whether read data is good or not. 
  260.  * If SLC, must write ecc codes to controller before reading status bit. 
  261.  * If MLC, status bit is already set, so only reading is needed. 
  262.  * If status bit is good, return 0. 
  263.  * If correctable errors occured, do that. 
  264.  * If uncorrectable errors occured, return -1. 
  265.  * Written by jsgood 
  266.  */  
  267. static int s3c_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)  
  268. {  
  269.     int ret = -1;  
  270.     u_long nfestat0, nfestat1, nfmeccdata0, nfmeccdata1, nfmlcbitpt;  
  271.     u_char err_type;  
  272.   
  273.     if (nand_type == S3C_NAND_TYPE_SLC) {  
  274.         /* SLC: Write ecc to compare */  
  275.         nfmeccdata0 = (read_ecc[1] << 16) | read_ecc[0];  
  276.         nfmeccdata1 = (read_ecc[3] << 16) | read_ecc[2];  
  277.         writel(nfmeccdata0, NFMECCDATA0);  
  278.         writel(nfmeccdata1, NFMECCDATA1);  
  279.   
  280.         /* Read ecc status */  
  281.         nfestat0 = readl(NFESTAT0);  
  282.         err_type = nfestat0 & 0x3;  
  283.   
  284.         switch (err_type) {  
  285.         case 0: /* No error */  
  286.             ret = 0;  
  287.             break;  
  288.   
  289.         case 1: /* 1 bit error (Correctable) 
  290.                (nfestat0 >> 7) & 0x7ff    :error byte number 
  291.                (nfestat0 >> 4) & 0x7  :error bit number */  
  292.             printk("s3c-nand: 1 bit error detected at byte %ld, correcting from "  
  293.                     "0x%02x ", (nfestat0 >> 7) & 0x7ff, dat[(nfestat0 >> 7) & 0x7ff]);  
  294.             dat[(nfestat0 >> 7) & 0x7ff] ^= (1 << ((nfestat0 >> 4) & 0x7));  
  295.             printk("to 0x%02x...OK\n", dat[(nfestat0 >> 7) & 0x7ff]);  
  296.             ret = 1;  
  297.             break;  
  298.   
  299.         case 2: /* Multiple error */  
  300.         case 3: /* ECC area error */  
  301.             printk("s3c-nand: ECC uncorrectable error detected\n");  
  302.             ret = -1;  
  303.             break;  
  304.         }  
  305.     } else {  
  306.         /* MLC: */  
  307.         s3c_nand_wait_ecc_busy();  
  308.   
  309.         nfestat0 = readl(NFESTAT0);  
  310.         nfestat1 = readl(NFESTAT1);  
  311.         nfmlcbitpt = readl(NFMLCBITPT);  
  312.   
  313.         err_type = (nfestat0 >> 26) & 0x7;  
  314.   
  315.         /* No error, If free page (all 0xff) */  
  316.         if ((nfestat0 >> 29) & 0x1) {  
  317.             err_type = 0;  
  318.         } else {  
  319.             /* No error, If all 0xff from 17th byte in oob (in case of JFFS2 format) */  
  320.             if (dat) {  
  321.                 if (dat[17] == 0xff && dat[26] == 0xff && dat[35] == 0xff && dat[44] == 0xff && dat[54] == 0xff)  
  322.                     err_type = 0;  
  323.             }  
  324.         }  
  325.   
  326.         switch (err_type) {  
  327.         case 5: /* Uncorrectable */  
  328.             printk("s3c-nand: ECC uncorrectable error detected\n");  
  329.             ret = -1;  
  330.             break;  
  331.   
  332.         case 4: /* 4 bit error (Correctable) */  
  333.             dat[(nfestat1 >> 16) & 0x3ff] ^= ((nfmlcbitpt >> 24) & 0xff);  
  334.   
  335.         case 3: /* 3 bit error (Correctable) */  
  336.             dat[nfestat1 & 0x3ff] ^= ((nfmlcbitpt >> 16) & 0xff);  
  337.   
  338.         case 2: /* 2 bit error (Correctable) */  
  339.             dat[(nfestat0 >> 16) & 0x3ff] ^= ((nfmlcbitpt >> 8) & 0xff);  
  340.   
  341.         case 1: /* 1 bit error (Correctable) */  
  342.             printk("s3c-nand: %d bit(s) error detected, corrected successfully\n", err_type);  
  343.             dat[nfestat0 & 0x3ff] ^= (nfmlcbitpt & 0xff);  
  344.             ret = err_type;  
  345.             break;  
  346.   
  347.         case 0: /* No error */  
  348.             ret = 0;  
  349.             break;  
  350.         }  
  351.     }  
  352.   
  353.     return ret;  
  354. }  
  355.  
  356. #if defined(CONFIG_NAND_BL1_8BIT_ECC) && defined(CONFIG_S5PC110)  
  357. /*************************************************************** 
  358.  * jsgood: Temporary 8 Bit H/W ECC supports for BL1 (6410/6430 only) 
  359.  ***************************************************************/  
  360. static void s3c_nand_wait_ecc_busy_8bit(void)  
  361. {  
  362.     while (readl(NFECCSTAT) & NFESTAT0_ECCBUSY) {  
  363.     }  
  364. }  
  365.   
  366. void s3c_nand_enable_hwecc_8bit(struct mtd_info *mtd, int mode)  
  367. {  
  368.     u_long nfreg;  
  369.       
  370.     cur_ecc_mode = mode;  
  371.   
  372.     if(cur_ecc_mode == NAND_ECC_WRITE){  
  373.   
  374.     /* 8 bit selection */  
  375.     nfreg = readl(NFCONF);  
  376.     nfreg &= ~(0x3 << 23);  
  377.     nfreg |= (0x3<< 23);  
  378.     writel(nfreg, NFCONF);  
  379.       
  380.     /* Set ECC type */  
  381.     nfreg = readl(NFECCCONF);  
  382.     nfreg &= 0xf;  
  383.     nfreg |= 0x3;  
  384.     writel(nfreg, NFECCCONF);  
  385.   
  386.     /* set 8/12/16bit Ecc direction to Encoding */  
  387.     nfreg = readl(NFECCCONT);  
  388.     nfreg &= ~(0x1 << 16);  
  389.     nfreg |= (0x1 << 16);  
  390.     writel(nfreg, NFECCCONT);  
  391.   
  392.     /* set 8/12/16bit ECC message length  to msg */  
  393.     nfreg = readl(NFECCCONF);  
  394.     nfreg &= ~((0x3ff<<16));  
  395.     nfreg |= (0x1ff << 16);  
  396.     writel(nfreg, NFECCCONF);  
  397.   
  398.     /* write '1' to clear this bit. */  
  399.     /* clear illegal access status bit */  
  400.     nfreg = readl(NFSTAT);  
  401.     nfreg |= (0x1 << 4);  
  402.     nfreg |= (0x1 << 5);  
  403.     writel(nfreg, NFSTAT);  
  404.   
  405.     /* clear 8/12/16bit ecc encode done */  
  406.     nfreg = readl(NFECCSTAT);  
  407.     nfreg |= (0x1 << 25);  
  408.     writel(nfreg, NFECCSTAT);  
  409.   
  410.     nfreg = readl(NFCONT);  
  411.     nfreg &= ~(0x1 << 1);  
  412.     writel(nfreg, NFCONT);  
  413.       
  414.     /* Initialize & unlock */  
  415.     nfreg = readl(NFCONT);  
  416.     nfreg &= ~NFCONT_MECCLOCK;  
  417.     nfreg |= NFCONT_INITECC;      
  418.     writel(nfreg, NFCONT);  
  419.   
  420.     /* Reset ECC value. */  
  421.     nfreg = readl(NFECCCONT);  
  422.     nfreg |= (0x1 << 2);  
  423.     writel(nfreg, NFECCCONT);  
  424.       
  425.     }else{  
  426.   
  427.     /* set 8/12/16bit ECC message length  to msg */  
  428.     nfreg = readl(NFECCCONF);  
  429.     nfreg &= ~((0x3ff<<16));  
  430.     nfreg |= (0x1ff << 16);  
  431.     writel(nfreg, NFECCCONF);  
  432.       
  433.     /* set 8/12/16bit Ecc direction to Decoding */  
  434.     nfreg = readl(NFECCCONT);  
  435.     nfreg &= ~(0x1 << 16);  
  436.     writel(nfreg, NFECCCONT);  
  437.       
  438.     /* write '1' to clear this bit. */  
  439.     /* clear illegal access status bit */  
  440.     nfreg = readl(NFSTAT);  
  441.     nfreg |= (0x1 << 4);  
  442.     nfreg |= (0x1 << 5);  
  443.     writel(nfreg, NFSTAT);  
  444.   
  445.     /* Lock */  
  446.     nfreg = readl(NFCONT);  
  447.     nfreg |= NFCONT_MECCLOCK;  
  448.     writel(nfreg, NFCONT);  
  449.   
  450.     nfreg = readl(NFCONT);  
  451.     nfreg &= ~(0x1 << 1);  
  452.     writel(nfreg, NFCONT);  
  453.   
  454.     /* clear 8/12/16bit ecc decode done */  
  455.     nfreg = readl(NFECCSTAT);  
  456.     nfreg |= (0x1 << 24);  
  457.     writel(nfreg, NFECCSTAT);  
  458.       
  459.     /* Initialize & lock */  
  460.     nfreg = readl(NFCONT);  
  461.     nfreg &= ~NFCONT_MECCLOCK;  
  462.     nfreg |= NFCONT_MECCLOCK;  
  463.     writel(nfreg, NFCONT);  
  464.   
  465.     /* write '1' to clear this bit. */  
  466.     nfreg = readl(NFSTAT);  
  467.     nfreg &= ~(1<<4);  
  468.     nfreg |= (1<<4);  
  469.     writel(nfreg, NFSTAT);  
  470.   
  471.     while(!(nfreg &(1<<4))){  
  472.         nfreg = readl(NFSTAT);  
  473.         }  
  474.   
  475.     /* write '1' to clear this bit. */  
  476.     nfreg = readl(NFSTAT);  
  477.     nfreg &= ~(1<<4);  
  478.     nfreg |= (1<<4);  
  479.     writel(nfreg, NFSTAT);  
  480.       
  481.     /* Initialize & unlock */  
  482.     nfreg = readl(NFCONT);  
  483.     nfreg &= ~NFCONT_MECCLOCK;  
  484.     nfreg |= NFCONT_INITECC;      
  485.     writel(nfreg, NFCONT);  
  486.   
  487.     /* Reset ECC value. */  
  488.     nfreg = readl(NFECCCONT);  
  489.     nfreg |= (0x1 << 2);  
  490.     writel(nfreg, NFECCCONT);  
  491.     }  
  492.   
  493. }  
  494.   
  495. int s3c_nand_calculate_ecc_8bit(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)  
  496. {  
  497.     u_long nfcont, nfeccprgecc0, nfeccprgecc1, nfeccprgecc2, nfeccprgecc3;  
  498.   
  499.     if (cur_ecc_mode == NAND_ECC_READ) {  
  500.         /* Lock */  
  501.         nfcont = readl(NFCONT);  
  502.         nfcont |= NFCONT_MECCLOCK;  
  503.         writel(nfcont, NFCONT);  
  504.           
  505.         s3c_nand_wait_dec();  
  506.   
  507.         /* clear 8/12/16bit ecc decode done */  
  508.         nfcont = readl(NFECCSTAT);  
  509.         nfcont |= (1<<24);  
  510.         writel(nfcont, NFECCSTAT);  
  511.   
  512.         s3c_nand_wait_ecc_busy_8bit();  
  513.   
  514.         if(readl(NFSTAT)&(1<<5))  
  515.         {  
  516.             /* clear illegal access status bit */  
  517.             nfcont = readl(NFSTAT);  
  518.             nfcont |= (1<<5);  
  519.             writel(nfcont, NFSTAT);  
  520.   
  521.             printf("\n Accessed locked area!! \n");  
  522.               
  523.             nfcont = readl(NFCONT);  
  524.             nfcont |= (1<<1);  
  525.             writel(nfcont, NFCONT);  
  526.               
  527.             return -1;  
  528.         }  
  529.           
  530.         nfcont = readl(NFCONT);  
  531.         nfcont |= (1<<1);  
  532.         writel(nfcont, NFCONT);  
  533.   
  534.           
  535.     } else {  
  536.         /* Lock */  
  537.         nfcont = readl(NFCONT);  
  538.         nfcont |= NFCONT_MECCLOCK;  
  539.         writel(nfcont, NFCONT);  
  540.           
  541.         s3c_nand_wait_enc();  
  542.   
  543.         /* clear 8/12/16bit ecc encode done */  
  544.         nfcont = readl(NFECCSTAT);  
  545.         nfcont |= (1<<25);  
  546.         writel(nfcont, NFECCSTAT);  
  547.   
  548.         nfeccprgecc0 = readl(NFECCPRGECC0);  
  549.         nfeccprgecc1 = readl(NFECCPRGECC1);  
  550.         nfeccprgecc2 = readl(NFECCPRGECC2);  
  551.         nfeccprgecc3 = readl(NFECCPRGECC3);  
  552.       
  553.         ecc_code[0] = nfeccprgecc0 & 0xff;  
  554.         ecc_code[1] = (nfeccprgecc0 >> 8) & 0xff;  
  555.         ecc_code[2] = (nfeccprgecc0 >> 16) & 0xff;  
  556.         ecc_code[3] = (nfeccprgecc0 >> 24) & 0xff;  
  557.         ecc_code[4] = nfeccprgecc1 & 0xff;  
  558.         ecc_code[5] = (nfeccprgecc1 >> 8) & 0xff;  
  559.         ecc_code[6] = (nfeccprgecc1 >> 16) & 0xff;  
  560.         ecc_code[7] = (nfeccprgecc1 >> 24) & 0xff;  
  561.         ecc_code[8] = nfeccprgecc2 & 0xff;  
  562.         ecc_code[9] = (nfeccprgecc2 >> 8) & 0xff;  
  563.         ecc_code[10] = (nfeccprgecc2 >> 16) & 0xff;  
  564.         ecc_code[11] = (nfeccprgecc2 >> 24) & 0xff;  
  565.         ecc_code[12] = nfeccprgecc3 & 0xff;  
  566.   
  567.           
  568.   
  569.     }  
  570.   
  571.     return 0;  
  572. }  
  573.   
  574. int s3c_nand_correct_data_8bit(struct mtd_info *mtd, u_char *dat)  
  575. {  
  576.     int ret = -1;  
  577.     u_long nf8eccerr0, nf8eccerr1, nf8eccerr2, nf8eccerr3, nf8eccerr4, nfmlc8bitpt0, nfmlc8bitpt1;  
  578.     u_char err_type;  
  579.   
  580.     s3c_nand_wait_ecc_busy_8bit();  
  581.   
  582.     nf8eccerr0 = readl(NFECCSECSTAT);  
  583.     nf8eccerr1 = readl(NFECCERL0);  
  584.     nf8eccerr2 = readl(NFECCERL1);  
  585.     nf8eccerr3 = readl(NFECCERL2);  
  586.     nf8eccerr4 = readl(NFECCERL3);  
  587.     nfmlc8bitpt0 = readl(NFECCERP0);  
  588.     nfmlc8bitpt1 = readl(NFECCERP1);  
  589.   
  590.     err_type = (nf8eccerr0) & 0xf;  
  591.   
  592.     /* No error, If free page (all 0xff) */  
  593.     if ((nf8eccerr0 >> 29) & 0x1)  
  594.         err_type = 0;  
  595.   
  596.     switch (err_type) {  
  597.     case 9: /* Uncorrectable */  
  598.         printk("s3c-nand: ECC uncorrectable error detected\n");  
  599.         ret = -1;  
  600.         break;  
  601.   
  602.     case 8: /* 8 bit error (Correctable) */  
  603.         dat[(nf8eccerr4 >> 16) & 0x3ff] ^= ((nfmlc8bitpt1 >> 24) & 0xff);  
  604.   
  605.     case 7: /* 7 bit error (Correctable) */  
  606.         dat[(nf8eccerr4) & 0x3ff] ^= ((nfmlc8bitpt1 >> 16) & 0xff);  
  607.   
  608.     case 6: /* 6 bit error (Correctable) */  
  609.         dat[(nf8eccerr3 >> 16) & 0x3ff] ^= ((nfmlc8bitpt1 >> 8) & 0xff);  
  610.   
  611.     case 5: /* 5 bit error (Correctable) */  
  612.         dat[(nf8eccerr3) & 0x3ff] ^= ((nfmlc8bitpt1) & 0xff);  
  613.   
  614.     case 4: /* 8 bit error (Correctable) */  
  615.         dat[(nf8eccerr2 >> 16) & 0x3ff] ^= ((nfmlc8bitpt0 >> 24) & 0xff);  
  616.   
  617.     case 3: /* 7 bit error (Correctable) */  
  618.         dat[(nf8eccerr2) & 0x3ff] ^= ((nfmlc8bitpt0>> 16) & 0xff);  
  619.   
  620.     case 2: /* 6 bit error (Correctable) */  
  621.         dat[(nf8eccerr1 >> 16) & 0x3ff] ^= ((nfmlc8bitpt0>> 8) & 0xff);  
  622.   
  623.     case 1: /* 1 bit error (Correctable) */  
  624.         printk("s3c-nand: %d bit(s) error detected, corrected successfully\n", err_type);  
  625.         dat[(nf8eccerr1) & 0x3ff] ^= ((nfmlc8bitpt0) & 0xff);  
  626.         ret = err_type;  
  627.         break;  
  628.   
  629.     case 0: /* No error */  
  630.         ret = 0;  
  631.         break;  
  632.     }  
  633.   
  634.     return ret;  
  635. }  
  636.   
  637. void s3c_nand_write_page_8bit(struct mtd_info *mtd, struct nand_chip *chip,  
  638.                   const uint8_t *buf)  
  639. {     
  640.     u_long nfreg;  
  641.     int i, eccsize = 512;  
  642.     int eccbytes = 13;  
  643.     int eccsteps = mtd->writesize / eccsize;  
  644.     int badoffs = mtd->writesize == 512 ? NAND_SMALL_BADBLOCK_POS : NAND_LARGE_BADBLOCK_POS;  
  645.   
  646.     uint8_t *ecc_calc = chip->buffers->ecccalc;  
  647.     uint8_t *p = buf;  
  648.       
  649.     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {  
  650.         s3c_nand_enable_hwecc_8bit(mtd, NAND_ECC_WRITE);  
  651.         chip->write_buf(mtd, p, eccsize);  
  652.         s3c_nand_calculate_ecc_8bit(mtd, p, &ecc_calc[i]);  
  653.     }  
  654.   
  655.     chip->oob_poi[badoffs] = 0xff;  
  656.     for (i = 0; i <= eccbytes * (mtd->writesize / eccsize); i++) {  
  657. #if defined(CONFIG_EVT1)  
  658.         chip->oob_poi[i+12] = ecc_calc[i];  
  659. #else  
  660.         chip->oob_poi[i] = ecc_calc[i];  
  661. #endif  
  662.     }  
  663.   
  664.     chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);  
  665. }  
  666.   
  667. int s3c_nand_read_page_8bit(struct mtd_info *mtd, struct nand_chip *chip,  
  668.                 uint8_t *buf)  
  669. {  
  670.     u_long nfreg;  
  671.     int i, stat, eccsize = 512;  
  672.     int eccbytes = 13;  
  673.     int eccsteps = mtd->writesize / eccsize;  
  674.     int col = 0;  
  675.     uint8_t *p = buf;  
  676.       
  677.     /* Step1: read whole oob */  
  678.     col = mtd->writesize;  
  679. #if defined(CONFIG_EVT1)  
  680.     chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col+12, -1);  
  681. #else  
  682.     chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);  
  683. #endif  
  684.     chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);  
  685.   
  686.     col = 0;  
  687.   
  688.     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {  
  689.   
  690.         chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);  
  691.         s3c_nand_enable_hwecc_8bit(mtd, NAND_ECC_READ);  
  692.         chip->read_buf(mtd, p, eccsize);  
  693.         chip->write_buf(mtd, chip->oob_poi + (((mtd->writesize / eccsize) - eccsteps) * eccbytes), eccbytes);  
  694.         s3c_nand_calculate_ecc_8bit(mtd, 0, 0);  
  695.         stat = s3c_nand_correct_data_8bit(mtd, p);  
  696.   
  697.         if (stat == -1)  
  698.             mtd->ecc_stats.failed++;  
  699.   
  700.         col = eccsize * ((mtd->writesize / eccsize) + 1 - eccsteps);  
  701.     }  
  702.   
  703.     return 0;  
  704. }  
  705.   
  706. int s3c_nand_read_oob_8bit(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd)  
  707. {  
  708.         int eccbytes = chip->ecc.bytes;  
  709.         int secc_start = mtd->oobsize - eccbytes;  
  710.   
  711.         if (sndcmd) {  
  712.                 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);  
  713.                 sndcmd = 0;  
  714.         }  
  715.   
  716.         chip->read_buf(mtd, chip->oob_poi, 0); //secc_start);  
  717.         return sndcmd;  
  718. }  
  719.   
  720. int s3c_nand_write_oob_8bit(struct mtd_info *mtd, struct nand_chip *chip, int page)  
  721. {  
  722.         int status = 0;  
  723.         int eccbytes = chip->ecc.bytes;  
  724.         int secc_start = mtd->oobsize - eccbytes;  
  725.   
  726.         chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);  
  727.   
  728.         /* spare area */  
  729.         chip->write_buf(mtd, chip->oob_poi, 0); //secc_start);  
  730.   
  731.         /* Send command to program the OOB data */  
  732.         chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);  
  733.         status = chip->waitfunc(mtd, chip);  
  734.         return status & NAND_STATUS_FAIL ? -EIO : 0;  
  735. }  
  736.   
  737. /********************************************************/  
  738. #endif  
  739.   
  740. static int s3c_nand_write_oob_1bit(struct mtd_info *mtd, struct nand_chip *chip,  
  741.                   int page)  
  742. {  
  743.     uint8_t *ecc_calc = chip->buffers->ecccalc;  
  744.     int status = 0;  
  745.     int eccbytes = chip->ecc.bytes;  
  746.     int secc_start = mtd->oobsize - eccbytes;  
  747.     int i;  
  748.   
  749.     chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);  
  750.   
  751.     /* spare area */  
  752.     chip->ecc.hwctl(mtd, NAND_ECC_WRITE);  
  753.     chip->write_buf(mtd, chip->oob_poi, secc_start);  
  754.     chip->ecc.calculate(mtd, 0, &ecc_calc[chip->ecc.total]);  
  755.   
  756.     for (i = 0; i < eccbytes; i++)  
  757.         chip->oob_poi[secc_start + i] = ecc_calc[chip->ecc.total + i];  
  758.   
  759.     chip->write_buf(mtd, chip->oob_poi + secc_start, eccbytes);  
  760.   
  761.     /* Send command to program the OOB data */  
  762.     chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);  
  763.   
  764.     status = chip->waitfunc(mtd, chip);  
  765.   
  766.     return status & NAND_STATUS_FAIL ? -EIO : 0;  
  767. }  
  768.   
  769. static int s3c_nand_read_oob_1bit(struct mtd_info *mtd, struct nand_chip *chip,  
  770.                  int page, int sndcmd)  
  771. {  
  772.     uint8_t *ecc_calc = chip->buffers->ecccalc;  
  773.     int eccbytes = chip->ecc.bytes;  
  774.     int secc_start = mtd->oobsize - eccbytes;  
  775.   
  776.     if (sndcmd) {  
  777.         chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);  
  778.         sndcmd = 0;  
  779.     }  
  780.   
  781.     chip->ecc.hwctl(mtd, NAND_ECC_READ);  
  782.     chip->read_buf(mtd, chip->oob_poi, secc_start);  
  783.     chip->ecc.calculate(mtd, 0, &ecc_calc[chip->ecc.total]);  
  784.     chip->read_buf(mtd, chip->oob_poi + secc_start, eccbytes);  
  785.   
  786.     /* jffs2 special case */  
  787.     if (!(chip->oob_poi[2] == 0x85 && chip->oob_poi[3] == 0x19))  
  788.         chip->ecc.correct(mtd, chip->oob_poi, chip->oob_poi + secc_start, 0);  
  789.   
  790.     return sndcmd;  
  791. }  
  792.   
  793. static void s3c_nand_write_page_1bit(struct mtd_info *mtd, struct nand_chip *chip,  
  794.                   const uint8_t *buf)  
  795. {  
  796.     int i, eccsize = chip->ecc.size;  
  797.     int eccbytes = chip->ecc.bytes;  
  798.     int eccsteps = chip->ecc.steps;  
  799.     int secc_start = mtd->oobsize - eccbytes;  
  800.     uint8_t *ecc_calc = chip->buffers->ecccalc;  
  801.     const uint8_t *p = buf;  
  802.   
  803.     uint32_t *eccpos = chip->ecc.layout->eccpos;  
  804.   
  805.     /* main area */  
  806.     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {  
  807.         chip->ecc.hwctl(mtd, NAND_ECC_WRITE);  
  808.         chip->write_buf(mtd, p, eccsize);  
  809.         chip->ecc.calculate(mtd, p, &ecc_calc[i]);  
  810.     }  
  811.   
  812.     for (i = 0; i < chip->ecc.total; i++)  
  813.         chip->oob_poi[eccpos[i]] = ecc_calc[i];  
  814.   
  815.     /* spare area */  
  816.     chip->ecc.hwctl(mtd, NAND_ECC_WRITE);  
  817.     chip->write_buf(mtd, chip->oob_poi, secc_start);  
  818.     chip->ecc.calculate(mtd, p, &ecc_calc[chip->ecc.total]);  
  819.   
  820.     for (i = 0; i < eccbytes; i++)  
  821.         chip->oob_poi[secc_start + i] = ecc_calc[chip->ecc.total + i];  
  822.   
  823.     chip->write_buf(mtd, chip->oob_poi + secc_start, eccbytes);  
  824. }  
  825.   
  826. static int s3c_nand_read_page_1bit(struct mtd_info *mtd, struct nand_chip *chip,  
  827.                 uint8_t *buf)  
  828. {  
  829.     int i, stat, eccsize = chip->ecc.size;  
  830.     int eccbytes = chip->ecc.bytes;  
  831.     int eccsteps = chip->ecc.steps;  
  832.     int secc_start = mtd->oobsize - eccbytes;  
  833.     int col = 0;  
  834.     uint8_t *p = buf;  
  835.     uint32_t *mecc_pos = chip->ecc.layout->eccpos;  
  836.     uint8_t *ecc_calc = chip->buffers->ecccalc;  
  837.   
  838.     col = mtd->writesize;  
  839.     chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);  
  840.   
  841.     /* spare area */  
  842.     chip->ecc.hwctl(mtd, NAND_ECC_READ);  
  843.     chip->read_buf(mtd, chip->oob_poi, secc_start);  
  844.     chip->ecc.calculate(mtd, p, &ecc_calc[chip->ecc.total]);  
  845.     chip->read_buf(mtd, chip->oob_poi + secc_start, eccbytes);  
  846.   
  847.     /* jffs2 special case */  
  848.     if (!(chip->oob_poi[2] == 0x85 && chip->oob_poi[3] == 0x19))  
  849.         chip->ecc.correct(mtd, chip->oob_poi, chip->oob_poi + secc_start, 0);  
  850.   
  851.     col = 0;  
  852.   
  853.     /* main area */  
  854.     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {  
  855.         chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);  
  856.         chip->ecc.hwctl(mtd, NAND_ECC_READ);  
  857.         chip->read_buf(mtd, p, eccsize);  
  858.         chip->ecc.calculate(mtd, p, &ecc_calc[i]);  
  859.   
  860.         stat = chip->ecc.correct(mtd, p, chip->oob_poi + mecc_pos[0] + ((chip->ecc.steps - eccsteps) * eccbytes), 0);  
  861.         if (stat == -1)  
  862.             mtd->ecc_stats.failed++;  
  863.   
  864.         col = eccsize * (chip->ecc.steps + 1 - eccsteps);  
  865.     }  
  866.   
  867.     return 0;  
  868. }  
  869.   
  870. /* 
  871.  * Hardware specific page read function for MLC. 
  872.  * Written by jsgood 
  873.  */  
  874. static int s3c_nand_read_page_4bit(struct mtd_info *mtd, struct nand_chip *chip,  
  875.                 uint8_t *buf)  
  876. {  
  877.     int i, stat, eccsize = chip->ecc.size;  
  878.     int eccbytes = chip->ecc.bytes;  
  879.     int eccsteps = chip->ecc.steps;  
  880.     int col = 0;  
  881.     uint8_t *p = buf;  
  882.     uint32_t *mecc_pos = chip->ecc.layout->eccpos;  
  883.   
  884.     /* Step1: read whole oob */  
  885.     col = mtd->writesize;  
  886.     chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);  
  887.     chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);  
  888.   
  889.     col = 0;  
  890.     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {  
  891.         chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);  
  892.         chip->ecc.hwctl(mtd, NAND_ECC_READ);  
  893.         chip->read_buf(mtd, p, eccsize);  
  894.         chip->write_buf(mtd, chip->oob_poi + mecc_pos[0] + ((chip->ecc.steps - eccsteps) * eccbytes), eccbytes);  
  895.         chip->ecc.calculate(mtd, 0, 0);  
  896.         stat = chip->ecc.correct(mtd, p, 0, 0);  
  897.   
  898.         if (stat == -1)  
  899.             mtd->ecc_stats.failed++;  
  900.   
  901.         col = eccsize * (chip->ecc.steps + 1 - eccsteps);  
  902.     }  
  903.   
  904.     return 0;  
  905. }  
  906.   
  907. /* 
  908.  * Hardware specific page write function for MLC. 
  909.  * Written by jsgood 
  910.  */  
  911. static void s3c_nand_write_page_4bit(struct mtd_info *mtd, struct nand_chip *chip,  
  912.                   const uint8_t *buf)  
  913. {  
  914.     int i, eccsize = chip->ecc.size;  
  915.     int eccbytes = chip->ecc.bytes;  
  916.     int eccsteps = chip->ecc.steps;  
  917.     const uint8_t *p = buf;  
  918.     uint8_t *ecc_calc = chip->buffers->ecccalc;  
  919.     uint32_t *mecc_pos = chip->ecc.layout->eccpos;  
  920.   
  921.     /* Step1: write main data and encode mecc */  
  922.     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {  
  923.         chip->ecc.hwctl(mtd, NAND_ECC_WRITE);  
  924.         chip->write_buf(mtd, p, eccsize);  
  925.         chip->ecc.calculate(mtd, p, &ecc_calc[i]);  
  926.     }  
  927.   
  928.     /* Step2: save encoded mecc */  
  929.     for (i = 0; i < chip->ecc.total; i++)  
  930.         chip->oob_poi[mecc_pos[i]] = ecc_calc[i];  
  931.   
  932.     chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);  
  933. }  
  934. #endif  
  935.   
  936. /* 
  937.  * Board-specific NAND initialization. The following members of the 
  938.  * argument are board-specific (per include/linux/mtd/nand.h): 
  939.  * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device 
  940.  * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device 
  941.  * - hwcontrol: hardwarespecific function for accesing control-lines 
  942.  * - dev_ready: hardwarespecific function for  accesing device ready/busy line 
  943.  * - enable_hwecc?: function to enable (reset)  hardware ecc generator. Must 
  944.  *   only be provided if a hardware ECC is available 
  945.  * - eccmode: mode of ecc, see defines 
  946.  * - chip_delay: chip dependent delay for transfering data from array to 
  947.  *   read regs (tR) 
  948.  * - options: various chip options. They can partly be set to inform 
  949.  *   nand_scan about special functionality. See the defines for further 
  950.  *   explanation 
  951.  * Members with a "?" were not set in the merged testing-NAND branch, 
  952.  * so they are not set here either. 
  953.  */  
  954. int board_nand_init(struct nand_chip *nand)  
  955. {   unsigned int  cur;  
  956. #if defined(CFG_NAND_HWECC)  
  957.     int i;  
  958.     u_char tmp;  
  959.     struct nand_flash_dev *type = NULL;  
  960. #endif  
  961.     /*Modified by lk*/  
  962.         cur = MP01CON_REG;  
  963.     cur = (0x3<<12)|(0x3<<8)|(cur&(~(0xff<<8)));  
  964.       
  965.     MP01CON_REG = cur;   
  966.     cur = MP03CON_REG;  
  967.     cur = (cur&(~(0xfff<<0)));  
  968.     cur = (cur&(~(0xf<<16)));  
  969.     cur |= (0x2<<16)|(0x2<<8)|(0x2<<4)|(0x2<<0);  
  970.     MP03CON_REG = cur;   
  971.       
  972.     NFCONF_REG |= (7<<12)|(7<<8)|(7<<4)|(2<<23)|(1<<1);//NFCONF_VAL;  
  973.     NFCONT_REG |= (3<<4)|(1<<0);//NFCONT_VAL;  
  974.       
  975.   
  976.     NFCONT_REG              &= ~((0x1<<16)|(0x1<<6)|(0x1<<7));  
  977.     /*Modified by lk*/    
  978.   
  979.     nand->IO_ADDR_R      = (void __iomem *)(NFDATA);  
  980.     nand->IO_ADDR_W      = (void __iomem *)(NFDATA);  
  981.     nand->cmd_ctrl       = s3c_nand_hwcontrol;  
  982.     nand->dev_ready      = s3c_nand_device_ready;  
  983.     nand->scan_bbt       = s3c_nand_scan_bbt;  
  984.     nand->options        = 0;  
  985.  
  986. #if defined(CFG_NAND_FLASH_BBT)  
  987.         nand->options        |= NAND_USE_FLASH_BBT;  
  988. #else  
  989.         nand->options        |= NAND_SKIP_BBTSCAN;  
  990. #endif  
  991.  
  992. #if defined(CFG_NAND_HWECC)  
  993.     nand->ecc.mode       = NAND_ECC_HW;  
  994.     nand->ecc.hwctl      = s3c_nand_enable_hwecc;  
  995.     nand->ecc.calculate  = s3c_nand_calculate_ecc;  
  996.     nand->ecc.correct    = s3c_nand_correct_data;  
  997.   
  998.     s3c_nand_hwcontrol(0, NAND_CMD_READID, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);  
  999.     s3c_nand_hwcontrol(0, 0x00, NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE);  
  1000.     s3c_nand_hwcontrol(0, 0x00, NAND_NCE | NAND_ALE);  
  1001.     s3c_nand_hwcontrol(0, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);  
  1002.     s3c_nand_device_ready(0);  
  1003.   
  1004.     tmp = readb(nand->IO_ADDR_R); /* Maf. ID */  
  1005.     tmp = readb(nand->IO_ADDR_R); /* Device ID */  
  1006.   
  1007.     for (i = 0; nand_flash_ids[i].name != NULL; i++) {  
  1008.         if (tmp == nand_flash_ids[i].id) {  
  1009.             type = &nand_flash_ids[i];  
  1010.             break;  
  1011.         }  
  1012.     }  
  1013.     printf("id = %x\n",nand_flash_ids[i].id);  
  1014.   
  1015.     nand->cellinfo = readb(nand->IO_ADDR_R);  /* 3rd byte */  
  1016.     tmp = readb(nand->IO_ADDR_R);            /* 4th byte */  
  1017.   
  1018.     if (!type->pagesize) {  
  1019.         if (((nand->cellinfo >> 2) & 0x3) == 0) {  
  1020.             nand_type = S3C_NAND_TYPE_SLC;  
  1021.             nand->ecc.size = 512;  
  1022.             nand->ecc.bytes  = 4;  
  1023.   
  1024.             if ((1024 << (tmp & 0x3)) > 512) {  
  1025.                 nand->ecc.read_page = s3c_nand_read_page_1bit;  
  1026.                 nand->ecc.write_page = s3c_nand_write_page_1bit;  
  1027.                 nand->ecc.read_oob = s3c_nand_read_oob_1bit;  
  1028.                 nand->ecc.write_oob = s3c_nand_write_oob_1bit;  
  1029.                 nand->ecc.layout = &s3c_nand_oob_64;  
  1030.                 nand->ecc.hwctl = s3c_nand_enable_hwecc;  
  1031.                                 nand->ecc.calculate = s3c_nand_calculate_ecc;  
  1032.                                 nand->ecc.correct = s3c_nand_correct_data;  
  1033.                                 nand->options |= NAND_NO_SUBPAGE_WRITE;  
  1034.             } else {  
  1035.                 nand->ecc.layout = &s3c_nand_oob_16;  
  1036.             }  
  1037.         } else {  
  1038.             nand_type = S3C_NAND_TYPE_MLC;  
  1039.             nand->options |= NAND_NO_SUBPAGE_WRITE;  /* NOP = 1 if MLC */  
  1040.             nand->ecc.read_page = s3c_nand_read_page_4bit;  
  1041.             nand->ecc.write_page = s3c_nand_write_page_4bit;  
  1042.             nand->ecc.size = 512;  
  1043.             nand->ecc.bytes = 8; /* really 7 bytes */  
  1044.             nand->ecc.layout = &s3c_nand_oob_mlc_64;  
  1045.         }  
  1046.     } else {  
  1047.         nand_type = S3C_NAND_TYPE_SLC;  
  1048.         nand->ecc.size = 512;  
  1049.         nand->cellinfo = 0;  
  1050.         nand->ecc.bytes = 4;  
  1051.         nand->ecc.layout = &s3c_nand_oob_16;  
  1052.     }  
  1053. #else  
  1054.     nand->ecc.mode = NAND_ECC_SOFT;  
  1055. #endif  
  1056.     return 0;  
  1057. }  
  1058. #endif /* (CONFIG_CMD_NAND) */  

 
 
添加nand_cp.c
[csharp]   view plain copy print ?
  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. /* 
  26.  * You must make sure that all functions in this file are designed 
  27.  * to load only U-Boot image. 
  28.  * 
  29.  * So, DO NOT USE in common read. 
  30.  * 
  31.  * By scsuh. 
  32.  */  
  33.  
  34.  
  35. #include <common.h>  
  36.  
  37. #ifdef CONFIG_S5PC11X  
  38. #include <asm/io.h>  
  39. #include <linux/mtd/nand.h>  
  40. #include <regs.h>  
  41.  
  42. #define NAND_CONTROL_ENABLE()   (NFCONT_REG |= (1 << 0))  
  43.   
  44. /* 
  45.  * address format 
  46.  *              17 16         9 8            0 
  47.  * -------------------------------------------- 
  48.  * | block(12bit) | page(5bit) | offset(9bit) | 
  49.  * -------------------------------------------- 
  50.  */  
  51.   
  52. static int nandll_read_page (uchar *buf, ulong addr, int large_block)  
  53. {  
  54.         int i;  
  55.     int page_size = 512;  
  56.   
  57.     if (large_block)  
  58.         page_size = 2048;  
  59.   
  60.         NAND_ENABLE_CE();  
  61.   
  62.         NFCMD_REG = NAND_CMD_READ0;  
  63.   
  64.         /* Write Address */  
  65.         NFADDR_REG = 0;  
  66.   
  67.     if (large_block)  
  68.             NFADDR_REG = 0;  
  69.   
  70.     NFADDR_REG = (addr) & 0xff;  
  71.     NFADDR_REG = (addr >> 8) & 0xff;  
  72.     NFADDR_REG = (addr >> 16) & 0xff;  
  73.   
  74.     if (large_block)  
  75.         NFCMD_REG = NAND_CMD_READSTART;  
  76.   
  77.         NF_TRANSRnB();  
  78.   
  79.     /* for compatibility(2460). u32 cannot be used. by scsuh */  
  80.     for(i=0; i < page_size; i++) {  
  81.                 *buf++ = NFDATA8_REG;  
  82.         }  
  83.   
  84.         NAND_DISABLE_CE();  
  85.         return 0;  
  86. }  
  87.   
  88. /* 
  89.  * Read data from NAND. 
  90.  */  
  91. static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)  
  92. {  
  93.         uchar *buf = (uchar *)dst_addr;  
  94.         int i;  
  95.     uint page_shift = 9;  
  96.   
  97.     if (large_block)  
  98.         page_shift = 11;  
  99.   
  100.         /* Read pages */  
  101.         for (i = 0; i < (size>>page_shift); i++, buf+=(1<<page_shift)) {  
  102.                 nandll_read_page(buf, i, large_block);  
  103.         }  
  104.   
  105.         return 0;  
  106. }  
  107.   
  108. int copy_uboot_to_ram (void)  
  109. {  
  110.     int large_block = 0;  
  111.     int i;  
  112.     vu_char id;  
  113.   
  114.     NAND_CONTROL_ENABLE();  
  115.         NAND_ENABLE_CE();  
  116.         NFCMD_REG = NAND_CMD_READID;  
  117.         NFADDR_REG =  0x00;  
  118.   
  119.     /* wait for a while */  
  120.         for (i=0; i<200; i++);  
  121.     id = NFDATA8_REG;  
  122.     id = NFDATA8_REG;  
  123.   
  124.     if (id > 0x80)  
  125.         large_block = 1;  
  126.   
  127.     /* read NAND Block. 
  128.      * 128KB ->240KB because of U-Boot size increase. by scsuh 
  129.      * So, read 0x3c000 bytes not 0x20000(128KB). 
  130.      */  
  131.     return nandll_read_blocks(CFG_PHY_UBOOT_BASE, COPY_BL2_SIZE, large_block);  
  132. }  
  133.   
  134. #endif  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值