Beispiel #1
0
/* For some reason the Millennium Plus seems to occasionally 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);
	}
}
Beispiel #2
0
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;
    unsigned long docptr = doc->virtadr;

    if(debug)printk("write_byte %02x\n", datum);
    WriteDOC(datum, docptr, CDSNSlowIO);
    WriteDOC(datum, docptr, 2k_CDSN_IO);
}
Beispiel #3
0
static void DoC_Command(void __iomem * docptr, unsigned char command,
			       unsigned char xtraflags)
{
	
	WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
	DoC_Delay(docptr, 4);

	
	WriteDOC(command, docptr, Mil_CDSN_IO);
	WriteDOC(0x00, docptr, WritePipeTerm);

	
	WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
	DoC_Delay(docptr, 4);
}
Beispiel #4
0
static void DoC_Command(void __iomem * docptr, unsigned char command,
			       unsigned char xtraflags)
{
	/* Assert the CLE (Command Latch Enable) line to the flash chip */
	WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
	DoC_Delay(docptr, 4);

	/* Send the command */
	WriteDOC(command, docptr, Mil_CDSN_IO);
	WriteDOC(0x00, docptr, WritePipeTerm);

	/* Lower the CLE line */
	WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
	DoC_Delay(docptr, 4);
}
/* Perform the required delay cycles by writing to the NOP register */
static void DoC_Delay(unsigned long docptr, int cycles)
{
	int i;

	for (i = 0; (i < cycles); i++)
		WriteDOC(0, docptr, Mplus_NOP);
}
Beispiel #6
0
/* Perform the required delay cycles by writing to the NOP register */
static void DoC_Delay(void __iomem * docptr, int cycles)
{
	int i;

	for (i = 0; (i < cycles); i++)
		WriteDOC(0, docptr, Mplus_NOP);
}
Beispiel #7
0
/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
static int DoC_SelectFloor(void __iomem * docptr, int floor)
{
	/* Select the floor (bank) of chips required */
	WriteDOC(floor, docptr, FloorSelect);

	/* Wait for the chip to be ready */
	return DoC_WaitReady(docptr);
}
Beispiel #8
0
static int DoC_SelectFloor(void __iomem * docptr, int floor)
{
	
	WriteDOC(floor, docptr, FloorSelect);

	
	return DoC_WaitReady(docptr);
}
Beispiel #9
0
/* DoC_SelectChip: Select a given flash chip within the current floor */
static int DoC_SelectChip(void __iomem * docptr, int chip)
{
	/* Select the individual flash chip requested */
	WriteDOC(chip, docptr, CDSNDeviceSelect);
	DoC_Delay(docptr, 4);

	/* Wait for it to be ready */
	return DoC_WaitReady(docptr);
}
Beispiel #10
0
static int DoC_SelectChip(void __iomem * docptr, int chip)
{
	
	WriteDOC(chip, docptr, CDSNDeviceSelect);
	DoC_Delay(docptr, 4);

	
	return DoC_WaitReady(docptr);
}
Beispiel #11
0
static inline void MemWriteDOC(void __iomem * docptr, unsigned char *buf, int len)
{
#ifndef USE_MEMCPY
	int i;
	for (i = 0; i < len; i++)
		WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
#else
	memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len);
#endif
}
Beispiel #12
0
static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs,
		       unsigned char xtraflags1, unsigned char xtraflags2)
{
	unsigned long docptr;
	int i;

	docptr = doc->virtadr;

	if (DoC_is_2000(doc))
		xtraflags1 |= CDSN_CTRL_FLASH_IO;

	/* Assert the ALE (Address Latch Enable) line to the flash chip */
	WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);

	DoC_Delay(doc, 4);	/* Software requirement 11.4.3 for Millennium */

	/* Send the address */
	/* Devices with 256-byte page are addressed as:
	   Column (bits 0-7), Page (bits 8-15, 16-23, 24-31)
	   * there is no device on the market with page256
	   and more than 24 bits.
	   Devices with 512-byte page are addressed as:
	   Column (bits 0-7), Page (bits 9-16, 17-24, 25-31)
	   * 25-31 is sent only if the chip support it.
	   * bit 8 changes the read command to be sent
	   (NAND_CMD_READ0 or NAND_CMD_READ1).
	 */

	if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) {
		if (DoC_is_Millennium(doc))
			WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
		WriteDOC_(ofs & 0xff, docptr, doc->ioreg);
	}

	if (doc->page256) {
		ofs = ofs >> 8;
	} else {
Beispiel #13
0
static inline void DoC_Address(void __iomem * docptr, int numbytes, unsigned long ofs,
			       unsigned char xtraflags1, unsigned char xtraflags2)
{
	/* Assert the ALE (Address Latch Enable) line to the flash chip */
	WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
	DoC_Delay(docptr, 4);

	/* Send the address */
	switch (numbytes)
	    {
	    case 1:
		    /* Send single byte, bits 0-7. */
		    WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC(0x00, docptr, WritePipeTerm);
		    break;
	    case 2:
		    /* Send bits 9-16 followed by 17-23 */
		    WriteDOC((ofs >> 9)  & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC(0x00, docptr, WritePipeTerm);
		break;
	    case 3:
		    /* Send 0-7, 9-16, then 17-23 */
		    WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC((ofs >> 9)  & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC(0x00, docptr, WritePipeTerm);
		break;
	    default:
		return;
	    }

	/* Lower the ALE line */
	WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl);
	DoC_Delay(docptr, 4);
}
Beispiel #14
0
static inline void DoC_Address(void __iomem * docptr, int numbytes, unsigned long ofs,
			       unsigned char xtraflags1, unsigned char xtraflags2)
{
	
	WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
	DoC_Delay(docptr, 4);

	
	switch (numbytes)
	    {
	    case 1:
		    
		    WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC(0x00, docptr, WritePipeTerm);
		    break;
	    case 2:
		    
		    WriteDOC((ofs >> 9)  & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC(0x00, docptr, WritePipeTerm);
		break;
	    case 3:
		    
		    WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC((ofs >> 9)  & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
		    WriteDOC(0x00, docptr, WritePipeTerm);
		break;
	    default:
		return;
	    }

	
	WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl);
	DoC_Delay(docptr, 4);
}
Beispiel #15
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;
}   
/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
static int DoC_SelectFloor(unsigned long docptr, int floor)
{
	WriteDOC((floor & 0x3), docptr, Mplus_DeviceSelect);
	return 0;
}
Beispiel #17
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;
}
Beispiel #18
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;
}
Beispiel #19
0
/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
static int DoC_SelectFloor(void __iomem * docptr, int floor)
{
	WriteDOC((floor & 0x3), docptr, Mplus_DeviceSelect);
	return 0;
}
Beispiel #20
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;
}