Lines Matching +full:nand +full:- +full:no +full:- +full:ecc +full:- +full:engine

1 // SPDX-License-Identifier: GPL-2.0-only
14 * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de>
16 * Interface to generic NAND code for M-Systems DiskOnChip devices
79 /* This is the ecc value computed by the HW ecc generator upon writing an empty
85 #define DoC_is_MillenniumPlus(doc) ((doc)->ChipID == DOC_ChipID_DocMilPlus16 || (doc)->ChipID == DO…
86 #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
87 #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
115 /* Sector size for HW ECC */
129 * Reed-Solomon library code.
133 * of the generic Reed-Solomon library. tglx
135 static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) in doc_ecc_decode() argument
140 struct rs_codec *cd = rs->codec; in doc_ecc_decode()
143 /* Convert the ecc bytes into words */ in doc_ecc_decode()
144 ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8); in doc_ecc_decode()
145 ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6); in doc_ecc_decode()
146 ds[2] = ((ecc[2] & 0xf0) >> 4) | ((ecc[3] & 0x3f) << 4); in doc_ecc_decode()
147 ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2); in doc_ecc_decode()
148 parity = ecc[1]; in doc_ecc_decode()
161 tmp = cd->index_of[ds[j]]; in doc_ecc_decode()
163 s[i] ^= cd->alpha_to[rs_modnn(cd, tmp + (FCR + i) * j)]; in doc_ecc_decode()
169 syn[i] = rs_modnn(cd, cd->index_of[s[i]] + (NN - FCR - i)); in doc_ecc_decode()
184 int index, bitpos, pos = 1015 - errpos[i]; in doc_ecc_decode()
190 pos = 10 * (NB_DATA - 1 - pos) - 6; in doc_ecc_decode()
206 val = (uint8_t) (errval[i] << (8 - bitpos)); in doc_ecc_decode()
213 /* If the parity is wrong, no rescue possible */ in doc_ecc_decode()
214 return parity ? -EBADMSG : nerr; in doc_ecc_decode()
224 dummy = ReadDOC(doc->virtadr, NOP); in DoC_Delay()
226 dummy = ReadDOC(doc->virtadr, Mplus_NOP); in DoC_Delay()
228 dummy = ReadDOC(doc->virtadr, DOCStatus); in DoC_Delay()
238 void __iomem *docptr = doc->virtadr; in _DoC_WaitReady()
243 /* Out-of-line routine to wait for chip response */ in _DoC_WaitReady()
248 return -EIO; in _DoC_WaitReady()
257 return -EIO; in _DoC_WaitReady()
269 void __iomem *docptr = doc->virtadr; in DoC_WaitReady()
276 /* Call the out-of-line routine to wait */ in DoC_WaitReady()
282 /* Call the out-of-line routine to wait */ in DoC_WaitReady()
295 void __iomem *docptr = doc->virtadr; in doc2000_write_byte()
307 void __iomem *docptr = doc->virtadr; in doc2000_writebuf()
323 void __iomem *docptr = doc->virtadr; in doc2000_readbuf()
330 if (!doc->supports_32b_reads || in doc2000_readbuf()
341 * We need our own readid() here because it's called before the NAND chip
343 * pointer exception when dereferencing the NAND timings.
357 op.ninstrs--; in doc200x_readid()
359 this->controller->ops->exec_op(this, &op, false); in doc200x_readid()
373 if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) { in doc200x_ident_chip()
374 /* First chip probe. See if we get same results by 32-bit access */ in doc200x_ident_chip()
379 void __iomem *docptr = doc->virtadr; in doc200x_ident_chip()
386 doc->supports_32b_reads = true; in doc200x_ident_chip()
401 doc->chips_per_floor = 4; in doc2000_count_chips()
411 doc->chips_per_floor = i; in doc2000_count_chips()
418 void __iomem *docptr = doc->virtadr; in doc2001_write_byte()
428 void __iomem *docptr = doc->virtadr; in doc2001_writebuf()
440 void __iomem *docptr = doc->virtadr; in doc2001_readbuf()
446 for (i = 0; i < len - 1; i++) in doc2001_readbuf()
456 void __iomem *docptr = doc->virtadr; in doc2001plus_writebuf()
473 void __iomem *docptr = doc->virtadr; in doc2001plus_readbuf()
483 for (i = 0; i < len - 2; i++) { in doc2001plus_readbuf()
491 buf[len - 2] = ReadDOC(docptr, Mplus_LastDataRead); in doc2001plus_readbuf()
493 printk("%02x ", buf[len - 2]); in doc2001plus_readbuf()
496 buf[len - 1] = ReadDOC(docptr, Mplus_LastDataRead); in doc2001plus_readbuf()
498 printk("%02x ", buf[len - 1]); in doc2001plus_readbuf()
505 WriteDOC(value, doc->virtadr, CDSNControl); in doc200x_write_control()
506 /* 11.4.3 -- 4 NOPs after CSDNControl write */ in doc200x_write_control()
516 switch (instr->type) { in doc200x_exec_instr()
519 doc2000_write_byte(this, instr->ctx.cmd.opcode); in doc200x_exec_instr()
524 for (i = 0; i < instr->ctx.addr.naddrs; i++) { in doc200x_exec_instr()
525 u8 addr = instr->ctx.addr.addrs[i]; in doc200x_exec_instr()
537 doc2000_readbuf(this, instr->ctx.data.buf.in, in doc200x_exec_instr()
538 instr->ctx.data.len); in doc200x_exec_instr()
540 doc2001_readbuf(this, instr->ctx.data.buf.in, in doc200x_exec_instr()
541 instr->ctx.data.len); in doc200x_exec_instr()
547 doc2000_writebuf(this, instr->ctx.data.buf.out, in doc200x_exec_instr()
548 instr->ctx.data.len); in doc200x_exec_instr()
550 doc2001_writebuf(this, instr->ctx.data.buf.out, in doc200x_exec_instr()
551 instr->ctx.data.len); in doc200x_exec_instr()
559 if (instr->delay_ns) in doc200x_exec_instr()
560 ndelay(instr->delay_ns); in doc200x_exec_instr()
573 doc->curchip = op->cs % doc->chips_per_floor; in doc200x_exec_op()
574 doc->curfloor = op->cs / doc->chips_per_floor; in doc200x_exec_op()
576 WriteDOC(doc->curfloor, doc->virtadr, FloorSelect); in doc200x_exec_op()
577 WriteDOC(doc->curchip, doc->virtadr, CDSNDeviceSelect); in doc200x_exec_op()
582 for (i = 0; i < op->ninstrs; i++) in doc200x_exec_op()
583 doc200x_exec_instr(this, &op->instrs[i]); in doc200x_exec_op()
585 /* De-assert CE pin */ in doc200x_exec_op()
593 WriteDOC(0x00, doc->virtadr, Mplus_WritePipeTerm); in doc2001plus_write_pipe_term()
594 WriteDOC(0x00, doc->virtadr, Mplus_WritePipeTerm); in doc2001plus_write_pipe_term()
603 switch (instr->type) { in doc2001plus_exec_instr()
605 WriteDOC(instr->ctx.cmd.opcode, doc->virtadr, Mplus_FlashCmd); in doc2001plus_exec_instr()
610 for (i = 0; i < instr->ctx.addr.naddrs; i++) { in doc2001plus_exec_instr()
611 u8 addr = instr->ctx.addr.addrs[i]; in doc2001plus_exec_instr()
613 WriteDOC(addr, doc->virtadr, Mplus_FlashAddress); in doc2001plus_exec_instr()
617 WriteDOC(0, doc->virtadr, Mplus_FlashControl); in doc2001plus_exec_instr()
621 doc2001plus_readbuf(this, instr->ctx.data.buf.in, in doc2001plus_exec_instr()
622 instr->ctx.data.len); in doc2001plus_exec_instr()
625 doc2001plus_writebuf(this, instr->ctx.data.buf.out, in doc2001plus_exec_instr()
626 instr->ctx.data.len); in doc2001plus_exec_instr()
634 if (instr->delay_ns) in doc2001plus_exec_instr()
635 ndelay(instr->delay_ns); in doc2001plus_exec_instr()
648 doc->curchip = op->cs % doc->chips_per_floor; in doc2001plus_exec_op()
649 doc->curfloor = op->cs / doc->chips_per_floor; in doc2001plus_exec_op()
652 WriteDOC(DOC_FLASH_CE, doc->virtadr, Mplus_FlashSelect); in doc2001plus_exec_op()
654 for (i = 0; i < op->ninstrs; i++) in doc2001plus_exec_op()
655 doc2001plus_exec_instr(this, &op->instrs[i]); in doc2001plus_exec_op()
657 /* De-assert ChipEnable */ in doc2001plus_exec_op()
658 WriteDOC(0, doc->virtadr, Mplus_FlashSelect); in doc2001plus_exec_op()
666 void __iomem *docptr = doc->virtadr; in doc200x_enable_hwecc()
668 /* Prime the ECC engine */ in doc200x_enable_hwecc()
684 void __iomem *docptr = doc->virtadr; in doc2001plus_enable_hwecc()
686 /* Prime the ECC engine */ in doc2001plus_enable_hwecc()
704 void __iomem *docptr = doc->virtadr; in doc200x_calculate_ecc()
710 WriteDOC(doc->CDSNControl & ~CDSN_CTRL_FLASH_IO, docptr, CDSNControl); in doc200x_calculate_ecc()
714 WriteDOC(doc->CDSNControl, docptr, CDSNControl); in doc200x_calculate_ecc()
738 /* If emptymatch=1, we might have an all-0xff data buffer. Check. */ in doc200x_calculate_ecc()
750 /* If emptymatch still =1, we do have an all-0xff data buffer. in doc200x_calculate_ecc()
751 Return all-0xff ecc value instead of the computed one, so in doc200x_calculate_ecc()
752 it'll look just like a freshly-erased page. */ in doc200x_calculate_ecc()
764 void __iomem *docptr = doc->virtadr; in doc200x_correct_data()
792 ret = doc_ecc_decode(doc->rs_decoder, dat, calc_ecc); in doc200x_correct_data()
802 pr_err("suppressing ECC failure\n"); in doc200x_correct_data()
814 return -ERANGE; in doc200x_ooblayout_ecc()
816 oobregion->offset = 0; in doc200x_ooblayout_ecc()
817 oobregion->length = 6; in doc200x_ooblayout_ecc()
826 return -ERANGE; in doc200x_ooblayout_free()
829 * The strange out-of-order free bytes definition is a (possibly in doc200x_ooblayout_free()
838 * free bytes position must be able to handle out-of-order segments. in doc200x_ooblayout_free()
841 oobregion->offset = 8; in doc200x_ooblayout_free()
842 oobregion->length = 8; in doc200x_ooblayout_free()
844 oobregion->offset = 6; in doc200x_ooblayout_free()
845 oobregion->length = 2; in doc200x_ooblayout_free()
852 .ecc = doc200x_ooblayout_ecc,
870 for (offs = 0; offs < mtd->size; offs += mtd->erasesize) { in find_media_headers()
871 ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf); in find_media_headers()
872 if (retlen != mtd->writesize) in find_media_headers()
875 pr_warn("ECC error scanning DOC at 0x%x\n", offs); in find_media_headers()
880 if (doc->mh0_page == -1) { in find_media_headers()
881 doc->mh0_page = offs >> this->page_shift; in find_media_headers()
886 doc->mh1_page = offs >> this->page_shift; in find_media_headers()
889 if (doc->mh0_page == -1) { in find_media_headers()
894 mediaheader on return, so we'll have to re-read the one we found. */ in find_media_headers()
895 offs = doc->mh0_page << this->page_shift; in find_media_headers()
896 ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf); in find_media_headers()
897 if (retlen != mtd->writesize) { in find_media_headers()
913 const unsigned psize = 1 << this->page_shift; in nftl_partscan()
918 memorg = nanddev_get_memorg(&this->base); in nftl_partscan()
920 buf = kmalloc(mtd->writesize, GFP_KERNEL); in nftl_partscan()
928 le16_to_cpus(&mh->NumEraseUnits); in nftl_partscan()
929 le16_to_cpus(&mh->FirstPhysicalEUN); in nftl_partscan()
930 le32_to_cpus(&mh->FormattedSize); in nftl_partscan()
937 mh->DataOrgID, mh->NumEraseUnits, in nftl_partscan()
938 mh->FirstPhysicalEUN, mh->FormattedSize, in nftl_partscan()
939 mh->UnitSizeFactor); in nftl_partscan()
941 blocks = mtd->size >> this->phys_erase_shift; in nftl_partscan()
942 maxblocks = min(32768U, mtd->erasesize - psize); in nftl_partscan()
944 if (mh->UnitSizeFactor == 0x00) { in nftl_partscan()
945 /* Auto-determine UnitSizeFactor. The constraints are: in nftl_partscan()
946 - There can be at most 32768 virtual blocks. in nftl_partscan()
947 - There can be at most (virtual block size - page size) in nftl_partscan()
950 mh->UnitSizeFactor = 0xff; in nftl_partscan()
954 mh->UnitSizeFactor--; in nftl_partscan()
956 …pr_warn("UnitSizeFactor=0x00 detected. Correct value is assumed to be 0x%02x.\n", mh->UnitSizeFac… in nftl_partscan()
959 /* NOTE: The lines below modify internal variables of the NAND and MTD in nftl_partscan()
963 implementation of the NAND layer. */ in nftl_partscan()
964 if (mh->UnitSizeFactor != 0xff) { in nftl_partscan()
965 this->bbt_erase_shift += (0xff - mh->UnitSizeFactor); in nftl_partscan()
966 memorg->pages_per_eraseblock <<= (0xff - mh->UnitSizeFactor); in nftl_partscan()
967 mtd->erasesize <<= (0xff - mh->UnitSizeFactor); in nftl_partscan()
968 pr_info("Setting virtual erase size to %d\n", mtd->erasesize); in nftl_partscan()
969 blocks = mtd->size >> this->bbt_erase_shift; in nftl_partscan()
970 maxblocks = min(32768U, mtd->erasesize - psize); in nftl_partscan()
974 …pr_err("UnitSizeFactor of 0x%02x is inconsistent with device size. Aborting.\n", mh->UnitSizeFact… in nftl_partscan()
979 offs = max(doc->mh0_page, doc->mh1_page); in nftl_partscan()
980 offs <<= this->page_shift; in nftl_partscan()
981 offs += mtd->erasesize; in nftl_partscan()
992 parts[numparts].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift; in nftl_partscan()
997 if (offs < mtd->size) { in nftl_partscan()
1000 parts[numparts].size = mtd->size - offs; in nftl_partscan()
1010 /* This is a stripped-down copy of the code in inftlmount.c */
1023 int end = mtd->size; in inftl_partscan()
1026 end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift); in inftl_partscan()
1028 buf = kmalloc(mtd->writesize, GFP_KERNEL); in inftl_partscan()
1035 doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift); in inftl_partscan()
1038 le32_to_cpus(&mh->NoOfBootImageBlocks); in inftl_partscan()
1039 le32_to_cpus(&mh->NoOfBinaryPartitions); in inftl_partscan()
1040 le32_to_cpus(&mh->NoOfBDTLPartitions); in inftl_partscan()
1041 le32_to_cpus(&mh->BlockMultiplierBits); in inftl_partscan()
1042 le32_to_cpus(&mh->FormatFlags); in inftl_partscan()
1043 le32_to_cpus(&mh->PercentUsed); in inftl_partscan()
1053 mh->bootRecordID, mh->NoOfBootImageBlocks, in inftl_partscan()
1054 mh->NoOfBinaryPartitions, in inftl_partscan()
1055 mh->NoOfBDTLPartitions, in inftl_partscan()
1056 mh->BlockMultiplierBits, mh->FormatFlags, in inftl_partscan()
1057 ((unsigned char *) &mh->OsakVersion)[0] & 0xf, in inftl_partscan()
1058 ((unsigned char *) &mh->OsakVersion)[1] & 0xf, in inftl_partscan()
1059 ((unsigned char *) &mh->OsakVersion)[2] & 0xf, in inftl_partscan()
1060 ((unsigned char *) &mh->OsakVersion)[3] & 0xf, in inftl_partscan()
1061 mh->PercentUsed); in inftl_partscan()
1063 vshift = this->phys_erase_shift + mh->BlockMultiplierBits; in inftl_partscan()
1065 blocks = mtd->size >> vshift; in inftl_partscan()
1067 …pr_err("BlockMultiplierBits=%d is inconsistent with device size. Aborting.\n", mh->BlockMultiplie… in inftl_partscan()
1071 blocks = doc->chips_per_floor << (this->chip_shift - this->phys_erase_shift); in inftl_partscan()
1072 if (inftl_bbt_write && (blocks > mtd->erasesize)) { in inftl_partscan()
1079 ip = &(mh->Partitions[i]); in inftl_partscan()
1080 le32_to_cpus(&ip->virtualUnits); in inftl_partscan()
1081 le32_to_cpus(&ip->firstUnit); in inftl_partscan()
1082 le32_to_cpus(&ip->lastUnit); in inftl_partscan()
1083 le32_to_cpus(&ip->flags); in inftl_partscan()
1084 le32_to_cpus(&ip->spareUnits); in inftl_partscan()
1085 le32_to_cpus(&ip->Reserved0); in inftl_partscan()
1087 pr_info(" PARTITION[%d] ->\n" in inftl_partscan()
1093 i, ip->virtualUnits, ip->firstUnit, in inftl_partscan()
1094 ip->lastUnit, ip->flags, in inftl_partscan()
1095 ip->spareUnits); in inftl_partscan()
1098 (i == 0) && (ip->firstUnit > 0)) { in inftl_partscan()
1101 parts[0].size = mtd->erasesize * ip->firstUnit; in inftl_partscan()
1105 if (ip->flags & INFTL_BINARY) in inftl_partscan()
1109 parts[numparts].offset = ip->firstUnit << vshift; in inftl_partscan()
1110 parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift; in inftl_partscan()
1112 if (ip->lastUnit > lastvunit) in inftl_partscan()
1113 lastvunit = ip->lastUnit; in inftl_partscan()
1114 if (ip->flags & INFTL_LAST) in inftl_partscan()
1121 parts[numparts].size = end - parts[numparts].offset; in inftl_partscan()
1142 return -EIO; in nftl_scan_bbt()
1143 this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT | in nftl_scan_bbt()
1146 this->bbt_td->veroffs = 7; in nftl_scan_bbt()
1147 this->bbt_td->pages[0] = doc->mh0_page + 1; in nftl_scan_bbt()
1148 if (doc->mh1_page != -1) { in nftl_scan_bbt()
1149 this->bbt_md->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT | in nftl_scan_bbt()
1152 this->bbt_md->veroffs = 7; in nftl_scan_bbt()
1153 this->bbt_md->pages[0] = doc->mh1_page + 1; in nftl_scan_bbt()
1155 this->bbt_md = NULL; in nftl_scan_bbt()
1172 if (nanddev_ntargets(&this->base) > doc->chips_per_floor) { in inftl_scan_bbt()
1173 pr_err("Multi-floor INFTL devices not yet supported.\n"); in inftl_scan_bbt()
1174 return -EIO; in inftl_scan_bbt()
1178 this->bbt_td->options = NAND_BBT_2BIT | NAND_BBT_ABSPAGE; in inftl_scan_bbt()
1180 this->bbt_td->options |= NAND_BBT_WRITE; in inftl_scan_bbt()
1181 this->bbt_td->pages[0] = 2; in inftl_scan_bbt()
1182 this->bbt_md = NULL; in inftl_scan_bbt()
1184 this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION; in inftl_scan_bbt()
1186 this->bbt_td->options |= NAND_BBT_WRITE; in inftl_scan_bbt()
1187 this->bbt_td->offs = 8; in inftl_scan_bbt()
1188 this->bbt_td->len = 8; in inftl_scan_bbt()
1189 this->bbt_td->veroffs = 7; in inftl_scan_bbt()
1190 this->bbt_td->maxblocks = INFTL_BBT_RESERVED_BLOCKS; in inftl_scan_bbt()
1191 this->bbt_td->reserved_block_code = 0x01; in inftl_scan_bbt()
1192 this->bbt_td->pattern = "MSYS_BBT"; in inftl_scan_bbt()
1194 this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION; in inftl_scan_bbt()
1196 this->bbt_md->options |= NAND_BBT_WRITE; in inftl_scan_bbt()
1197 this->bbt_md->offs = 8; in inftl_scan_bbt()
1198 this->bbt_md->len = 8; in inftl_scan_bbt()
1199 this->bbt_md->veroffs = 7; in inftl_scan_bbt()
1200 this->bbt_md->maxblocks = INFTL_BBT_RESERVED_BLOCKS; in inftl_scan_bbt()
1201 this->bbt_md->reserved_block_code = 0x01; in inftl_scan_bbt()
1202 this->bbt_md->pattern = "TBB_SYSM"; in inftl_scan_bbt()
1212 do without it for non-INFTL use, since all it gives us is in inftl_scan_bbt()
1215 return -EIO; in inftl_scan_bbt()
1224 doc->late_init = nftl_scan_bbt; in doc2000_init()
1226 doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO; in doc2000_init()
1228 mtd->name = "DiskOnChip 2000 (NFTL Model)"; in doc2000_init()
1229 return (4 * doc->chips_per_floor); in doc2000_init()
1237 ReadDOC(doc->virtadr, ChipID); in doc2001_init()
1238 ReadDOC(doc->virtadr, ChipID); in doc2001_init()
1239 ReadDOC(doc->virtadr, ChipID); in doc2001_init()
1240 if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) { in doc2001_init()
1246 mtd->name = "DiskOnChip 2000 (INFTL Model)"; in doc2001_init()
1247 doc->late_init = inftl_scan_bbt; in doc2001_init()
1248 return (4 * doc->chips_per_floor); in doc2001_init()
1250 /* Bog-standard Millennium */ in doc2001_init()
1251 doc->chips_per_floor = 1; in doc2001_init()
1252 mtd->name = "DiskOnChip Millennium"; in doc2001_init()
1253 doc->late_init = nftl_scan_bbt; in doc2001_init()
1263 doc->late_init = inftl_scan_bbt; in doc2001plus_init()
1264 this->ecc.hwctl = doc2001plus_enable_hwecc; in doc2001plus_init()
1266 doc->chips_per_floor = 1; in doc2001plus_init()
1267 mtd->name = "DiskOnChip Millennium Plus"; in doc2001plus_init()
1274 if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) in doc200x_attach_chip()
1277 chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED; in doc200x_attach_chip()
1278 chip->ecc.size = 512; in doc200x_attach_chip()
1279 chip->ecc.bytes = 6; in doc200x_attach_chip()
1280 chip->ecc.strength = 2; in doc200x_attach_chip()
1281 chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; in doc200x_attach_chip()
1282 chip->ecc.hwctl = doc200x_enable_hwecc; in doc200x_attach_chip()
1283 chip->ecc.calculate = doc200x_calculate_ecc; in doc200x_attach_chip()
1284 chip->ecc.correct = doc200x_correct_data; in doc200x_attach_chip()
1301 struct nand_chip *nand = NULL; in doc_probe() local
1312 return -EBUSY; in doc_probe()
1317 ret = -EIO; in doc_probe()
1321 /* It's not possible to cleanly detect the DiskOnChip - the in doc_probe()
1378 ret = -ENODEV; in doc_probe()
1384 ret = -ENODEV; in doc_probe()
1387 /* Check the TOGGLE bit in the ECC register */ in doc_probe()
1393 ret = -ENODEV; in doc_probe()
1397 for (mtd = doclist; mtd; mtd = doc->nextdoc) { in doc_probe()
1400 nand = mtd_to_nand(mtd); in doc_probe()
1401 doc = nand_get_controller_data(nand); in doc_probe()
1407 oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); in doc_probe()
1410 oldval = ReadDOC(doc->virtadr, AliasResolution); in doc_probe()
1417 oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); in doc_probe()
1421 oldval = ReadDOC(doc->virtadr, AliasResolution); in doc_probe()
1427 doc->physadr, physadr); in doc_probe()
1436 nand = kzalloc(len, GFP_KERNEL); in doc_probe()
1437 if (!nand) { in doc_probe()
1438 ret = -ENOMEM; in doc_probe()
1451 doc = (struct doc_priv *) (nand + 1); in doc_probe()
1452 doc->rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); in doc_probe()
1453 if (!doc->rs_decoder) { in doc_probe()
1455 ret = -ENOMEM; in doc_probe()
1459 nand_controller_init(&doc->base); in doc_probe()
1461 doc->base.ops = &doc2001plus_ops; in doc_probe()
1463 doc->base.ops = &doc200x_ops; in doc_probe()
1465 mtd = nand_to_mtd(nand); in doc_probe()
1466 nand->bbt_td = (struct nand_bbt_descr *) (doc + 1); in doc_probe()
1467 nand->bbt_md = nand->bbt_td + 1; in doc_probe()
1469 mtd->owner = THIS_MODULE; in doc_probe()
1472 nand->controller = &doc->base; in doc_probe()
1473 nand_set_controller_data(nand, doc); in doc_probe()
1474 nand->bbt_options = NAND_BBT_USE_FLASH; in doc_probe()
1476 nand->options |= NAND_SKIP_BBTSCAN | NAND_NO_BBM_QUIRK; in doc_probe()
1478 doc->physadr = physadr; in doc_probe()
1479 doc->virtadr = virtadr; in doc_probe()
1480 doc->ChipID = ChipID; in doc_probe()
1481 doc->curfloor = -1; in doc_probe()
1482 doc->curchip = -1; in doc_probe()
1483 doc->mh0_page = -1; in doc_probe()
1484 doc->mh1_page = -1; in doc_probe()
1485 doc->nextdoc = doclist; in doc_probe()
1494 if ((ret = nand_scan(nand, numchips)) || (ret = doc->late_init(mtd))) { in doc_probe()
1498 nand_cleanup(nand); in doc_probe()
1512 free_rs(doc->rs_decoder); in doc_probe()
1513 kfree(nand); in doc_probe()
1525 struct nand_chip *nand; in release_nanddoc() local
1530 nand = mtd_to_nand(mtd); in release_nanddoc()
1531 doc = nand_get_controller_data(nand); in release_nanddoc()
1533 nextmtd = doc->nextdoc; in release_nanddoc()
1536 nand_cleanup(nand); in release_nanddoc()
1537 iounmap(doc->virtadr); in release_nanddoc()
1538 release_mem_region(doc->physadr, DOC_IOREMAP_LEN); in release_nanddoc()
1539 free_rs(doc->rs_decoder); in release_nanddoc()
1540 kfree(nand); in release_nanddoc()
1559 /* No banner message any more. Print a message if no DiskOnChip in init_nanddoc()
1562 pr_info("No valid DiskOnChip devices found\n"); in init_nanddoc()
1563 ret = -ENODEV; in init_nanddoc()
1570 /* Cleanup the nand/DoC resources */ in cleanup_nanddoc()
1579 MODULE_DESCRIPTION("M-Systems DiskOnChip 2000, Millennium and Millennium Plus device driver");