This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / mtd / nand / diskonchip.c
index f2116fa..0f7dedd 100644 (file)
@@ -8,22 +8,16 @@
  * Author: David Woodhouse <dwmw2@infradead.org>
  * Additional Diskonchip 2000 and Millennium support by Dan Brown <dan_brown@ieee.org>
  * Diskonchip Millennium Plus support by Kalev Lember <kalev@smartlink.ee>
- * 
- * Error correction code lifted from the old docecc code
- * Author: Fabrice Bellard (fabrice.bellard@netgem.com) 
- * Copyright (C) 2000 Netgem S.A.
- * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de>
- *  
+ *
  * Interface to generic NAND code for M-Systems DiskOnChip devices
  *
- * $Id: diskonchip.c,v 1.42 2004/11/16 18:29:03 dwmw2 Exp $
+ * $Id: diskonchip.c,v 1.34 2004/08/09 19:41:12 dbrown Exp $
  */
 
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
-#include <linux/rslib.h>
 #include <asm/io.h>
 
 #include <linux/mtd/mtd.h>
@@ -68,7 +62,7 @@ static unsigned long __initdata doc_locations[] = {
 static struct mtd_info *doclist = NULL;
 
 struct doc_priv {
-       void __iomem *virtadr;
+       unsigned long virtadr;
        unsigned long physadr;
        u_char ChipID;
        u_char CDSNControl;
@@ -102,136 +96,28 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd);
 static void doc200x_select_chip(struct mtd_info *mtd, int chip);
 
 static int debug=0;
-module_param(debug, int, 0);
+MODULE_PARM(debug, "i");
 
 static int try_dword=1;
-module_param(try_dword, int, 0);
+MODULE_PARM(try_dword, "i");
 
 static int no_ecc_failures=0;
-module_param(no_ecc_failures, int, 0);
+MODULE_PARM(no_ecc_failures, "i");
 
-#ifdef CONFIG_MTD_PARTITIONS
 static int no_autopart=0;
-module_param(no_autopart, int, 0);
-#endif
+MODULE_PARM(no_autopart, "i");
 
 #ifdef MTD_NAND_DISKONCHIP_BBTWRITE
 static int inftl_bbt_write=1;
 #else
 static int inftl_bbt_write=0;
 #endif
-module_param(inftl_bbt_write, int, 0);
+MODULE_PARM(inftl_bbt_write, "i");
 
 static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS;
-module_param(doc_config_location, ulong, 0);
+MODULE_PARM(doc_config_location, "l");
 MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
 
-
-/* Sector size for HW ECC */
-#define SECTOR_SIZE 512
-/* The sector bytes are packed into NB_DATA 10 bit words */
-#define NB_DATA (((SECTOR_SIZE + 1) * 8 + 6) / 10)
-/* Number of roots */
-#define NROOTS 4
-/* First consective root */
-#define FCR 510
-/* Number of symbols */
-#define NN 1023
-
-/* the Reed Solomon control structure */
-static struct rs_control *rs_decoder;
-
-/* 
- * The HW decoder in the DoC ASIC's provides us a error syndrome,
- * which we must convert to a standard syndrom usable by the generic
- * Reed-Solomon library code.
- *
- * Fabrice Bellard figured this out in the old docecc code. I added
- * some comments, improved a minor bit and converted it to make use
- * of the generic Reed-Solomon libary. tglx
- */
-static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
-{
-       int i, j, nerr, errpos[8];
-       uint8_t parity;
-       uint16_t ds[4], s[5], tmp, errval[8], syn[4];
-
-       /* Convert the ecc bytes into words */
-       ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8);
-       ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6);
-       ds[2] = ((ecc[2] & 0xf0) >> 4) | ((ecc[3] & 0x3f) << 4);
-       ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2);
-       parity = ecc[1];
-
-       /* Initialize the syndrom buffer */
-       for (i = 0; i < NROOTS; i++)
-               s[i] = ds[0];
-       /* 
-        *  Evaluate 
-        *  s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0]
-        *  where x = alpha^(FCR + i)
-        */
-       for(j = 1; j < NROOTS; j++) {
-               if(ds[j] == 0)
-                       continue;
-               tmp = rs->index_of[ds[j]];
-               for(i = 0; i < NROOTS; i++)
-                       s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)];
-       }
-
-       /* Calc s[i] = s[i] / alpha^(v + i) */
-       for (i = 0; i < NROOTS; i++) {
-               if (syn[i])
-                       syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
-       }
-       /* Call the decoder library */
-       nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval);
-
-       /* Incorrectable errors ? */
-       if (nerr < 0)
-               return nerr;
-
-       /* 
-        * Correct the errors. The bitpositions are a bit of magic,
-        * but they are given by the design of the de/encoder circuit
-        * in the DoC ASIC's.
-        */
-       for(i = 0;i < nerr; i++) {
-               int index, bitpos, pos = 1015 - errpos[i];
-               uint8_t val;
-               if (pos >= NB_DATA && pos < 1019)
-                       continue;
-               if (pos < NB_DATA) {
-                       /* extract bit position (MSB first) */
-                       pos = 10 * (NB_DATA - 1 - pos) - 6;
-                       /* now correct the following 10 bits. At most two bytes
-                          can be modified since pos is even */
-                       index = (pos >> 3) ^ 1;
-                       bitpos = pos & 7;
-                       if ((index >= 0 && index < SECTOR_SIZE) || 
-                           index == (SECTOR_SIZE + 1)) {
-                               val = (uint8_t) (errval[i] >> (2 + bitpos));
-                               parity ^= val;
-                               if (index < SECTOR_SIZE)
-                                       data[index] ^= val;
-                       }
-                       index = ((pos >> 3) + 1) ^ 1;
-                       bitpos = (bitpos + 10) & 7;
-                       if (bitpos == 0)
-                               bitpos = 8;
-                       if ((index >= 0 && index < SECTOR_SIZE) || 
-                           index == (SECTOR_SIZE + 1)) {
-                               val = (uint8_t)(errval[i] << (8 - bitpos));
-                               parity ^= val;
-                               if (index < SECTOR_SIZE)
-                                       data[index] ^= val;
-                       }
-               }
-       }
-       /* If the parity is wrong, no rescue possible */
-       return parity ? -1 : nerr;
-}
-
 static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
 {
        volatile char dummy;
@@ -253,7 +139,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
 /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
 static int _DoC_WaitReady(struct doc_priv *doc)
 {
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        unsigned long timeo = jiffies + (HZ * 10);
 
        if(debug) printk("_DoC_WaitReady...\n");
@@ -283,7 +169,7 @@ static int _DoC_WaitReady(struct doc_priv *doc)
 
 static inline int DoC_WaitReady(struct doc_priv *doc)
 {
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int ret = 0;
 
        if (DoC_is_MillenniumPlus(doc)) {
@@ -309,7 +195,7 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
 
        if(debug)printk("write_byte %02x\n", datum);
        WriteDOC(datum, docptr, CDSNSlowIO);
@@ -320,7 +206,7 @@ static u_char doc2000_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        u_char ret;
 
        ReadDOC(docptr, CDSNSlowIO);
@@ -335,7 +221,7 @@ static void doc2000_writebuf(struct mtd_info *mtd,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
        if (debug)printk("writebuf of %d bytes: ", len);
        for (i=0; i < len; i++) {
@@ -351,7 +237,7 @@ static void doc2000_readbuf(struct mtd_info *mtd,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
 
        if (debug)printk("readbuf of %d bytes: ", len);
@@ -366,7 +252,7 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
 
        if (debug) printk("readbuf_dword of %d bytes: ", len);
@@ -387,7 +273,7 @@ static int doc2000_verifybuf(struct mtd_info *mtd,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
 
        for (i=0; i < len; i++)
@@ -419,7 +305,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
                        uint32_t dword;
                        uint8_t byte[4];
                } ident;
-               void __iomem *docptr = doc->virtadr;
+               unsigned long docptr = doc->virtadr;
 
                doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
                doc2000_write_byte(mtd, NAND_CMD_READID);
@@ -478,7 +364,7 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
 
        WriteDOC(datum, docptr, CDSNSlowIO);
        WriteDOC(datum, docptr, Mil_CDSN_IO);
@@ -489,7 +375,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
 
        //ReadDOC(docptr, CDSNSlowIO);
        /* 11.4.5 -- delay twice to allow extended length cycle */
@@ -504,7 +390,7 @@ static void doc2001_writebuf(struct mtd_info *mtd,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
 
        for (i=0; i < len; i++)
@@ -518,7 +404,7 @@ static void doc2001_readbuf(struct mtd_info *mtd,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
 
        /* Start read pipeline */
@@ -536,7 +422,7 @@ static int doc2001_verifybuf(struct mtd_info *mtd,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
 
        /* Start read pipeline */
@@ -556,7 +442,7 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        u_char ret;
 
         ReadDOC(docptr, Mplus_ReadPipeInit);
@@ -571,7 +457,7 @@ static void doc2001plus_writebuf(struct mtd_info *mtd,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
 
        if (debug)printk("writebuf of %d bytes: ", len);
@@ -588,7 +474,7 @@ static void doc2001plus_readbuf(struct mtd_info *mtd,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
 
        if (debug)printk("readbuf of %d bytes: ", len);
@@ -618,7 +504,7 @@ static int doc2001plus_verifybuf(struct mtd_info *mtd,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
 
        if (debug)printk("verifybuf of %d bytes: ", len);
@@ -644,7 +530,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int floor = 0;
 
        if(debug)printk("select chip (%d)\n", chip);
@@ -670,7 +556,7 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int floor = 0;
 
        if(debug)printk("select chip (%d)\n", chip);
@@ -697,7 +583,7 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
 
        switch(cmd) {
        case NAND_CTL_SETNCE:
@@ -735,7 +621,7 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
 
        /*
         * Must terminate write pipeline before sending any commands
@@ -839,7 +725,7 @@ static int doc200x_dev_ready(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
 
        if (DoC_is_MillenniumPlus(doc)) {
                /* 11.4.2 -- must NOP four times before checking FR/B# */
@@ -877,7 +763,7 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
 
        /* Prime the ECC engine */
        switch(mode) {
@@ -896,7 +782,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
 
        /* Prime the ECC engine */
        switch(mode) {
@@ -917,7 +803,7 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        int i;
        int emptymatch = 1;
 
@@ -975,7 +861,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
        int i, ret = 0;
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = (void *)this->priv;
-        void __iomem *docptr = doc->virtadr;
+       unsigned long docptr = doc->virtadr;
        volatile u_char dummy;
        int emptymatch = 1;
        
@@ -1028,7 +914,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
                   erased block, in which case the ECC will not come out right.
                   We'll suppress the error and tell the caller everything's
                   OK.  Because it is. */
-               if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc);
+               if (!emptymatch) ret = doc_decode_ecc (dat, calc_ecc);
                if (ret > 0)
                        printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
        }       
@@ -1499,13 +1385,13 @@ static inline int __init doc_probe(unsigned long physadr)
        struct mtd_info *mtd;
        struct nand_chip *nand;
        struct doc_priv *doc;
-       void __iomem *virtadr;
+       unsigned long virtadr;
        unsigned char save_control;
        unsigned char tmp, tmpb, tmpc;
        int reg, len, numchips;
        int ret = 0;
 
-       virtadr = ioremap(physadr, DOC_IOREMAP_LEN);
+       virtadr = (unsigned long)ioremap(physadr, DOC_IOREMAP_LEN);
        if (!virtadr) {
                printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr);
                return -EIO;
@@ -1632,7 +1518,7 @@ static inline int __init doc_probe(unsigned long physadr)
              sizeof(struct nand_chip) +
              sizeof(struct doc_priv) +
              (2 * sizeof(struct nand_bbt_descr));
-       mtd =  kmalloc(len, GFP_KERNEL);
+       mtd = kmalloc(len, GFP_KERNEL);
        if (!mtd) {
                printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
                ret = -ENOMEM;
@@ -1657,7 +1543,7 @@ static inline int __init doc_probe(unsigned long physadr)
        nand->enable_hwecc      = doc200x_enable_hwecc;
        nand->calculate_ecc     = doc200x_calculate_ecc;
        nand->correct_data      = doc200x_correct_data;
-
+       //nand->data_buf
        nand->autooob           = &doc200x_oobinfo;
        nand->eccmode           = NAND_ECC_HW6_512;
        nand->options           = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME;
@@ -1703,47 +1589,13 @@ fail:
        return ret;
 }
 
-static void release_nanddoc(void)
-{
-       struct mtd_info *mtd, *nextmtd;
-       struct nand_chip *nand;
-       struct doc_priv *doc;
-
-       for (mtd = doclist; mtd; mtd = nextmtd) {
-               nand = mtd->priv;
-               doc = (void *)nand->priv;
-
-               nextmtd = doc->nextdoc;
-               nand_release(mtd);
-               iounmap((void *)doc->virtadr);
-               kfree(mtd);
-       }
-}
-
-static int __init init_nanddoc(void)
+int __init init_nanddoc(void)
 {
-       int i, ret = 0;
-
-       /* We could create the decoder on demand, if memory is a concern.
-        * This way we have it handy, if an error happens 
-        *
-        * Symbolsize is 10 (bits)
-        * Primitve polynomial is x^10+x^3+1
-        * first consecutive root is 510
-        * primitve element to generate roots = 1
-        * generator polinomial degree = 4
-        */
-       rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS);
-       if (!rs_decoder) {
-               printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n");
-               return -ENOMEM;
-       }
+       int i;
 
        if (doc_config_location) {
                printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location);
-               ret = doc_probe(doc_config_location);
-               if (ret < 0)
-                       goto outerr;
+               return doc_probe(doc_config_location);
        } else {
                for (i=0; (doc_locations[i] != 0xffffffff); i++) {
                        doc_probe(doc_locations[i]);
@@ -1753,23 +1605,25 @@ static int __init init_nanddoc(void)
           found, so the user knows we at least tried. */
        if (!doclist) {
                printk(KERN_INFO "No valid DiskOnChip devices found\n");
-               ret = -ENODEV;
-               goto outerr;
+               return -ENODEV;
        }
        return 0;
-outerr:
-       free_rs(rs_decoder);
-       return ret;
 }
 
-static void __exit cleanup_nanddoc(void)
+void __exit cleanup_nanddoc(void)
 {
-       /* Cleanup the nand/DoC resources */
-       release_nanddoc();
+       struct mtd_info *mtd, *nextmtd;
+       struct nand_chip *nand;
+       struct doc_priv *doc;
 
-       /* Free the reed solomon resources */
-       if (rs_decoder) {
-               free_rs(rs_decoder);
+       for (mtd = doclist; mtd; mtd = nextmtd) {
+               nand = mtd->priv;
+               doc = (void *)nand->priv;
+
+               nextmtd = doc->nextdoc;
+               nand_release(mtd);
+               iounmap((void *)doc->virtadr);
+               kfree(mtd);
        }
 }