Esempio n. 1
0
/* Perform the required delay cycles by reading from the appropriate register */
static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles)
{
	volatile char dummy;
	int i;

	for (i = 0; i < cycles; i++) {
		if (DoC_is_Millennium(doc))
			dummy = ReadDOC(doc->virtadr, NOP);
		else
			dummy = ReadDOC(doc->virtadr, DOCStatus);
	}

}
Esempio n. 2
0
/* Perform the required delay cycles by reading from the NOP register */
static void DoC_Delay(void __iomem * docptr, unsigned short cycles)
{
	volatile char dummy;
	int i;

	for (i = 0; i < cycles; i++)
		dummy = ReadDOC(docptr, NOP);
}
Esempio n. 3
0
/* For some reason the Millennium Plus seems to occassionally put itself
 * into reset mode. For me this happens randomly, with no pattern that I
 * can detect. M-systems suggest always check this on any block level
 * operation and setting to normal mode if in reset mode.
 */
static inline void DoC_CheckASIC(void __iomem * docptr)
{
	/* Make sure the DoC is in normal mode */
	if ((ReadDOC(docptr, Mplus_DOCControl) & DOC_MODE_NORMAL) == 0) {
		WriteDOC((DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_DOCControl);
		WriteDOC(~(DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_CtrlConfirm);
	}
}
Esempio n. 4
0
static inline void MemReadDOC(void __iomem * docptr, unsigned char *buf, int len)
{
#ifndef USE_MEMCPY
	int i;
	for (i = 0; i < len; i++)
		buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
#else
	memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len);
#endif
}
Esempio n. 5
0
static int doc2000_verifybuf(struct mtd_info *mtd,
                             const u_char *buf, int len)
{
    struct nand_chip *this = mtd->priv;
    struct doc_priv *doc = (void *)this->priv;
    unsigned long docptr = doc->virtadr;
    int i;

    for (i=0; i < len; i++)
        if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO))
            return -EFAULT;
    return 0;
}
Esempio n. 6
0
static void doc2000_readbuf(struct mtd_info *mtd,
                            u_char *buf, int len)
{
    struct nand_chip *this = mtd->priv;
    struct doc_priv *doc = (void *)this->priv;
    unsigned long docptr = doc->virtadr;
    int i;

    if (debug)printk("readbuf of %d bytes: ", len);

    for (i=0; i < len; i++) {
        buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i);
    }
}
Esempio n. 7
0
static inline int DoC_WaitReady(struct doc_priv *doc)
{
    unsigned long docptr = doc->virtadr;
    int ret = 0;

    DoC_Delay(doc, 4);

    if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
        /* Call the out-of-line routine to wait */
        ret = _DoC_WaitReady(doc);

    DoC_Delay(doc, 2);
    if(debug) printk("DoC_WaitReady OK\n");
    return ret;
}
Esempio n. 8
0
static inline int DoC_WaitReady(void __iomem * docptr)
{
	/* This is inline, to optimise the common case, where it's ready instantly */
	int ret = 0;

	/* read form NOP register should be issued prior to the read from CDSNControl
	   see Software Requirement 11.4 item 2. */
	DoC_Delay(docptr, 4);

	if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK)
		/* Call the out-of-line routine to wait */
		ret = _DoC_WaitReady(docptr);

	return ret;
}
Esempio n. 9
0
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
static int _DoC_WaitReady(void __iomem * docptr)
{
	unsigned int c = 0xffff;

	pr_debug("_DoC_WaitReady called for out-of-line wait\n");

	/* Out-of-line routine to wait for chip response */
	while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c)
		;

	if (c == 0)
		pr_debug("_DoC_WaitReady timed out.\n");

	return (c == 0);
}
Esempio n. 10
0
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
static int _DoC_WaitReady(void __iomem * docptr)
{
	unsigned short c = 0xffff;

	DEBUG(MTD_DEBUG_LEVEL3,
	      "_DoC_WaitReady called for out-of-line wait\n");

	/* Out-of-line routine to wait for chip response */
	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
		;

	if (c == 0)
		DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");

	return (c == 0);
}
Esempio n. 11
0
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
static int _DoC_WaitReady(unsigned long docptr)
{
	unsigned int c = 0xffff;

	DEBUG(MTD_DEBUG_LEVEL3,
	      "_DoC_WaitReady called for out-of-line wait\n");

	/* Out-of-line routine to wait for chip response */
	while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c)
		;

	if (c == 0)
		DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");

	return (c == 0);
}
Esempio n. 12
0
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
static int _DoC_WaitReady(struct DiskOnChip *doc)
{
	unsigned long docptr = doc->virtadr;
	unsigned short c = 0xffff;

	DEBUG(MTD_DEBUG_LEVEL3,
	      "_DoC_WaitReady called for out-of-line wait\n");

	/* Out-of-line routine to wait for chip response */
	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
		;

	if (c == 0)
		DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");

	return (c == 0);
}
Esempio n. 13
0
static inline int DoC_WaitReady(void __iomem * docptr)
{
	
	int ret = 0;

	
	DoC_Delay(docptr, 4);

	if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
		
		ret = _DoC_WaitReady(docptr);

	
	DoC_Delay(docptr, 2);

	return ret;
}
Esempio n. 14
0
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
static int _DoC_WaitReady(struct doc_priv *doc)
{
    unsigned long docptr = doc->virtadr;
    unsigned long timeo = jiffies + (HZ * 10);

    if(debug) printk("_DoC_WaitReady...\n");
    /* Out-of-line routine to wait for chip response */
    while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
        if (time_after(jiffies, timeo)) {
            printk("_DoC_WaitReady timed out.\n");
            return -EIO;
        }
        udelay(1);
        cond_resched();
    }

    return 0;
}
Esempio n. 15
0
static inline int DoC_WaitReady(unsigned long docptr)
{
	/* This is inline, to optimise the common case, where it's ready instantly */
	int ret = 0;

	/* 4 read form NOP register should be issued in prior to the read from CDSNControl
	   see Software Requirement 11.4 item 2. */
	DoC_Delay(docptr, 4);

	if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
		/* Call the out-of-line routine to wait */
		ret = _DoC_WaitReady(docptr);

	/* issue 2 read from NOP register after reading from CDSNControl register
	   see Software Requirement 11.4 item 2. */
	DoC_Delay(docptr, 2);

	return ret;
}
Esempio n. 16
0
static void doc2000_readbuf_dword(struct mtd_info *mtd,
                                  u_char *buf, int len)
{
    struct nand_chip *this = mtd->priv;
    struct doc_priv *doc = (void *)this->priv;
    unsigned long docptr = doc->virtadr;
    int i;

    if (debug) printk("readbuf_dword of %d bytes: ", len);

    if (unlikely((((unsigned long)buf)|len) & 3)) {
        for (i=0; i < len; i++) {
            *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i);
        }
    } else {
        for (i=0; i < len; i+=4) {
            *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i);
        }
    }
}
Esempio n. 17
0
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
static int _DoC_WaitReady(struct DiskOnChip *doc)
{
	unsigned long docptr = doc->virtadr;
	unsigned long timeo = jiffies + (HZ * 10);

	DEBUG(MTD_DEBUG_LEVEL3,
	      "_DoC_WaitReady called for out-of-line wait\n");

	/* Out-of-line routine to wait for chip response */
	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
		if (time_after(jiffies, timeo)) {
			DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
			return -EIO;
		}
		udelay(1);
		cond_resched();
	}

	return 0;
}
Esempio n. 18
0
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
static int _DoC_WaitReady(struct DiskOnChip *doc)
{
	void __iomem *docptr = doc->virtadr;
	unsigned long timeo = jiffies + (HZ * 10);

	pr_debug("_DoC_WaitReady called for out-of-line wait\n");

	/* Out-of-line routine to wait for chip response */
	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
		/* issue 2 read from NOP register after reading from CDSNControl register
	   	see Software Requirement 11.4 item 2. */
		DoC_Delay(doc, 2);

		if (time_after(jiffies, timeo)) {
			pr_debug("_DoC_WaitReady timed out.\n");
			return -EIO;
		}
		udelay(1);
		cond_resched();
	}

	return 0;
}
Esempio n. 19
0
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
static int _DoC_WaitReady(struct DiskOnChip *doc)
{
	unsigned long docptr = doc->virtadr;
	unsigned long timeo = jiffies + (HZ * 10);

	DEBUG(MTD_DEBUG_LEVEL3,
	      "_DoC_WaitReady called for out-of-line wait\n");

	/* Out-of-line routine to wait for chip response */
	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
		if (time_after(jiffies, timeo)) {
			DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
			return -EIO;
		}
		if (current->need_resched) {
			set_current_state(TASK_UNINTERRUPTIBLE);
			schedule_timeout(1);
		}
		else
			udelay(1);
	}

	return 0;
}
Esempio n. 20
0
static inline int __init doccheck(void __iomem *potential, unsigned long physadr)
{
	void __iomem *window=potential;
	unsigned char tmp, tmpb, tmpc, ChipID;
#ifndef DOC_PASSIVE_PROBE
	unsigned char tmp2;
#endif

	/* Routine copied from the Linux DOC driver */

#ifdef CONFIG_MTD_DOCPROBE_55AA
	/* Check for 0x55 0xAA signature at beginning of window,
	   this is no longer true once we remove the IPL (for Millennium */
	if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa)
		return 0;
