📄 u-boot-lfc.patch
字号:
- 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);- WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);- break;- }-}--static void doc2001plus_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, Mplus_ECCConf);- WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);- break;- case NAND_ECC_WRITE:- WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);- WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);- break;- }-}--/* This code is only called on write */-static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,- unsigned char *ecc_code)-{- struct nand_chip *this = mtd->priv;- struct doc_priv *doc = this->priv;- void __iomem *docptr = doc->virtadr;- int i;- int emptymatch = 1;-- /* flush the pipeline */- if (DoC_is_2000(doc)) {- WriteDOC(doc->CDSNControl & ~CDSN_CTRL_FLASH_IO, docptr, CDSNControl);- WriteDOC(0, docptr, 2k_CDSN_IO);- WriteDOC(0, docptr, 2k_CDSN_IO);- WriteDOC(0, docptr, 2k_CDSN_IO);- WriteDOC(doc->CDSNControl, docptr, CDSNControl);- } else if (DoC_is_MillenniumPlus(doc)) {- WriteDOC(0, docptr, Mplus_NOP);- WriteDOC(0, docptr, Mplus_NOP);- WriteDOC(0, docptr, Mplus_NOP);- } else {- WriteDOC(0, docptr, NOP);- WriteDOC(0, docptr, NOP);- WriteDOC(0, docptr, NOP);- }-- for (i = 0; i < 6; i++) {- if (DoC_is_MillenniumPlus(doc))- ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i);- else- ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);- if (ecc_code[i] != empty_write_ecc[i])- emptymatch = 0;- }- if (DoC_is_MillenniumPlus(doc))- WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);- else- WriteDOC(DOC_ECC_DIS, docptr, ECCConf);-#if 0- /* If emptymatch=1, we might have an all-0xff data buffer. Check. */- if (emptymatch) {- /* Note: this somewhat expensive test should not be triggered- often. It could be optimized away by examining the data in- the writebuf routine, and remembering the result. */- for (i = 0; i < 512; i++) {- if (dat[i] == 0xff) continue;- emptymatch = 0;- break;- }- }- /* If emptymatch still =1, we do have an all-0xff data buffer.- Return all-0xff ecc value instead of the computed one, so- it'll look just like a freshly-erased page. */- if (emptymatch) memset(ecc_code, 0xff, 6);-#endif- return 0;-}--static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)-{- int i, ret = 0;- struct nand_chip *this = mtd->priv;- struct doc_priv *doc = this->priv;- void __iomem *docptr = doc->virtadr;- volatile u_char dummy;- int emptymatch = 1;-- /* flush the pipeline */- if (DoC_is_2000(doc)) {- dummy = ReadDOC(docptr, 2k_ECCStatus);- dummy = ReadDOC(docptr, 2k_ECCStatus);- dummy = ReadDOC(docptr, 2k_ECCStatus);- } else if (DoC_is_MillenniumPlus(doc)) {- dummy = ReadDOC(docptr, Mplus_ECCConf);- dummy = ReadDOC(docptr, Mplus_ECCConf);- dummy = ReadDOC(docptr, Mplus_ECCConf);- } else {- dummy = ReadDOC(docptr, ECCConf);- dummy = ReadDOC(docptr, ECCConf);- dummy = ReadDOC(docptr, ECCConf);- }-- /* Error occured ? */- if (dummy & 0x80) {- for (i = 0; i < 6; i++) {- if (DoC_is_MillenniumPlus(doc))- calc_ecc[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i);- else- calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);- if (calc_ecc[i] != empty_read_syndrome[i])- emptymatch = 0;- }- /* If emptymatch=1, the read syndrome is consistent with an- all-0xff data and stored ecc block. Check the stored ecc. */- if (emptymatch) {- for (i = 0; i < 6; i++) {- if (read_ecc[i] == 0xff) continue;- emptymatch = 0;- break;- }- }- /* If emptymatch still =1, check the data block. */- if (emptymatch) {- /* Note: this somewhat expensive test should not be triggered- often. It could be optimized away by examining the data in- the readbuf routine, and remembering the result. */- for (i = 0; i < 512; i++) {- if (dat[i] == 0xff) continue;- emptymatch = 0;- break;- }- }- /* If emptymatch still =1, this is almost certainly a freshly-- erased block, in which case the ECC will not come out right.- We'll suppress the error and tell the caller everything's- OK. Because it is. */- if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc);- if (ret > 0)- printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);- }- if (DoC_is_MillenniumPlus(doc))- WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);- else- WriteDOC(DOC_ECC_DIS, docptr, ECCConf);- if (no_ecc_failures && (ret == -1)) {- printk(KERN_ERR "suppressing ECC failure\n");- ret = 0;- }- return ret;-}--/*u_char mydatabuf[528]; */--static struct nand_oobinfo doc200x_oobinfo = {- .useecc = MTD_NANDECC_AUTOPLACE,- .eccbytes = 6,- .eccpos = {0, 1, 2, 3, 4, 5},- .oobfree = { {8, 8} }-};--/* Find the (I)NFTL Media Header, and optionally also the mirror media header.- On sucessful return, buf will contain a copy of the media header for- further processing. id is the string to scan for, and will presumably be- either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media- header. The page #s of the found media headers are placed in mh0_page and- mh1_page in the DOC private structure. */-static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,- const char *id, int findmirror)-{- struct nand_chip *this = mtd->priv;- struct doc_priv *doc = this->priv;- unsigned offs, end = (MAX_MEDIAHEADER_SCAN << this->phys_erase_shift);- int ret;- size_t retlen;-- end = min(end, mtd->size); /* paranoia */- for (offs = 0; offs < end; offs += mtd->erasesize) {- ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);- if (retlen != mtd->oobblock) continue;- if (ret) {- printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n",- offs);- }- if (memcmp(buf, id, 6)) continue;- printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs);- if (doc->mh0_page == -1) {- doc->mh0_page = offs >> this->page_shift;- if (!findmirror) return 1;- continue;- }- doc->mh1_page = offs >> this->page_shift;- return 2;- }- if (doc->mh0_page == -1) {- printk(KERN_WARNING "DiskOnChip %s Media Header not found.\n", id);- return 0;- }- /* Only one mediaheader was found. We want buf to contain a- mediaheader on return, so we'll have to re-read the one we found. */- offs = doc->mh0_page << this->page_shift;- ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);- if (retlen != mtd->oobblock) {- /* Insanity. Give up. */- printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n");- return 0;- }- return 1;-}--static inline int __init nftl_partscan(struct mtd_info *mtd,- struct mtd_partition *parts)-{- struct nand_chip *this = mtd->priv;- struct doc_priv *doc = this->priv;- int ret = 0;- u_char *buf;- struct NFTLMediaHeader *mh;- const unsigned psize = 1 << this->page_shift;- unsigned blocks, maxblocks;- int offs, numheaders;-- buf = kmalloc(mtd->oobblock, GFP_KERNEL);- if (!buf) {- printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");- return 0;- }- if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out;- mh = (struct NFTLMediaHeader *) buf;--/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */-/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */- printk(KERN_INFO " DataOrgID = %s\n"- " NumEraseUnits = %d\n"- " FirstPhysicalEUN = %d\n"- " FormattedSize = %d\n"- " UnitSizeFactor = %d\n",- mh->DataOrgID, mh->NumEraseUnits,- mh->FirstPhysicalEUN, mh->FormattedSize,- mh->UnitSizeFactor);-/*#endif */-- blocks = mtd->size >> this->phys_erase_shift;- maxblocks = min(32768U, mtd->erasesize - psize);-- if (mh->UnitSizeFactor == 0x00) {- /* Auto-determine UnitSizeFactor. The constraints are:- - There can be at most 32768 virtual blocks.- - There can be at most (virtual block size - page size)- virtual blocks (because MediaHeader+BBT must fit in 1).- */- mh->UnitSizeFactor = 0xff;- while (blocks > maxblocks) {- blocks >>= 1;- maxblocks = min(32768U, (maxblocks << 1) + psize);- mh->UnitSizeFactor--;- }- printk(KERN_WARNING "UnitSizeFactor=0x00 detected. Correct value is assumed to be 0x%02x.\n", mh->UnitSizeF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -