static int DoC_Command(struct DiskOnChip *doc, unsigned char command, unsigned char xtraflags) { void __iomem *docptr = doc->virtadr; if (DoC_is_2000(doc)) xtraflags |= CDSN_CTRL_FLASH_IO; /* Assert the CLE (Command Latch Enable) line to the flash chip */ WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl); DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ if (DoC_is_Millennium(doc)) WriteDOC(command, docptr, CDSNSlowIO); /* Send the command */ WriteDOC_(command, docptr, doc->ioreg); if (DoC_is_Millennium(doc)) WriteDOC(command, docptr, WritePipeTerm); /* Lower the CLE line */ WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ /* Wait for the chip to respond - Software requirement 11.4.1 (extended for any command) */ return DoC_WaitReady(doc); }
/* 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; /* Page in the required floor/chip FIXME: is this supported by Millennium ?? */ DoC_SelectFloor(doc->virtadr, floor); DoC_SelectChip(doc->virtadr, chip); /* Reset the chip, see Software Requirement 11.4 item 1. */ DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP); DoC_WaitReady(doc->virtadr); /* Read the NAND chip ID: 1. Send ReadID command */ DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP); /* Read the NAND chip ID: 2. Send address byte zero */ DoC_Address(doc->virtadr, 1, 0x00, CDSN_CTRL_WP, 0x00); /* Read the manufacturer and device id codes of the flash device through CDSN IO register see Software Requirement 11.4 item 5.*/ dummy = ReadDOC(doc->virtadr, ReadPipeInit); DoC_Delay(doc->virtadr, 2); mfr = ReadDOC(doc->virtadr, Mil_CDSN_IO); DoC_Delay(doc->virtadr, 2); id = ReadDOC(doc->virtadr, Mil_CDSN_IO); dummy = ReadDOC(doc->virtadr, LastDataRead); /* No response - return failure */ if (mfr == 0xff || mfr == 0) return 0; /* FIXME: to deal with multi-flash on multi-Millennium case more carefully */ 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; break; } } if (nand_flash_ids[i].name == NULL) return 0; else return 1; }
static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) { int mfr, id, i, j; volatile char dummy; DoC_SelectFloor(doc->virtadr, floor); DoC_SelectChip(doc->virtadr, chip); DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP); DoC_WaitReady(doc->virtadr); DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP); DoC_Address(doc->virtadr, 1, 0x00, CDSN_CTRL_WP, 0x00); dummy = ReadDOC(doc->virtadr, ReadPipeInit); DoC_Delay(doc->virtadr, 2); mfr = ReadDOC(doc->virtadr, Mil_CDSN_IO); DoC_Delay(doc->virtadr, 2); id = ReadDOC(doc->virtadr, Mil_CDSN_IO); dummy = ReadDOC(doc->virtadr, LastDataRead); if (mfr == 0xff || mfr == 0) return 0; for (i = 0; nand_flash_ids[i].name != NULL; i++) { if ( id == nand_flash_ids[i].id) { 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; break; } } if (nand_flash_ids[i].name == NULL) return 0; else return 1; }
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); }
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; }
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); }
static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs, unsigned char xtraflags1, unsigned char xtraflags2) { int i; void __iomem *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 {
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; }
/* 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); }
static int DoC_SelectChip(void __iomem * docptr, int chip) { WriteDOC(chip, docptr, CDSNDeviceSelect); DoC_Delay(docptr, 4); return DoC_WaitReady(docptr); }
static inline int DoC_WaitReady(void __iomem * 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; }
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); }
static inline int DoC_WaitReady(unsigned long 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; }
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); }
/* 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; }