#endif /* CONFIG_MTD_DOCPROBE_55AA */

#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. 
	 */
	tmp2 = ReadDOC(window, DOCControl);
	
	/* Reset the DiskOnChip ASIC */
	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, 
		 window, DOCControl);
	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, 
		 window, DOCControl);
	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, 
		 window, DOCControl);
#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 */
		tmp  = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
		tmpb = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
		tmpc = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
		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;
		tmpc = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
		if (tmp != tmpb && tmp == tmpc)
				return ChipID;
		break;
		
	case DOC_ChipID_DocMilPlus16:
	case DOC_ChipID_DocMilPlus32:
	case 0:
		/* Possible Millennium+, need to do more checks */
#ifndef DOC_PASSIVE_PROBE
		/* Possibly release from power down mode */
		for (tmp = 0; (tmp < 4); tmp++)
			ReadDOC(window, Mplus_Power);

		/* Reset the DiskOnChip ASIC */
		tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
			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 |
			DOC_MODE_BDECT;
		WriteDOC(tmp, window, Mplus_DOCControl);
		WriteDOC(~tmp, window, Mplus_CtrlConfirm);
		mdelay(1);
#endif /* !DOC_PASSIVE_PROBE */	

		ChipID = ReadDOC(window, ChipID);

		switch (ChipID) {
		case DOC_ChipID_DocMilPlus16:
		case DOC_ChipID_DocMilPlus32:
			/* Check the TOGGLE bit in the toggle register */
			tmp  = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
			tmpb = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
			tmpc = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
			if (tmp != tmpb && tmp == tmpc)
					return ChipID;
		default:
			break;
		}
		/* FALL TRHU */

	default:

