Revert to Fedora kernel-2.6.17-1.2187_FC5 patched with vs2.0.2.1; there are too many...
[linux-2.6.git] / drivers / mtd / devices / docprobe.c
index f7a91fa..13178b9 100644 (file)
@@ -4,22 +4,22 @@
 /* (C) 1999 Machine Vision Holdings, Inc.                      */
 /* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>         */
 
-/* $Id: docprobe.c,v 1.36 2003/05/23 11:29:34 dwmw2 Exp $      */
+/* $Id: docprobe.c,v 1.46 2005/11/07 11:14:25 gleixner Exp $   */
 
 
 
 /* DOC_PASSIVE_PROBE:
-   In order to ensure that the BIOS checksum is correct at boot time, and 
-   hence that the onboard BIOS extension gets executed, the DiskOnChip 
-   goes into reset mode when it is read sequentially: all registers 
-   return 0xff until the chip is woken up again by writing to the 
-   DOCControl register. 
-
-   Unfortunately, this means that the probe for the DiskOnChip is unsafe, 
-   because one of the first things it does is write to where it thinks 
-   the DOCControl register should be - which may well be shared memory 
-   for another device. I've had machines which lock up when this is 
-   attempted. Hence the possibility to do a passive probe, which will fail 
+   In order to ensure that the BIOS checksum is correct at boot time, and
+   hence that the onboard BIOS extension gets executed, the DiskOnChip
+   goes into reset mode when it is read sequentially: all registers
+   return 0xff until the chip is woken up again by writing to the
+   DOCControl register.
+
+   Unfortunately, this means that the probe for the DiskOnChip is unsafe,
+   because one of the first things it does is write to where it thinks
+   the DOCControl register should be - which may well be shared memory
+   for another device. I've had machines which lock up when this is
+   attempted. Hence the possibility to do a passive probe, which will fail
    to detect a chip in reset mode, but is at least guaranteed not to lock
    the machine.
 
@@ -33,9 +33,9 @@
 
    The old Millennium-only driver has been retained just in case there
    are problems with the new code. If the combined driver doesn't work
-   for you, you can try the old one by undefining DOC_SINGLE_DRIVER 
+   for you, you can try the old one by undefining DOC_SINGLE_DRIVER
    below and also enabling it in your configuration. If this fixes the
-   problems, please send a report to the MTD mailing list at 
+   problems, please send a report to the MTD mailing list at
    <linux-mtd@lists.infradead.org>.
 */
 #define DOC_SINGLE_DRIVER
 
 
 static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
-MODULE_PARM(doc_config_location, "l");
+module_param(doc_config_location, ulong, 0);
 MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
 
 static unsigned long __initdata doc_locations[] = {
 #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
 #ifdef CONFIG_MTD_DOCPROBE_HIGH
-       0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, 
+       0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
        0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
-       0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, 
-       0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, 
+       0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
+       0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
        0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
 #else /*  CONFIG_MTD_DOCPROBE_HIGH */
-       0xc8000, 0xca000, 0xcc000, 0xce000, 
+       0xc8000, 0xca000, 0xcc000, 0xce000,
        0xd0000, 0xd2000, 0xd4000, 0xd6000,
-       0xd8000, 0xda000, 0xdc000, 0xde000, 
-       0xe0000, 0xe2000, 0xe4000, 0xe6000, 
+       0xd8000, 0xda000, 0xdc000, 0xde000,
+       0xe0000, 0xe2000, 0xe4000, 0xe6000,
        0xe8000, 0xea000, 0xec000, 0xee000,
 #endif /*  CONFIG_MTD_DOCPROBE_HIGH */
 #elif defined(__PPC__)
@@ -94,9 +94,9 @@ static unsigned long __initdata doc_locations[] = {
 
 /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
 
-static inline int __init doccheck(unsigned long potential, unsigned long physadr)
+static inline int __init doccheck(void __iomem *potential, unsigned long physadr)
 {
-       unsigned long window=potential;
+       void __iomem *window=potential;
        unsigned char tmp, tmpb, tmpc, ChipID;
 #ifndef DOC_PASSIVE_PROBE
        unsigned char tmp2;
@@ -111,32 +111,35 @@ static inline int __init doccheck(unsigned long potential, unsigned long physadr
                return 0;
 #endif /* CONFIG_MTD_DOCPROBE_55AA */
 
-#ifndef DOC_PASSIVE_PROBE      
+#ifndef DOC_PASSIVE_PROBE
        /* It's not possible to cleanly detect the DiskOnChip - the
         * bootup procedure will put the device into reset mode, and
         * it's not possible to talk to it without actually writing
         * to the DOCControl register. So we store the current contents
         * of the DOCControl register's location, in case we later decide
         * that it's not a DiskOnChip, and want to put it back how we
-        * found it. 
+        * found it.
         */
        tmp2 = ReadDOC(window, DOCControl);
-       
+
        /* Reset the DiskOnChip ASIC */
-       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, 
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
                 window, DOCControl);
-       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, 
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
                 window, DOCControl);
-       
+
        /* Enable the DiskOnChip ASIC */
-       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, 
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
                 window, DOCControl);
-       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, 
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
                 window, DOCControl);
-#endif /* !DOC_PASSIVE_PROBE */        
+#endif /* !DOC_PASSIVE_PROBE */
 
+       /* We need to read the ChipID register four times. For some
+          newer DiskOnChip 2000 units, the first three reads will
+          return the DiskOnChip Millennium ident. Don't ask. */
        ChipID = ReadDOC(window, ChipID);
-  
+
        switch (ChipID) {
        case DOC_ChipID_Doc2k:
                /* Check the TOGGLE bit in the ECC register */
@@ -146,8 +149,14 @@ static inline int __init doccheck(unsigned long potential, unsigned long physadr
                if (tmp != tmpb && tmp == tmpc)
                                return ChipID;
                break;
-               
+
        case DOC_ChipID_DocMil:
+               /* Check for the new 2000 with Millennium ASIC */
+               ReadDOC(window, ChipID);
+               ReadDOC(window, ChipID);
+               if (ReadDOC(window, ChipID) != DOC_ChipID_DocMil)
+                       ChipID = DOC_ChipID_Doc2kTSOP;
+
                /* Check the TOGGLE bit in the ECC register */
                tmp  = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
                tmpb = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
@@ -155,7 +164,7 @@ static inline int __init doccheck(unsigned long potential, unsigned long physadr
                if (tmp != tmpb && tmp == tmpc)
                                return ChipID;
                break;
-               
+
        case DOC_ChipID_DocMilPlus16:
        case DOC_ChipID_DocMilPlus32:
        case 0:
@@ -170,7 +179,7 @@ static inline int __init doccheck(unsigned long potential, unsigned long physadr
                        DOC_MODE_BDECT;
                WriteDOC(tmp, window, Mplus_DOCControl);
                WriteDOC(~tmp, window, Mplus_CtrlConfirm);
-       
+
                mdelay(1);
                /* Enable the DiskOnChip ASIC */
                tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
@@ -178,7 +187,7 @@ static inline int __init doccheck(unsigned long potential, unsigned long physadr
                WriteDOC(tmp, window, Mplus_DOCControl);
                WriteDOC(~tmp, window, Mplus_CtrlConfirm);
                mdelay(1);
-#endif /* !DOC_PASSIVE_PROBE */        
+#endif /* !DOC_PASSIVE_PROBE */
 
                ChipID = ReadDOC(window, ChipID);
 
@@ -191,7 +200,6 @@ static inline int __init doccheck(unsigned long potential, unsigned long physadr
                        tmpc = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
                        if (tmp != tmpb && tmp == tmpc)
                                        return ChipID;
-                       break;
                default:
                        break;
                }
@@ -199,8 +207,8 @@ static inline int __init doccheck(unsigned long potential, unsigned long physadr
 
        default:
 
-#ifndef CONFIG_MTD_DOCPROBE_55AA
-               printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
+#ifdef CONFIG_MTD_DOCPROBE_55AA
+               printk(KERN_DEBUG "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
                       ChipID, physadr);
 #endif
 #ifndef DOC_PASSIVE_PROBE
@@ -219,13 +227,13 @@ static inline int __init doccheck(unsigned long potential, unsigned long physadr
        WriteDOC(tmp2, window, DOCControl);
 #endif
        return 0;
-}   
+}
 
 static int docfound;
 
 static void __init DoC_Probe(unsigned long physadr)
 {
-       unsigned long docptr;
+       void __iomem *docptr;
        struct DiskOnChip *this;
        struct mtd_info *mtd;
        int ChipID;
@@ -235,23 +243,29 @@ static void __init DoC_Probe(unsigned long physadr)
        char *im_modname = NULL;
        void (*initroutine)(struct mtd_info *) = NULL;
 
-       docptr = (unsigned long)ioremap(physadr, DOC_IOREMAP_LEN);
-       
+       docptr = ioremap(physadr, DOC_IOREMAP_LEN);
+
        if (!docptr)
                return;
-       
+
        if ((ChipID = doccheck(docptr, physadr))) {
+               if (ChipID == DOC_ChipID_Doc2kTSOP) {
+                       /* Remove this at your own peril. The hardware driver works but nothing prevents you from erasing bad blocks */
+                       printk(KERN_NOTICE "Refusing to drive DiskOnChip 2000 TSOP until Bad Block Table is correctly supported by INFTL\n");
+                       iounmap(docptr);
+                       return;
+               }
                docfound = 1;
                mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL);
 
                if (!mtd) {
                        printk(KERN_WARNING "Cannot allocate memory for data structures. Dropping.\n");
-                       iounmap((void *)docptr);
+                       iounmap(docptr);
                        return;
                }
-               
+
                this = (struct DiskOnChip *)(&mtd[1]);
-               
+
                memset((char *)mtd,0, sizeof(struct mtd_info));
                memset((char *)this, 0, sizeof(struct DiskOnChip));
 
@@ -262,12 +276,18 @@ static void __init DoC_Probe(unsigned long physadr)
                sprintf(namebuf, "with ChipID %2.2X", ChipID);
 
                switch(ChipID) {
+               case DOC_ChipID_Doc2kTSOP:
+                       name="2000 TSOP";
+                       im_funcname = "DoC2k_init";
+                       im_modname = "doc2000";
+                       break;
+
                case DOC_ChipID_Doc2k:
                        name="2000";
                        im_funcname = "DoC2k_init";
                        im_modname = "doc2000";
                        break;
-                       
+
                case DOC_ChipID_DocMil:
                        name="Millennium";
 #ifdef DOC_SINGLE_DRIVER
@@ -298,7 +318,7 @@ static void __init DoC_Probe(unsigned long physadr)
                printk(KERN_NOTICE "Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr);
                kfree(mtd);
        }
-       iounmap((void *)docptr);
+       iounmap(docptr);
 }
 
 
@@ -308,10 +328,10 @@ static void __init DoC_Probe(unsigned long physadr)
  *
  ****************************************************************************/
 
-int __init init_doc(void)
+static int __init init_doc(void)
 {
        int i;
-       
+
        if (doc_config_location) {
                printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location);
                DoC_Probe(doc_config_location);