--- zzzz-none-000/linux-3.10.107/drivers/mtd/nand/diskonchip.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/mtd/nand/diskonchip.c 2021-02-04 17:41:59.000000000 +0000 @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -38,7 +38,7 @@ #define CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS 0 #endif -static unsigned long __initdata doc_locations[] = { +static unsigned long doc_locations[] __initdata = { #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) #ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, @@ -46,13 +46,13 @@ 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, -#else /* CONFIG_MTD_DOCPROBE_HIGH */ +#else 0xc8000, 0xca000, 0xcc000, 0xce000, 0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000, 0xe0000, 0xe2000, 0xe4000, 0xe6000, 0xe8000, 0xea000, 0xec000, 0xee000, -#endif /* CONFIG_MTD_DOCPROBE_HIGH */ +#endif #endif 0xffffffff }; @@ -69,6 +69,9 @@ int mh0_page; int mh1_page; struct mtd_info *nextdoc; + + /* Handle the last stage of initialization (BBT scan, partitioning) */ + int (*late_init)(struct mtd_info *mtd); }; /* This is the syndrome computed by the HW ecc generator upon reading an empty @@ -698,7 +701,8 @@ /* Serially input address */ if (column != -1) { /* Adjust columns for 16 bit buswidth */ - if (this->options & NAND_BUSWIDTH_16) + if (this->options & NAND_BUSWIDTH_16 && + !nand_opcode_8bits(command)) column >>= 1; WriteDOC(column, docptr, Mplus_FlashAddress); } @@ -794,7 +798,7 @@ } } -static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs) { /* This is our last resort if we couldn't find or create a BBT. Just pretend all blocks are good. */ @@ -1058,7 +1062,6 @@ buf = kmalloc(mtd->writesize, GFP_KERNEL); if (!buf) { - printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); return 0; } if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1))) @@ -1166,7 +1169,6 @@ buf = kmalloc(mtd->writesize, GFP_KERNEL); if (!buf) { - printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); return 0; } @@ -1295,14 +1297,11 @@ this->bbt_md = NULL; } - /* It's safe to set bd=NULL below because NAND_BBT_CREATE is not set. - At least as nand_bbt.c is currently written. */ - if ((ret = nand_scan_bbt(mtd, NULL))) + ret = this->scan_bbt(mtd); + if (ret) return ret; - mtd_device_register(mtd, NULL, 0); - if (!no_autopart) - mtd_device_register(mtd, parts, numparts); - return 0; + + return mtd_device_register(mtd, parts, no_autopart ? 0 : numparts); } static int __init inftl_scan_bbt(struct mtd_info *mtd) @@ -1345,10 +1344,10 @@ this->bbt_md->pattern = "TBB_SYSM"; } - /* It's safe to set bd=NULL below because NAND_BBT_CREATE is not set. - At least as nand_bbt.c is currently written. */ - if ((ret = nand_scan_bbt(mtd, NULL))) + ret = this->scan_bbt(mtd); + if (ret) return ret; + memset((char *)parts, 0, sizeof(parts)); numparts = inftl_partscan(mtd, parts); /* At least for now, require the INFTL Media Header. We could probably @@ -1356,10 +1355,7 @@ autopartitioning, but I want to give it more thought. */ if (!numparts) return -EIO; - mtd_device_register(mtd, NULL, 0); - if (!no_autopart) - mtd_device_register(mtd, parts, numparts); - return 0; + return mtd_device_register(mtd, parts, no_autopart ? 0 : numparts); } static inline int __init doc2000_init(struct mtd_info *mtd) @@ -1370,7 +1366,7 @@ this->read_byte = doc2000_read_byte; this->write_buf = doc2000_writebuf; this->read_buf = doc2000_readbuf; - this->scan_bbt = nftl_scan_bbt; + doc->late_init = nftl_scan_bbt; doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO; doc2000_count_chips(mtd); @@ -1397,13 +1393,13 @@ can have multiple chips. */ doc2000_count_chips(mtd); mtd->name = "DiskOnChip 2000 (INFTL Model)"; - this->scan_bbt = inftl_scan_bbt; + doc->late_init = inftl_scan_bbt; return (4 * doc->chips_per_floor); } else { /* Bog-standard Millennium */ doc->chips_per_floor = 1; mtd->name = "DiskOnChip Millennium"; - this->scan_bbt = nftl_scan_bbt; + doc->late_init = nftl_scan_bbt; return 1; } } @@ -1416,7 +1412,7 @@ this->read_byte = doc2001plus_read_byte; this->write_buf = doc2001plus_writebuf; this->read_buf = doc2001plus_readbuf; - this->scan_bbt = inftl_scan_bbt; + doc->late_init = inftl_scan_bbt; this->cmd_ctrl = NULL; this->select_chip = doc2001plus_select_chip; this->cmdfunc = doc2001plus_command; @@ -1440,10 +1436,13 @@ int reg, len, numchips; int ret = 0; + if (!request_mem_region(physadr, DOC_IOREMAP_LEN, "DiskOnChip")) + return -EBUSY; virtadr = ioremap(physadr, DOC_IOREMAP_LEN); if (!virtadr) { printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr); - return -EIO; + ret = -EIO; + goto error_ioremap; } /* It's not possible to cleanly detect the DiskOnChip - the @@ -1561,7 +1560,6 @@ sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); mtd = kzalloc(len, GFP_KERNEL); if (!mtd) { - printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); ret = -ENOMEM; goto fail; } @@ -1590,6 +1588,8 @@ nand->ecc.bytes = 6; nand->ecc.strength = 2; nand->bbt_options = NAND_BBT_USE_FLASH; + /* Skip the automatic BBT scan so we can run it manually */ + nand->options |= NAND_SKIP_BBTSCAN; doc->physadr = physadr; doc->virtadr = virtadr; @@ -1607,7 +1607,7 @@ else numchips = doc2001_init(mtd); - if ((ret = nand_scan(mtd, numchips))) { + if ((ret = nand_scan(mtd, numchips)) || (ret = doc->late_init(mtd))) { /* DBB note: i believe nand_release is necessary here, as buffers may have been allocated in nand_base. Check with Thomas. FIX ME! */ @@ -1629,6 +1629,10 @@ WriteDOC(save_control, virtadr, DOCControl); fail: iounmap(virtadr); + +error_ioremap: + release_mem_region(physadr, DOC_IOREMAP_LEN); + return ret; } @@ -1645,6 +1649,7 @@ nextmtd = doc->nextdoc; nand_release(mtd); iounmap(doc->virtadr); + release_mem_region(doc->physadr, DOC_IOREMAP_LEN); kfree(mtd); } }