#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
		/* Put back the contents of the DOCControl register, in case it's not
		 * actually a DiskOnChip.
		 */
		WriteDOC(tmp2, window, DOCControl);
#endif
		return 0;
	}

	printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n");

#ifndef DOC_PASSIVE_PROBE
	/* Put back the contents of the DOCControl register: it's not a DiskOnChip */
	WriteDOC(tmp2, window, DOCControl);
#endif
	return 0;
}   
Esempio n. 21
0
/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
{
	int mfr, id, i, j;
	volatile char dummy;
	void __iomem * docptr = doc->virtadr;

	/* Page in the required floor/chip */
	DoC_SelectFloor(docptr, floor);
	DoC_SelectChip(docptr, chip);

	/* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
	WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);

	/* Reset the chip, see Software Requirement 11.4 item 1. */
	DoC_Command(docptr, NAND_CMD_RESET, 0);
	DoC_WaitReady(docptr);

	/* Read the NAND chip ID: 1. Send ReadID command */
	DoC_Command(docptr, NAND_CMD_READID, 0);

	/* Read the NAND chip ID: 2. Send address byte zero */
	DoC_Address(doc, 1, 0x00, 0, 0x00);

	WriteDOC(0, docptr, Mplus_FlashControl);
	DoC_WaitReady(docptr);

	/* Read the manufacturer and device id codes of the flash device through
	   CDSN IO register see Software Requirement 11.4 item 5.*/
	dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
	dummy = ReadDOC(docptr, Mplus_ReadPipeInit);

	mfr = ReadDOC(docptr, Mil_CDSN_IO);
	if (doc->interleave)
		dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */

	id  = ReadDOC(docptr, Mil_CDSN_IO);
	if (doc->interleave)
		dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */

	dummy = ReadDOC(docptr, Mplus_LastDataRead);
	dummy = ReadDOC(docptr, Mplus_LastDataRead);

	/* Disable flash internally */
	WriteDOC(0, docptr, Mplus_FlashSelect);

	/* No response - return failure */
	if (mfr == 0xff || mfr == 0)
		return 0;

	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
		if (id == nand_flash_ids[i].id) {
			/* Try to identify manufacturer */
			for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
				if (nand_manuf_ids[j].id == mfr)
					break;
			}
			printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, "
			       "Chip ID: %2.2X (%s:%s)\n", mfr, id,
			       nand_manuf_ids[j].name, nand_flash_ids[i].name);
			doc->mfr = mfr;
			doc->id = id;
			doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1;
			doc->erasesize = nand_flash_ids[i].erasesize << doc->interleave;
			break;
		}
	}

	if (nand_flash_ids[i].name == NULL)
		return 0;
	return 1;
}
Esempio n. 22
0
static inline int __init doccheck(unsigned long potential, unsigned long physadr)
{
	unsigned long window=potential;
	unsigned char tmp, ChipID;
#ifndef DOC_PASSIVE_PROBE
	unsigned char tmp2;
#endif

	/* Routine copied from the Linux DOC driver */

#ifdef CONFIG_MTD_DOCPROBE_55AA
	/* Check for 0x55 0xAA signature at beginning of window,
	   this is no longer true once we remove the IPL (for Millennium */
	if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa)
		return 0;
