📄 doc2001plus.c
字号:
DoC_CheckASIC(docptr); /* Find the chip which is to be used and select it */ if (this->curfloor != mychip->floor) { DoC_SelectFloor(docptr, mychip->floor); DoC_SelectChip(docptr, mychip->chip); } else if (this->curchip != mychip->chip) { DoC_SelectChip(docptr, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); /* Reset the chip, see Software Requirement 11.4 item 1. */ DoC_Command(docptr, NAND_CMD_RESET, 0); DoC_WaitReady(docptr); /* Set device to appropriate plane of flash */ fto = to; WriteDOC(DoC_GetDataOffset(mtd, &fto), docptr, Mplus_FlashCmd); /* On interleaved devices the flags for 2nd half 512 are before data */ if (eccbuf && before) fto -= 2; /* issue the Serial Data In command to initial the Page Program process */ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); DoC_Address(this, 3, fto, 0x00, 0x00); /* Disable the ECC engine */ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); if (eccbuf) { if (before) { /* Write the block status BLOCK_USED (0x5555) */ WriteDOC(0x55, docptr, Mil_CDSN_IO); WriteDOC(0x55, docptr, Mil_CDSN_IO); } /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf); } MemWriteDOC(docptr, (unsigned char *) buf, len); if (eccbuf) { /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */ DoC_Delay(docptr, 3); /* Read the ECC data through the DiskOnChip ECC logic */ for (i = 0; i < 6; i++) eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); /* disable the ECC engine */ WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); /* Write the ECC data to flash */ MemWriteDOC(docptr, eccbuf, 6); if (!before) { /* Write the block status BLOCK_USED (0x5555) */ WriteDOC(0x55, docptr, Mil_CDSN_IO+6); WriteDOC(0x55, docptr, Mil_CDSN_IO+7); }#ifdef PSYCHO_DEBUG printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], eccbuf[4], eccbuf[5]);#endif } WriteDOC(0x00, docptr, Mplus_WritePipeTerm); WriteDOC(0x00, docptr, Mplus_WritePipeTerm); /* Commit the Page Program command and wait for ready see Software Requirement 11.4 item 1.*/ DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); DoC_WaitReady(docptr); /* Read the status of the flash device through CDSN IO register see Software Requirement 11.4 item 5.*/ DoC_Command(docptr, NAND_CMD_STATUS, 0); dummy = ReadDOC(docptr, Mplus_ReadPipeInit); dummy = ReadDOC(docptr, Mplus_ReadPipeInit); DoC_Delay(docptr, 2); if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { printk("MTD: Error 0x%x programming at 0x%x\n", dummy, (int)to); /* Error in programming FIXME: implement Bad Block Replacement (in nftl.c ??) */ *retlen = 0; ret = -EIO; } dummy = ReadDOC(docptr, Mplus_LastDataRead); /* Disable flash internally */ WriteDOC(0, docptr, Mplus_FlashSelect); /* Let the caller know we completed it */ *retlen = len; return ret;}static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf){ loff_t fofs, base; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; unsigned long docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; size_t i, size, got, want; DoC_CheckASIC(docptr); /* Find the chip which is to be used and select it */ if (this->curfloor != mychip->floor) { DoC_SelectFloor(docptr, mychip->floor); DoC_SelectChip(docptr, mychip->chip); } else if (this->curchip != mychip->chip) { DoC_SelectChip(docptr, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect); /* disable the ECC engine */ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); DoC_WaitReady(docptr); /* Maximum of 16 bytes in the OOB region, so limit read to that */ if (len > 16) len = 16; got = 0; want = len; for (i = 0; ((i < 3) && (want > 0)); i++) { /* Figure out which region we are accessing... */ fofs = ofs; base = ofs & 0xf; if (!this->interleave) { DoC_Command(docptr, NAND_CMD_READOOB, 0); size = 16 - base; } else if (base < 6) { DoC_Command(docptr, DoC_GetECCOffset(mtd, &fofs), 0); size = 6 - base; } else if (base < 8) { DoC_Command(docptr, DoC_GetFlagsOffset(mtd, &fofs), 0); size = 8 - base; } else { DoC_Command(docptr, DoC_GetHdrOffset(mtd, &fofs), 0); size = 16 - base; } if (size > want) size = want; /* Issue read command */ DoC_Address(this, 3, fofs, 0, 0x00); WriteDOC(0, docptr, Mplus_FlashControl); DoC_WaitReady(docptr); ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit); MemReadDOC(docptr, &buf[got], size - 2); buf[got + size - 2] = ReadDOC(docptr, Mplus_LastDataRead); buf[got + size - 1] = ReadDOC(docptr, Mplus_LastDataRead); ofs += size; got += size; want -= size; } /* Disable flash internally */ WriteDOC(0, docptr, Mplus_FlashSelect); *retlen = len; return 0;}static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf){ volatile char dummy; loff_t fofs, base; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; unsigned long docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; size_t i, size, got, want; int ret = 0; DoC_CheckASIC(docptr); /* Find the chip which is to be used and select it */ if (this->curfloor != mychip->floor) { DoC_SelectFloor(docptr, mychip->floor); DoC_SelectChip(docptr, mychip->chip); } else if (this->curchip != mychip->chip) { DoC_SelectChip(docptr, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); /* Maximum of 16 bytes in the OOB region, so limit write to that */ if (len > 16) len = 16; got = 0; want = len; for (i = 0; ((i < 3) && (want > 0)); i++) { /* Reset the chip, see Software Requirement 11.4 item 1. */ DoC_Command(docptr, NAND_CMD_RESET, 0); DoC_WaitReady(docptr); /* Figure out which region we are accessing... */ fofs = ofs; base = ofs & 0x0f; if (!this->interleave) { WriteDOC(NAND_CMD_READOOB, docptr, Mplus_FlashCmd); size = 16 - base; } else if (base < 6) { WriteDOC(DoC_GetECCOffset(mtd, &fofs), docptr, Mplus_FlashCmd); size = 6 - base; } else if (base < 8) { WriteDOC(DoC_GetFlagsOffset(mtd, &fofs), docptr, Mplus_FlashCmd); size = 8 - base; } else { WriteDOC(DoC_GetHdrOffset(mtd, &fofs), docptr, Mplus_FlashCmd); size = 16 - base; } if (size > want) size = want; /* Issue the Serial Data In command to initial the Page Program process */ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); DoC_Address(this, 3, fofs, 0, 0x00); /* Disable the ECC engine */ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); /* Write the data via the internal pipeline through CDSN IO register, see Pipelined Write Operations 11.2 */ MemWriteDOC(docptr, (unsigned char *) &buf[got], size); WriteDOC(0x00, docptr, Mplus_WritePipeTerm); WriteDOC(0x00, docptr, Mplus_WritePipeTerm); /* Commit the Page Program command and wait for ready see Software Requirement 11.4 item 1.*/ DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); DoC_WaitReady(docptr); /* Read the status of the flash device through CDSN IO register see Software Requirement 11.4 item 5.*/ DoC_Command(docptr, NAND_CMD_STATUS, 0x00); dummy = ReadDOC(docptr, Mplus_ReadPipeInit); dummy = ReadDOC(docptr, Mplus_ReadPipeInit); DoC_Delay(docptr, 2); if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { printk("MTD: Error 0x%x programming oob at 0x%x\n", dummy, (int)ofs); /* FIXME: implement Bad Block Replacement */ *retlen = 0; ret = -EIO; } dummy = ReadDOC(docptr, Mplus_LastDataRead); ofs += size; got += size; want -= size; } /* Disable flash internally */ WriteDOC(0, docptr, Mplus_FlashSelect); *retlen = len; return ret;}int doc_erase(struct mtd_info *mtd, struct erase_info *instr){ volatile char dummy; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; __u32 ofs = instr->addr; __u32 len = instr->len; unsigned long docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; DoC_CheckASIC(docptr); if (len != mtd->erasesize) printk(KERN_WARNING "MTD: Erase not right size (%x != %x)n", len, mtd->erasesize); /* Find the chip which is to be used and select it */ if (this->curfloor != mychip->floor) { DoC_SelectFloor(docptr, mychip->floor); DoC_SelectChip(docptr, mychip->chip); } else if (this->curchip != mychip->chip) { DoC_SelectChip(docptr, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; instr->state = MTD_ERASE_PENDING; /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); DoC_Command(docptr, NAND_CMD_RESET, 0x00); DoC_WaitReady(docptr); DoC_Command(docptr, NAND_CMD_ERASE1, 0); DoC_Address(this, 2, ofs, 0, 0x00); DoC_Command(docptr, NAND_CMD_ERASE2, 0); DoC_WaitReady(docptr); instr->state = MTD_ERASING; /* Read the status of the flash device through CDSN IO register see Software Requirement 11.4 item 5. */ DoC_Command(docptr, NAND_CMD_STATUS, 0); dummy = ReadDOC(docptr, Mplus_ReadPipeInit); dummy = ReadDOC(docptr, Mplus_ReadPipeInit); if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { printk("MTD: Error 0x%x erasing at 0x%x\n", dummy, ofs); /* FIXME: implement Bad Block Replacement (in nftl.c ??) */ instr->state = MTD_ERASE_FAILED; } else { instr->state = MTD_ERASE_DONE; } dummy = ReadDOC(docptr, Mplus_LastDataRead); /* Disable flash internally */ WriteDOC(0, docptr, Mplus_FlashSelect); mtd_erase_callback(instr); return 0;}/**************************************************************************** * * Module stuff * ****************************************************************************/int __init init_doc2001plus(void){ inter_module_register(im_name, THIS_MODULE, &DoCMilPlus_init); return 0;}static void __exit cleanup_doc2001plus(void){ struct mtd_info *mtd; struct DiskOnChip *this; while ((mtd=docmilpluslist)) { this = (struct DiskOnChip *)mtd->priv; docmilpluslist = this->nextdoc; del_mtd_device(mtd); iounmap((void *)this->virtadr); kfree(this->chips); kfree(mtd); } inter_module_unregister(im_name);}module_exit(cleanup_doc2001plus);module_init(init_doc2001plus);MODULE_LICENSE("GPL");MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com> et al.");MODULE_DESCRIPTION("Driver for DiskOnChip Millennium Plus");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -