]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/mtd/nand/rtc_from4.c
Merge git://oss.sgi.com:8090/xfs-2.6
[karo-tx-linux.git] / drivers / mtd / nand / rtc_from4.c
index 1887989fb885d18aa121172fef67fed7b8097beb..f8c49645324d7b5e458b08824beaabb535e42cd3 100644 (file)
@@ -142,8 +142,7 @@ static struct rs_control *rs_decoder;
 /*
  *      hardware specific Out Of Band information
  */
-static struct nand_oobinfo rtc_from4_nand_oobinfo = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout rtc_from4_nand_oobinfo = {
        .eccbytes = 32,
        .eccpos = {
                   0, 1, 2, 3, 4, 5, 6, 7,
@@ -208,32 +207,18 @@ static uint8_t revbits[256] = {
  * Address lines (A24-A22), so no action is required here.
  *
  */
-static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
+static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd,
+                               unsigned int ctrl)
 {
-       struct nand_chip *this = (struct nand_chip *)(mtd->priv);
+       struct nand_chip *chip = (mtd->priv);
 
-       switch (cmd) {
+       if (cmd == NAND_CMD_NONE)
+               return;
 
-       case NAND_CTL_SETCLE:
-               this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE);
-               break;
-       case NAND_CTL_CLRCLE:
-               this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE);
-               break;
-
-       case NAND_CTL_SETALE:
-               this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE);
-               break;
-       case NAND_CTL_CLRALE:
-               this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE);
-               break;
-
-       case NAND_CTL_SETNCE:
-               break;
-       case NAND_CTL_CLRNCE:
-               break;
-
-       }
+       if (ctrl & NAND_CLE)
+               writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_CLE);
+       else
+               writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_ALE);
 }
 
 /*
@@ -458,7 +443,8 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
  * note: see pages 34..37 of data sheet for details.
  *
  */
-static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page)
+static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
+                            int state, int status, int page)
 {
        int er_stat = 0;
        int rtn, retlen;
@@ -469,39 +455,50 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s
        this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
 
        if (state == FL_ERASING) {
+
                for (i = 0; i < 4; i++) {
-                       if (status & 1 << (i + 1)) {
-                               this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1);
-                               rtn = this->read_byte(mtd);
-                               this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
-                               if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
-                                       er_stat |= 1 << (i + 1);        /* err_ecc_not_avail */
-                               }
-                       }
+                       if (!(status & 1 << (i + 1)))
+                               continue;
+                       this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1),
+                                     -1, -1);
+                       rtn = this->read_byte(mtd);
+                       this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
+
+                       /* err_ecc_not_avail */
+                       if (!(rtn & ERR_STAT_ECC_AVAILABLE))
+                               er_stat |= 1 << (i + 1);
                }
+
        } else if (state == FL_WRITING) {
+
+               unsigned long corrected = mtd->ecc_stats.corrected;
+
                /* single bank write logic */
                this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1);
                rtn = this->read_byte(mtd);
                this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
+
                if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
-                       er_stat |= 1 << 1;      /* err_ecc_not_avail */
-               } else {
-                       len = mtd->oobblock;
-                       buf = kmalloc(len, GFP_KERNEL);
-                       if (!buf) {
-                               printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
-                               er_stat = 1;    /* if we can't check, assume failed */
-                       } else {
-                               /* recovery read */
-                               /* page read */
-                               rtn = nand_do_read_ecc(mtd, page, len, &retlen, buf, NULL, this->autooob, 1);
-                               if (rtn) {      /* if read failed or > 1-bit error corrected */
-                                       er_stat |= 1 << 1;      /* ECC read failed */
-                               }
-                               kfree(buf);
-                       }
+                       /* err_ecc_not_avail */
+                       er_stat |= 1 << 1;
+                       goto out;
                }
+
+               len = mtd->writesize;
+               buf = kmalloc(len, GFP_KERNEL);
+               if (!buf) {
+                       printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
+                       er_stat = 1;
+                       goto out;
+               }
+
+               /* recovery read */
+               rtn = nand_do_read(mtd, page, len, &retlen, buf);
+
+               /* if read failed or > 1-bit error corrected */
+               if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) {
+                       er_stat |= 1 << 1;
+               kfree(buf);
        }
 
        rtn = status;
@@ -516,7 +513,7 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s
 /*
  * Main initialization routine
  */
-int __init rtc_from4_init(void)
+static int __init rtc_from4_init(void)
 {
        struct nand_chip *this;
        unsigned short bcr1, bcr2, wcr2;
@@ -538,6 +535,7 @@ int __init rtc_from4_init(void)
 
        /* Link the private data with the MTD structure */
        rtc_from4_mtd->priv = this;
+       rtc_from4_mtd->owner = THIS_MODULE;
 
        /* set area 5 as PCMCIA mode to clear the spec of tDH(Data hold time;9ns min) */
        bcr1 = *SH77X9_BCR1 & ~0x0002;
@@ -558,7 +556,7 @@ int __init rtc_from4_init(void)
        this->IO_ADDR_R = rtc_from4_fio_base;
        this->IO_ADDR_W = rtc_from4_fio_base;
        /* Set address of hardware control function */
-       this->hwcontrol = rtc_from4_hwcontrol;
+       this->cmd_ctrl = rtc_from4_hwcontrol;
        /* Set address of chip select function */
        this->select_chip = rtc_from4_nand_select_chip;
        /* command delay time (in us) */
@@ -569,19 +567,20 @@ int __init rtc_from4_init(void)
 #ifdef RTC_FROM4_HWECC
        printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n");
 
-       this->eccmode = NAND_ECC_HW8_512;
-       this->options |= NAND_HWECC_SYNDROME;
+       this->ecc.mode = NAND_ECC_HW_SYNDROME;
+       this->ecc.size = 512;
+       this->ecc.bytes = 8;
        /* return the status of extra status and ECC checks */
        this->errstat = rtc_from4_errstat;
        /* set the nand_oobinfo to support FPGA H/W error detection */
-       this->autooob = &rtc_from4_nand_oobinfo;
-       this->enable_hwecc = rtc_from4_enable_hwecc;
-       this->calculate_ecc = rtc_from4_calculate_ecc;
-       this->correct_data = rtc_from4_correct_data;
+       this->ecc.layout = &rtc_from4_nand_oobinfo;
+       this->ecc.hwctl = rtc_from4_enable_hwecc;
+       this->ecc.calculate = rtc_from4_calculate_ecc;
+       this->ecc.correct = rtc_from4_correct_data;
 #else
        printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
 
-       this->eccmode = NAND_ECC_SOFT;
+       this->ecc.mode = NAND_ECC_SOFT;
 #endif
 
        /* set the bad block tables to support debugging */
@@ -636,7 +635,6 @@ module_init(rtc_from4_init);
 /*
  * Clean up routine
  */
-#ifdef MODULE
 static void __exit rtc_from4_cleanup(void)
 {
        /* Release resource, unregister partitions */
@@ -654,7 +652,6 @@ static void __exit rtc_from4_cleanup(void)
 }
 
 module_exit(rtc_from4_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("d.marlin <dmarlin@redhat.com");