#endif /* CONFIG_MTD_DOCPROBE_55AA */

#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. 
	 */
	tmp2 = ReadDOC(window, DOCControl);
	
	/* Reset the DiskOnChip ASIC */
	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, 
		 window, DOCControl);
	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, 
		 window, DOCControl);
	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, 
		 window, DOCControl);
#endif /* !DOC_PASSIVE_PROBE */	

	ChipID = ReadDOC(window, ChipID);
  
	switch (ChipID) {
	case DOC_ChipID_Doc2k:
		/* Check the TOGGLE bit in the ECC register */
		tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
		if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp)
				return ChipID;
		break;
		
	case DOC_ChipID_DocMil:
		/* Check the TOGGLE bit in the ECC register */
		tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
		if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp)
				return ChipID;
		break;
		
	default:
#ifndef CONFIG_MTD_DOCPROBE_55AA
		printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
		       ChipID, physadr);
#endif
#ifndef DOC_PASSIVE_PROBE
		/* Put back the contents of the DOCControl register, in case it's not
		 * actually a DiskOnChip.
		 */
		WriteDOC(tmp2, window, DOCControl);
#endif
		return 0;
	}

	printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n");

#ifndef DOC_PASSIVE_PROBE
	/* Put back the contents of the DOCControl register: it's not a DiskOnChip */
	WriteDOC(tmp2, window, DOCControl);
#endif
	return 0;
}   
Esempio n. 23
0
static inline int __init doccheck(void __iomem *potential, unsigned long physadr)
{
	void __iomem *window=potential;
	unsigned char tmp, tmpb, tmpc, ChipID;
#ifndef DOC_PASSIVE_PROBE
	unsigned char tmp2;
#endif

	

#ifdef CONFIG_MTD_DOCPROBE_55AA
	
	if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa)
		return 0;
#endif 

#ifndef DOC_PASSIVE_PROBE
	
	tmp2 = ReadDOC(window, DOCControl);

	
	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
		 window, DOCControl);
	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
		 window, DOCControl);

	
	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
		 window, DOCControl);
	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
		 window, DOCControl);
#endif 

	
	ChipID = ReadDOC(window, ChipID);

	switch (ChipID) {
	case DOC_ChipID_Doc2k:
		
		tmp  = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
		tmpb = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
		tmpc = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
		if (tmp != tmpb && tmp == tmpc)
				return ChipID;
		break;

	case DOC_ChipID_DocMil:
		
		ReadDOC(window, ChipID);
		ReadDOC(window, ChipID);
		if (ReadDOC(window, ChipID) != DOC_ChipID_DocMil)
			ChipID = DOC_ChipID_Doc2kTSOP;

		
		tmp  = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
		tmpb = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
		tmpc = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
		if (tmp != tmpb && tmp == tmpc)
				return ChipID;
		break;

	case DOC_ChipID_DocMilPlus16:
	case DOC_ChipID_DocMilPlus32:
	case 0:
		
#ifndef DOC_PASSIVE_PROBE
		
		for (tmp = 0; (tmp < 4); tmp++)
			ReadDOC(window, Mplus_Power);

		
		tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
			DOC_MODE_BDECT;
		WriteDOC(tmp, window, Mplus_DOCControl);
		WriteDOC(~tmp, window, Mplus_CtrlConfirm);

		mdelay(1);
		
		tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
			DOC_MODE_BDECT;
		WriteDOC(tmp, window, Mplus_DOCControl);
		WriteDOC(~tmp, window, Mplus_CtrlConfirm);
		mdelay(1);
#endif 

		ChipID = ReadDOC(window, ChipID);

		switch (ChipID) {
		case DOC_ChipID_DocMilPlus16:
		case DOC_ChipID_DocMilPlus32:
			
			tmp  = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
			tmpb = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
			tmpc = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
			if (tmp != tmpb && tmp == tmpc)
					return ChipID;
		default:
			break;
		}
		

	default:

#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
		
		WriteDOC(tmp2, window, DOCControl);
#endif
		return 0;
	}

	printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n");

#ifndef DOC_PASSIVE_PROBE
	
	WriteDOC(tmp2, window, DOCControl);
#endif
	return 0;
}