?? diskonchip.c
字號(hào):
struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; uint16_t mfrid; int i; /* Max 4 chips per floor on DiskOnChip 2000 */ doc->chips_per_floor = 4; /* Find out what the first chip is */ mfrid = doc200x_ident_chip(mtd, 0); /* Find how many chips in each floor. */ for (i = 1; i < 4; i++) { if (doc200x_ident_chip(mtd, i) != mfrid) break; } doc->chips_per_floor = i; printk(KERN_DEBUG "Detected %d chips per floor.\n", i);}static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state){ struct doc_priv *doc = this->priv; int status; DoC_WaitReady(doc); this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); DoC_WaitReady(doc); status = (int)this->read_byte(mtd); return status;}static void doc2001_write_byte(struct mtd_info *mtd, u_char datum){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; WriteDOC(datum, docptr, CDSNSlowIO); WriteDOC(datum, docptr, Mil_CDSN_IO); WriteDOC(datum, docptr, WritePipeTerm);}static u_char doc2001_read_byte(struct mtd_info *mtd){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; /*ReadDOC(docptr, CDSNSlowIO); */ /* 11.4.5 -- delay twice to allow extended length cycle */ DoC_Delay(doc, 2); ReadDOC(docptr, ReadPipeInit); /*return ReadDOC(docptr, Mil_CDSN_IO); */ return ReadDOC(docptr, LastDataRead);}static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; for (i=0; i < len; i++) WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); /* Terminate write pipeline */ WriteDOC(0x00, docptr, WritePipeTerm);}static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; /* Start read pipeline */ ReadDOC(docptr, ReadPipeInit); for (i=0; i < len-1; i++) buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff)); /* Terminate read pipeline */ buf[i] = ReadDOC(docptr, LastDataRead);}static int doc2001_verifybuf(struct mtd_info *mtd, const u_char *buf, int len){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; /* Start read pipeline */ ReadDOC(docptr, ReadPipeInit); for (i=0; i < len-1; i++) if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { ReadDOC(docptr, LastDataRead); return i; } if (buf[i] != ReadDOC(docptr, LastDataRead)) return i; return 0;}static u_char doc2001plus_read_byte(struct mtd_info *mtd){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; u_char ret; ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit); ret = ReadDOC(docptr, Mplus_LastDataRead); if (debug) printk("read_byte returns %02x\n", ret); return ret;}static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; if (debug)printk("writebuf of %d bytes: ", len); for (i=0; i < len; i++) { WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); if (debug && i < 16) printk("%02x ", buf[i]); } if (debug) printk("\n");}static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; if (debug)printk("readbuf of %d bytes: ", len); /* Start read pipeline */ ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit); for (i=0; i < len-2; i++) { buf[i] = ReadDOC(docptr, Mil_CDSN_IO); if (debug && i < 16) printk("%02x ", buf[i]); } /* Terminate read pipeline */ buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead); if (debug && i < 16) printk("%02x ", buf[len-2]); buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead); if (debug && i < 16) printk("%02x ", buf[len-1]); if (debug) printk("\n");}static int doc2001plus_verifybuf(struct mtd_info *mtd, const u_char *buf, int len){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; if (debug)printk("verifybuf of %d bytes: ", len); /* Start read pipeline */ ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit); for (i=0; i < len-2; i++) if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { ReadDOC(docptr, Mplus_LastDataRead); ReadDOC(docptr, Mplus_LastDataRead); return i; } if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead)) return len-2; if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead)) return len-1; return 0;}static void doc2001plus_select_chip(struct mtd_info *mtd, int chip){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int floor = 0; if(debug)printk("select chip (%d)\n", chip); if (chip == -1) { /* Disable flash internally */ WriteDOC(0, docptr, Mplus_FlashSelect); return; } floor = chip / doc->chips_per_floor; chip -= (floor * doc->chips_per_floor); /* Assert ChipEnable and deassert WriteProtect */ WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect); this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); doc->curchip = chip; doc->curfloor = floor;}static void doc200x_select_chip(struct mtd_info *mtd, int chip){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int floor = 0; if(debug)printk("select chip (%d)\n", chip); if (chip == -1) return; floor = chip / doc->chips_per_floor; chip -= (floor * doc->chips_per_floor); /* 11.4.4 -- deassert CE before changing chip */ doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE); WriteDOC(floor, docptr, FloorSelect); WriteDOC(chip, docptr, CDSNDeviceSelect); doc200x_hwcontrol(mtd, NAND_CTL_SETNCE); doc->curchip = chip; doc->curfloor = floor;}static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; switch(cmd) { case NAND_CTL_SETNCE: doc->CDSNControl |= CDSN_CTRL_CE; break; case NAND_CTL_CLRNCE: doc->CDSNControl &= ~CDSN_CTRL_CE; break; case NAND_CTL_SETCLE: doc->CDSNControl |= CDSN_CTRL_CLE; break; case NAND_CTL_CLRCLE: doc->CDSNControl &= ~CDSN_CTRL_CLE; break; case NAND_CTL_SETALE: doc->CDSNControl |= CDSN_CTRL_ALE; break; case NAND_CTL_CLRALE: doc->CDSNControl &= ~CDSN_CTRL_ALE; break; case NAND_CTL_SETWP: doc->CDSNControl |= CDSN_CTRL_WP; break; case NAND_CTL_CLRWP: doc->CDSNControl &= ~CDSN_CTRL_WP; break; } if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); WriteDOC(doc->CDSNControl, docptr, CDSNControl); /* 11.4.3 -- 4 NOPs after CSDNControl write */ DoC_Delay(doc, 4);}static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; /* * Must terminate write pipeline before sending any commands * to the device. */ if (command == NAND_CMD_PAGEPROG) { WriteDOC(0x00, docptr, Mplus_WritePipeTerm); WriteDOC(0x00, docptr, Mplus_WritePipeTerm); } /* * Write out the command to the device. */ if (command == NAND_CMD_SEQIN) { int readcmd; if (column >= mtd->oobblock) { /* OOB area */ column -= mtd->oobblock; readcmd = NAND_CMD_READOOB; } else if (column < 256) { /* First 256 bytes --> READ0 */ readcmd = NAND_CMD_READ0; } else { column -= 256; readcmd = NAND_CMD_READ1; } WriteDOC(readcmd, docptr, Mplus_FlashCmd); } WriteDOC(command, docptr, Mplus_FlashCmd); WriteDOC(0, docptr, Mplus_WritePipeTerm); WriteDOC(0, docptr, Mplus_WritePipeTerm); if (column != -1 || page_addr != -1) { /* Serially input address */ if (column != -1) { /* Adjust columns for 16 bit buswidth */ if (this->options & NAND_BUSWIDTH_16) column >>= 1; WriteDOC(column, docptr, Mplus_FlashAddress); } if (page_addr != -1) { WriteDOC((unsigned char) (page_addr & 0xff), docptr, Mplus_FlashAddress); WriteDOC((unsigned char) ((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress); /* One more address cycle for higher density devices */ if (this->chipsize & 0x0c000000) { WriteDOC((unsigned char) ((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress); printk("high density\n"); } } WriteDOC(0, docptr, Mplus_WritePipeTerm); WriteDOC(0, docptr, Mplus_WritePipeTerm); /* deassert ALE */ if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || command == NAND_CMD_READOOB || command == NAND_CMD_READID) WriteDOC(0, docptr, Mplus_FlashControl); } /* * program and erase have their own busy handlers * status and sequential in needs no delay */ switch (command) { case NAND_CMD_PAGEPROG: case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: case NAND_CMD_SEQIN: case NAND_CMD_STATUS: return; case NAND_CMD_RESET: if (this->dev_ready) break; udelay(this->chip_delay); WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); WriteDOC(0, docptr, Mplus_WritePipeTerm); WriteDOC(0, docptr, Mplus_WritePipeTerm); while ( !(this->read_byte(mtd) & 0x40)); return; /* This applies to read commands */ default: /* * If we don't have access to the busy pin, we apply the given * command delay */ if (!this->dev_ready) { udelay (this->chip_delay); return; } } /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ ndelay (100); /* wait until command is processed */ while (!this->dev_ready(mtd));}static int doc200x_dev_ready(struct mtd_info *mtd){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; if (DoC_is_MillenniumPlus(doc)) { /* 11.4.2 -- must NOP four times before checking FR/B# */ DoC_Delay(doc, 4); if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { if(debug) printk("not ready\n"); return 0; } if (debug)printk("was ready\n"); return 1; } else { /* 11.4.2 -- must NOP four times before checking FR/B# */ DoC_Delay(doc, 4); if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { if(debug) printk("not ready\n"); return 0; } /* 11.4.2 -- Must NOP twice if it's ready */ DoC_Delay(doc, 2); if (debug)printk("was ready\n"); return 1; }}static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip){ /* This is our last resort if we couldn't find or create a BBT. Just pretend all blocks are good. */ return 0;}static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode){ struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ switch(mode) { case NAND_ECC_READ: WriteDOC(DOC_ECC_RESET, docptr, ECCConf); WriteDOC(DOC_ECC_EN, docptr, ECCConf); break; case NAND_ECC_WRITE: WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -