Skip to content
Snippets Groups Projects
nand_base.c 70.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • static void single_erase_cmd(struct mtd_info *mtd, int page)
    
    	struct nand_chip *chip = mtd->priv;
    
    	/* Send commands to erase a block */
    
    	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
    	chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
    
    }
    
    /**
     * multi_erease_cmd - [GENERIC] AND specific block erase command function
     * @mtd:	MTD device structure
     * @page:	the page address of the block which will be erased
     *
     * AND multi block erase command function
     * Erase 4 consecutive blocks
     */
    
    static void multi_erase_cmd(struct mtd_info *mtd, int page)
    
    	struct nand_chip *chip = mtd->priv;
    
    	/* Send commands to erase a block */
    
    	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
    	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
    	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
    	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
    	chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
    
    }
    
    /**
     * nand_erase - [MTD Interface] erase block(s)
     * @mtd:	MTD device structure
     * @instr:	erase instruction
     *
     * Erase one ore more blocks
     */
    
    static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
    
    	return nand_erase_nand(mtd, instr, 0);
    
    #define BBT_PAGE_MASK	0xffffff3f
    
     * nand_erase_nand - [Internal] erase block(s)
    
     * @mtd:	MTD device structure
     * @instr:	erase instruction
     * @allowbbt:	allow erasing the bbt area
     *
     * Erase one ore more blocks
     */
    
    int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
    		    int allowbbt)
    
    {
    	int page, len, status, pages_per_block, ret, chipnr;
    
    	struct nand_chip *chip = mtd->priv;
    	int rewrite_bbt[NAND_MAX_CHIPS]={0};
    	unsigned int bbt_masked_page = 0xffffffff;
    
    	MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
    	          (unsigned int) instr->addr, (unsigned int) instr->len);
    
    
    	/* Start address must align on block boundary */
    
    	if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
    
    		MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
    
    		return -EINVAL;
    	}
    
    	/* Length must align on block boundary */
    
    	if (instr->len & ((1 << chip->phys_erase_shift) - 1)) {
    
    		MTDDEBUG (MTD_DEBUG_LEVEL0,
    		          "nand_erase: Length not block aligned\n");
    
    		return -EINVAL;
    	}
    
    	/* Do not allow erase past end of device */
    	if ((instr->len + instr->addr) > mtd->size) {
    
    		MTDDEBUG (MTD_DEBUG_LEVEL0,
    		          "nand_erase: Erase past end of device\n");
    
    		return -EINVAL;
    	}
    
    	instr->fail_addr = 0xffffffff;
    
    	/* Grab the lock and see if the device is available */
    
    	nand_get_device(chip, mtd, FL_ERASING);
    
    	page = (int)(instr->addr >> chip->page_shift);
    	chipnr = (int)(instr->addr >> chip->chip_shift);
    
    
    	/* Calculate pages in each block */
    
    	pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
    
    	/* Select the NAND device */
    
    	chip->select_chip(mtd, chipnr);
    
    
    	/* Check, if it is write protected */
    	if (nand_check_wp(mtd)) {
    
    		MTDDEBUG (MTD_DEBUG_LEVEL0,
    		          "nand_erase: Device is write protected!!!\n");
    
    		instr->state = MTD_ERASE_FAILED;
    		goto erase_exit;
    	}
    
    
    	/*
    	 * If BBT requires refresh, set the BBT page mask to see if the BBT
    	 * should be rewritten. Otherwise the mask is set to 0xffffffff which
    	 * can not be matched. This is also done when the bbt is actually
    	 * erased to avoid recusrsive updates
    	 */
    	if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
    		bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
    
    
    	/* Loop through the pages */
    	len = instr->len;
    
    	instr->state = MTD_ERASING;
    
    	while (len) {
    
    		/*
    		 * heck if we have a bad block, we do not erase bad blocks !
    		 */
    		if (nand_block_checkbad(mtd, ((loff_t) page) <<
    					chip->page_shift, 0, allowbbt)) {
    			printk(KERN_WARNING "nand_erase: attempt to erase a "
    			       "bad block at page 0x%08x\n", page);
    
    			instr->state = MTD_ERASE_FAILED;
    			goto erase_exit;
    		}
    
    
    		/*
    		 * Invalidate the page cache, if we erase the block which
    		 * contains the current cached page
    		 */
    		if (page <= chip->pagebuf && chip->pagebuf <
    		    (page + pages_per_block))
    			chip->pagebuf = -1;
    
    		chip->erase_cmd(mtd, page & chip->pagemask);
    
    		status = chip->waitfunc(mtd, chip);
    
    		/*
    		 * See if operation failed and additional status checks are
    		 * available
    		 */
    		if ((status & NAND_STATUS_FAIL) && (chip->errstat))
    			status = chip->errstat(mtd, chip, FL_ERASING,
    					       status, page);
    
    
    		/* See if block erase succeeded */
    
    		if (status & NAND_STATUS_FAIL) {
    
    			MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_erase: "
    			          "Failed erase, page 0x%08x\n", page);
    
    			instr->state = MTD_ERASE_FAILED;
    
    			instr->fail_addr = (page << chip->page_shift);
    
    		/*
    		 * If BBT requires refresh, set the BBT rewrite flag to the
    		 * page being erased
    		 */
    		if (bbt_masked_page != 0xffffffff &&
    		    (page & BBT_PAGE_MASK) == bbt_masked_page)
    			    rewrite_bbt[chipnr] = (page << chip->page_shift);
    
    
    		/* Increment page address and decrement length */
    
    		len -= (1 << chip->phys_erase_shift);
    
    		page += pages_per_block;
    
    		/* Check, if we cross a chip boundary */
    
    		if (len && !(page & chip->pagemask)) {
    
    			chip->select_chip(mtd, -1);
    			chip->select_chip(mtd, chipnr);
    
    			/*
    			 * If BBT requires refresh and BBT-PERCHIP, set the BBT
    			 * page mask to see if this BBT should be rewritten
    			 */
    			if (bbt_masked_page != 0xffffffff &&
    			    (chip->bbt_td->options & NAND_BBT_PERCHIP))
    				bbt_masked_page = chip->bbt_td->pages[chipnr] &
    					BBT_PAGE_MASK;
    
     erase_exit:
    
    
    	ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
    	/* Do call back function */
    	if (!ret)
    		mtd_erase_callback(instr);
    
    	/* Deselect and wake up anyone waiting on the device */
    	nand_release_device(mtd);
    
    
    	/*
    	 * If BBT requires refresh and erase was successful, rewrite any
    	 * selected bad block tables
    	 */
    	if (bbt_masked_page == 0xffffffff || ret)
    		return ret;
    
    	for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
    		if (!rewrite_bbt[chipnr])
    			continue;
    		/* update the BBT for chip */
    		MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
    		          "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
    		          chip->bbt_td->pages[chipnr]);
    		nand_update_bbt(mtd, rewrite_bbt[chipnr]);
    	}
    
    
    	/* Return more or less happy */
    	return ret;
    }
    
    /**
     * nand_sync - [MTD Interface] sync
     * @mtd:	MTD device structure
     *
     * Sync is actually a wait for chip ready function
     */
    
    static void nand_sync(struct mtd_info *mtd)
    
    	struct nand_chip *chip = mtd->priv;
    
    	MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n");
    
    
    	/* Grab the lock and see if the device is available */
    
    	nand_get_device(chip, mtd, FL_SYNCING);
    
    	/* Release it and go back */
    
    	nand_release_device(mtd);
    
     * nand_block_isbad - [MTD Interface] Check if block at offset is bad
    
     * @mtd:	MTD device structure
    
     * @offs:	offset relative to mtd start
    
    static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
    
    {
    	/* Check for invalid offset */
    
    	if (offs > mtd->size)
    
    	return nand_block_checkbad(mtd, offs, 1, 0);
    
     * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
    
     * @mtd:	MTD device structure
     * @ofs:	offset relative to mtd start
     */
    
    static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
    
    	struct nand_chip *chip = mtd->priv;
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	if ((ret = nand_block_isbad(mtd, ofs))) {
    		/* If it was bad already, return success and do nothing. */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		return ret;
    	}
    
    	return chip->block_markbad(mtd, ofs);
    
     * nand_suspend - [MTD Interface] Suspend the NAND flash
    
    static int nand_suspend(struct mtd_info *mtd)
    
    	struct nand_chip *chip = mtd->priv;
    
    	return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
    }
    
    /**
     * nand_resume - [MTD Interface] Resume the NAND flash
     * @mtd:	MTD device structure
     */
    static void nand_resume(struct mtd_info *mtd)
    {
    	struct nand_chip *chip = mtd->priv;
    
    	if (chip->state == FL_PM_SUSPENDED)
    		nand_release_device(mtd);
    	else
    		printk(KERN_ERR "nand_resume() called for a chip which is not "
    		       "in suspended state\n");
    }
    
    /*
     * Set default functions
     */
    static void nand_set_defaults(struct nand_chip *chip, int busw)
    {
    
    	/* check for proper chip_delay setup, set 20us if not */
    
    	if (!chip->chip_delay)
    		chip->chip_delay = 20;
    
    
    	/* check, if a user supplied command function given */
    
    	if (chip->cmdfunc == NULL)
    		chip->cmdfunc = nand_command;
    
    
    	/* check, if a user supplied wait function given */
    
    	if (chip->waitfunc == NULL)
    		chip->waitfunc = nand_wait;
    
    	if (!chip->select_chip)
    		chip->select_chip = nand_select_chip;
    	if (!chip->read_byte)
    		chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
    	if (!chip->read_word)
    		chip->read_word = nand_read_word;
    	if (!chip->block_bad)
    		chip->block_bad = nand_block_bad;
    	if (!chip->block_markbad)
    		chip->block_markbad = nand_default_block_markbad;
    	if (!chip->write_buf)
    		chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
    	if (!chip->read_buf)
    		chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
    	if (!chip->verify_buf)
    		chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
    	if (!chip->scan_bbt)
    		chip->scan_bbt = nand_default_bbt;
    
    	if (!chip->controller) {
    		chip->controller = &chip->hwcontrol;
    
    		/* XXX U-BOOT XXX */
    #if 0
    		spin_lock_init(&chip->controller->lock);
    		init_waitqueue_head(&chip->controller->wq);
    #endif
    	}
    
    }
    
    /*
     * Get the flash and manufacturer id and lookup if the type is supported
     */
    static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
    						  struct nand_chip *chip,
    						  int busw, int *maf_id)
    {
    	struct nand_flash_dev *type = NULL;
    	int i, dev_id, maf_idx;
    
    	chip->select_chip(mtd, 0);
    
    
    	/* Send the command for reading device ID */
    
    	chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
    
    
    	/* Read manufacturer and device IDs */
    
    	*maf_id = chip->read_byte(mtd);
    	dev_id = chip->read_byte(mtd);
    
    	/* Lookup the flash id */
    
    	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
    
    		if (dev_id == nand_flash_ids[i].id) {
    			type =  &nand_flash_ids[i];
    			break;
    		}
    	}
    
    	if (!type)
    		return ERR_PTR(-ENODEV);
    
    	if (!mtd->name)
    		mtd->name = type->name;
    
    	chip->chipsize = type->chipsize << 20;
    
    	/* Newer devices have all the information in additional id bytes */
    	if (!type->pagesize) {
    		int extid;
    		/* The 3rd id byte holds MLC / multichip data */
    		chip->cellinfo = chip->read_byte(mtd);
    		/* The 4th id byte is the important one */
    		extid = chip->read_byte(mtd);
    		/* Calc pagesize */
    		mtd->writesize = 1024 << (extid & 0x3);
    		extid >>= 2;
    		/* Calc oobsize */
    		mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
    		extid >>= 2;
    		/* Calc blocksize. Blocksize is multiples of 64KiB */
    		mtd->erasesize = (64 * 1024) << (extid & 0x03);
    		extid >>= 2;
    		/* Get buswidth information */
    		busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
    
    	} else {
    		/*
    		 * Old devices have chip data hardcoded in the device id table
    		 */
    		mtd->erasesize = type->erasesize;
    		mtd->writesize = type->pagesize;
    		mtd->oobsize = mtd->writesize / 32;
    		busw = type->options & NAND_BUSWIDTH_16;
    	}
    
    	/* Try to identify manufacturer */
    	for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
    		if (nand_manuf_ids[maf_idx].id == *maf_id)
    			break;
    	}
    
    	/*
    	 * Check, if buswidth is correct. Hardware drivers should set
    	 * chip correct !
    	 */
    	if (busw != (chip->options & NAND_BUSWIDTH_16)) {
    		printk(KERN_INFO "NAND device: Manufacturer ID:"
    		       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
    		       dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
    		printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
    		       (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
    		       busw ? 16 : 8);
    		return ERR_PTR(-EINVAL);
    	}
    
    	/* Calculate the address shift from the page size */
    	chip->page_shift = ffs(mtd->writesize) - 1;
    	/* Convert chipsize to number of pages per chip -1. */
    	chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
    
    	chip->bbt_erase_shift = chip->phys_erase_shift =
    		ffs(mtd->erasesize) - 1;
    	chip->chip_shift = ffs(chip->chipsize) - 1;
    
    	/* Set the bad block position */
    	chip->badblockpos = mtd->writesize > 512 ?
    		NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
    
    	/* Get chip options, preserve non chip based options */
    	chip->options &= ~NAND_CHIPOPTIONS_MSK;
    	chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
    
    	/*
    	 * Set chip as a default. Board drivers can override it, if necessary
    	 */
    	chip->options |= NAND_NO_AUTOINCR;
    
    	/* Check if chip is a not a samsung device. Do not clear the
    	 * options for chips which are not having an extended id.
    	 */
    	if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
    		chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
    
    	/* Check for AND chips with 4 page planes */
    	if (chip->options & NAND_4PAGE_ARRAY)
    		chip->erase_cmd = multi_erase_cmd;
    	else
    		chip->erase_cmd = single_erase_cmd;
    
    	/* Do not replace user supplied command function ! */
    	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
    		chip->cmdfunc = nand_command_lp;
    
    
    	MTDDEBUG (MTD_DEBUG_LEVEL0, "NAND device: Manufacturer ID:"
    	          " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
    	          nand_manuf_ids[maf_idx].name, type->name);
    
    
    	return type;
    }
    
    /**
     * nand_scan_ident - [NAND Interface] Scan for the NAND device
     * @mtd:	     MTD device structure
     * @maxchips:	     Number of chips to scan for
     *
     * This is the first phase of the normal nand_scan() function. It
     * reads the flash ID and sets up MTD fields accordingly.
     *
     * The mtd->owner field must be set to the module of the caller.
     */
    int nand_scan_ident(struct mtd_info *mtd, int maxchips)
    {
    	int i, busw, nand_maf_id;
    	struct nand_chip *chip = mtd->priv;
    	struct nand_flash_dev *type;
    
    	/* Get buswidth to select the correct functions */
    	busw = chip->options & NAND_BUSWIDTH_16;
    	/* Set the default functions */
    	nand_set_defaults(chip, busw);
    
    	/* Read the flash type */
    	type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
    
    	if (IS_ERR(type)) {
    		printk(KERN_WARNING "No NAND device found!!!\n");
    		chip->select_chip(mtd, -1);
    		return PTR_ERR(type);
    	}
    
    	/* Check for a chip array */
    	for (i = 1; i < maxchips; i++) {
    		chip->select_chip(mtd, i);
    		/* Send the command for reading device ID */
    		chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
    
    		/* Read manufacturer and device IDs */
    
    		if (nand_maf_id != chip->read_byte(mtd) ||
    		    type->id != chip->read_byte(mtd))
    
    			break;
    	}
    	if (i > 1)
    		printk(KERN_INFO "%d NAND chips detected\n", i);
    
    	/* Store the number of chips and calc total size for mtd */
    	chip->numchips = i;
    	mtd->size = i * chip->chipsize;
    
    
    /**
     * nand_scan_tail - [NAND Interface] Scan for the NAND device
     * @mtd:	    MTD device structure
     * @maxchips:	    Number of chips to scan for
     *
     * This is the second phase of the normal nand_scan() function. It
     * fills out all the uninitialized function pointers with the defaults
     * and scans for a bad block table if appropriate.
     */
    int nand_scan_tail(struct mtd_info *mtd)
    {
    	int i;
    	struct nand_chip *chip = mtd->priv;
    
    	if (!(chip->options & NAND_OWN_BUFFERS))
    		chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);
    	if (!chip->buffers)
    		return -ENOMEM;
    
    	/* Set the internal oob buffer location, just after the page data */
    	chip->oob_poi = chip->buffers->databuf + mtd->writesize;
    
    	/*
    	 * If no default placement scheme is given, select an appropriate one
    	 */
    	if (!chip->ecc.layout) {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		switch (mtd->oobsize) {
    
    			chip->ecc.layout = &nand_oob_8;
    
    			chip->ecc.layout = &nand_oob_16;
    
    			chip->ecc.layout = &nand_oob_64;
    
    			chip->ecc.layout = &nand_oob_128;
    
    			printk(KERN_WARNING "No oob scheme defined for "
    			       "oobsize %d\n", mtd->oobsize);
    
    William Juul's avatar
    William Juul committed
    /*			BUG(); */
    
    	if (!chip->write_page)
    		chip->write_page = nand_write_page;
    
    	 * check ECC mode, default to software if 3byte/512byte hardware ECC is
    	 * selected and we have 256 byte pagesize fallback to software ECC
    	 */
    	if (!chip->ecc.read_page_raw)
    		chip->ecc.read_page_raw = nand_read_page_raw;
    	if (!chip->ecc.write_page_raw)
    		chip->ecc.write_page_raw = nand_write_page_raw;
    
    	switch (chip->ecc.mode) {
    	case NAND_ECC_HW:
    		/* Use standard hwecc read page function ? */
    		if (!chip->ecc.read_page)
    			chip->ecc.read_page = nand_read_page_hwecc;
    		if (!chip->ecc.write_page)
    			chip->ecc.write_page = nand_write_page_hwecc;
    		if (!chip->ecc.read_oob)
    			chip->ecc.read_oob = nand_read_oob_std;
    		if (!chip->ecc.write_oob)
    			chip->ecc.write_oob = nand_write_oob_std;
    
    	case NAND_ECC_HW_SYNDROME:
    
    		if ((!chip->ecc.calculate || !chip->ecc.correct ||
    		     !chip->ecc.hwctl) &&
    		    (!chip->ecc.read_page ||
    		     chip->ecc.read_page == nand_read_page_hwecc ||
    		     !chip->ecc.write_page ||
    		     chip->ecc.write_page == nand_write_page_hwecc)) {
    
    			printk(KERN_WARNING "No ECC functions supplied, "
    			       "Hardware ECC not possible\n");
    			BUG();
    		}
    		/* Use standard syndrome read/write page function ? */
    		if (!chip->ecc.read_page)
    			chip->ecc.read_page = nand_read_page_syndrome;
    		if (!chip->ecc.write_page)
    			chip->ecc.write_page = nand_write_page_syndrome;
    		if (!chip->ecc.read_oob)
    			chip->ecc.read_oob = nand_read_oob_syndrome;
    		if (!chip->ecc.write_oob)
    			chip->ecc.write_oob = nand_write_oob_syndrome;
    
    		if (mtd->writesize >= chip->ecc.size)
    			break;
    		printk(KERN_WARNING "%d byte HW ECC not possible on "
    		       "%d byte page size, fallback to SW ECC\n",
    		       chip->ecc.size, mtd->writesize);
    		chip->ecc.mode = NAND_ECC_SOFT;
    
    	case NAND_ECC_SOFT:
    		chip->ecc.calculate = nand_calculate_ecc;
    		chip->ecc.correct = nand_correct_data;
    		chip->ecc.read_page = nand_read_page_swecc;
    		chip->ecc.write_page = nand_write_page_swecc;
    		chip->ecc.read_oob = nand_read_oob_std;
    		chip->ecc.write_oob = nand_write_oob_std;
    		chip->ecc.size = 256;
    		chip->ecc.bytes = 3;
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    	case NAND_ECC_NONE:
    
    		printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
    		       "This is not recommended !!\n");
    		chip->ecc.read_page = nand_read_page_raw;
    		chip->ecc.write_page = nand_write_page_raw;
    		chip->ecc.read_oob = nand_read_oob_std;
    		chip->ecc.write_oob = nand_write_oob_std;
    		chip->ecc.size = mtd->writesize;
    		chip->ecc.bytes = 0;
    
    		printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
    		       chip->ecc.mode);
    		BUG();
    
    	/*
    	 * The number of bytes available for a client to place data into
    	 * the out of band area
    	 */
    	chip->ecc.layout->oobavail = 0;
    	for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
    		chip->ecc.layout->oobavail +=
    			chip->ecc.layout->oobfree[i].length;
    	mtd->oobavail = chip->ecc.layout->oobavail;
    
    	/*
    	 * Set the number of read / write steps for one page depending on ECC
    	 * mode
    	 */
    	chip->ecc.steps = mtd->writesize / chip->ecc.size;
    	if(chip->ecc.steps * chip->ecc.size != mtd->writesize) {
    		printk(KERN_WARNING "Invalid ecc parameters\n");
    		BUG();
    	}
    	chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
    
    	/*
    	 * Allow subpage writes up to ecc.steps. Not possible for MLC
    	 * FLASH.
    	 */
    	if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
    	    !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
    		switch(chip->ecc.steps) {
    		case 2:
    			mtd->subpage_sft = 1;
    			break;
    		case 4:
    		case 8:
    			mtd->subpage_sft = 2;
    			break;
    		}
    
    	chip->subpagesize = mtd->writesize >> mtd->subpage_sft;
    
    	/* Initialize state */
    	chip->state = FL_READY;
    
    	chip->select_chip(mtd, -1);
    
    
    	/* Invalidate the pagebuffer reference */
    
    	chip->pagebuf = -1;
    
    
    	/* Fill in remaining MTD driver data */
    	mtd->type = MTD_NANDFLASH;
    
    	mtd->flags = MTD_CAP_NANDFLASH;
    
    	mtd->erase = nand_erase;
    	mtd->point = NULL;
    	mtd->unpoint = NULL;
    	mtd->read = nand_read;
    	mtd->write = nand_write;
    	mtd->read_oob = nand_read_oob;
    	mtd->write_oob = nand_write_oob;
    	mtd->sync = nand_sync;
    	mtd->lock = NULL;
    	mtd->unlock = NULL;
    
    	mtd->suspend = nand_suspend;
    	mtd->resume = nand_resume;
    
    	mtd->block_isbad = nand_block_isbad;
    	mtd->block_markbad = nand_block_markbad;
    
    
    	/* propagate ecc.layout to mtd_info */
    	mtd->ecclayout = chip->ecc.layout;
    
    	/* Check, if we should skip the bad block table scan */
    	if (chip->options & NAND_SKIP_BBTSCAN)
    		return 0;
    
    	/* Build bad block table */
    	return chip->scan_bbt(mtd);
    }
    
    /* module_text_address() isn't exported, and it's mostly a pointless
       test if this is a module _anyway_ -- they'd have to try _really_ hard
       to call us from in-kernel code if the core NAND support is modular. */
    #ifdef MODULE
    #define caller_is_module() (1)
    #else
    #define caller_is_module() \
    	module_text_address((unsigned long)__builtin_return_address(0))
    #endif
    
    /**
     * nand_scan - [NAND Interface] Scan for the NAND device
     * @mtd:	MTD device structure
     * @maxchips:	Number of chips to scan for
     *
     * This fills out all the uninitialized function pointers
     * with the defaults.
     * The flash ID is read and the mtd/chip structures are
     * filled with the appropriate values.
     * The mtd->owner field must be set to the module of the caller
     *
     */
    int nand_scan(struct mtd_info *mtd, int maxchips)
    {
    	int ret;
    
    	/* Many callers got this wrong, so check for it for a while... */
    	/* XXX U-BOOT XXX */
    
    	if (!mtd->owner && caller_is_module()) {
    		printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
    		BUG();
    	}
    
    	ret = nand_scan_ident(mtd, maxchips);
    	if (!ret)
    		ret = nand_scan_tail(mtd);
    	return ret;
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     * nand_release - [NAND Interface] Free resources held by the NAND device
    
     * @mtd:	MTD device structure
    
    */
    void nand_release(struct mtd_info *mtd)
    
    	struct nand_chip *chip = mtd->priv;
    
    
    #ifdef CONFIG_MTD_PARTITIONS
    	/* Deregister partitions */
    
    	del_mtd_partitions(mtd);
    
    #endif
    	/* Deregister the device */
    
    	/* XXX U-BOOT XXX */
    
    	del_mtd_device(mtd);
    
    
    	/* Free bad block table memory */
    	kfree(chip->bbt);
    	if (!(chip->options & NAND_OWN_BUFFERS))
    		kfree(chip->buffers);
    }
    
    /* XXX U-BOOT XXX */
    #if 0
    EXPORT_SYMBOL_GPL(nand_scan);
    EXPORT_SYMBOL_GPL(nand_scan_ident);
    EXPORT_SYMBOL_GPL(nand_scan_tail);
    EXPORT_SYMBOL_GPL(nand_release);
    
    static int __init nand_base_init(void)
    {
    	led_trigger_register_simple("nand-disk", &nand_led_trigger);
    	return 0;
    }
    
    static void __exit nand_base_exit(void)
    {
    	led_trigger_unregister_simple(nand_led_trigger);
    
    module_init(nand_base_init);
    module_exit(nand_base_exit);
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
    MODULE_DESCRIPTION("Generic NAND flash driver code");
    #endif