⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 onenand_base.c

📁 uboot200903最新版本的通用uboot
💻 C
📖 第 1 页 / 共 4 页
字号:
{	struct onenand_chip *this = mtd->priv;	int ret;	ret = onenand_block_isbad(mtd, ofs);	if (ret) {		/* If it was bad already, return success and do nothing */		if (ret > 0)			return 0;		return ret;	}	ret = this->block_markbad(mtd, ofs);	return ret;}/** * onenand_do_lock_cmd - [OneNAND Interface] Lock or unlock block(s) * @param mtd           MTD device structure * @param ofs           offset relative to mtd start * @param len           number of bytes to lock or unlock * @param cmd           lock or unlock command * * Lock or unlock one or more blocks */static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int cmd){	struct onenand_chip *this = mtd->priv;	int start, end, block, value, status;	int wp_status_mask;	start = ofs >> this->erase_shift;	end = len >> this->erase_shift;	if (cmd == ONENAND_CMD_LOCK)		wp_status_mask = ONENAND_WP_LS;	else		wp_status_mask = ONENAND_WP_US;	/* Continuous lock scheme */	if (this->options & ONENAND_HAS_CONT_LOCK) {		/* Set start block address */		this->write_word(start,				 this->base + ONENAND_REG_START_BLOCK_ADDRESS);		/* Set end block address */		this->write_word(end - 1,				 this->base + ONENAND_REG_END_BLOCK_ADDRESS);		/* Write unlock command */		this->command(mtd, cmd, 0, 0);		/* There's no return value */		this->wait(mtd, FL_UNLOCKING);		/* Sanity check */		while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)		       & ONENAND_CTRL_ONGO)			continue;		/* Check lock status */		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);		if (!(status & ONENAND_WP_US))			printk(KERN_ERR "wp status = 0x%x\n", status);		return 0;	}	/* Block lock scheme */	for (block = start; block < start + end; block++) {		/* Set block address */		value = onenand_block_address(this, block);		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);		/* Select DataRAM for DDP */		value = onenand_bufferram_address(this, block);		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);		/* Set start block address */		this->write_word(block,				 this->base + ONENAND_REG_START_BLOCK_ADDRESS);		/* Write unlock command */		this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);		/* There's no return value */		this->wait(mtd, FL_UNLOCKING);		/* Sanity check */		while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)		       & ONENAND_CTRL_ONGO)			continue;		/* Check lock status */		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);		if (!(status & ONENAND_WP_US))			printk(KERN_ERR "block = %d, wp status = 0x%x\n",			       block, status);	}	return 0;}#ifdef ONENAND_LINUX/** * onenand_lock - [MTD Interface] Lock block(s) * @param mtd           MTD device structure * @param ofs           offset relative to mtd start * @param len           number of bytes to unlock * * Lock one or more blocks */static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len){	int ret;	onenand_get_device(mtd, FL_LOCKING);	ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);	onenand_release_device(mtd);	return ret;}/** * onenand_unlock - [MTD Interface] Unlock block(s) * @param mtd           MTD device structure * @param ofs           offset relative to mtd start * @param len           number of bytes to unlock * * Unlock one or more blocks */static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len){	int ret;	onenand_get_device(mtd, FL_LOCKING);	ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);	onenand_release_device(mtd);	return ret;}#endif/** * onenand_check_lock_status - [OneNAND Interface] Check lock status * @param this          onenand chip data structure * * Check lock status */static int onenand_check_lock_status(struct onenand_chip *this){	unsigned int value, block, status;	unsigned int end;	end = this->chipsize >> this->erase_shift;	for (block = 0; block < end; block++) {		/* Set block address */		value = onenand_block_address(this, block);		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);		/* Select DataRAM for DDP */		value = onenand_bufferram_address(this, block);		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);		/* Set start block address */		this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);		/* Check lock status */		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);		if (!(status & ONENAND_WP_US)) {			printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);			return 0;		}	}	return 1;}/** * onenand_unlock_all - [OneNAND Interface] unlock all blocks * @param mtd           MTD device structure * * Unlock all blocks */static void onenand_unlock_all(struct mtd_info *mtd){	struct onenand_chip *this = mtd->priv;	loff_t ofs = 0;	size_t len = this->chipsize;	if (this->options & ONENAND_HAS_UNLOCK_ALL) {		/* Set start block address */		this->write_word(0, this->base + ONENAND_REG_START_BLOCK_ADDRESS);		/* Write unlock command */		this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);		/* There's no return value */		this->wait(mtd, FL_LOCKING);		/* Sanity check */		while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)				& ONENAND_CTRL_ONGO)			continue;		return;		/* Check lock status */		if (onenand_check_lock_status(this))			return;		/* Workaround for all block unlock in DDP */		if (ONENAND_IS_DDP(this)) {			/* All blocks on another chip */			ofs = this->chipsize >> 1;			len = this->chipsize >> 1;		}	}	onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);}/** * onenand_check_features - Check and set OneNAND features * @param mtd           MTD data structure * * Check and set OneNAND features * - lock scheme * - two plane */static void onenand_check_features(struct mtd_info *mtd){	struct onenand_chip *this = mtd->priv;	unsigned int density, process;	/* Lock scheme depends on density and process */	density = onenand_get_density(this->device_id);	process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;	/* Lock scheme */	switch (density) {	case ONENAND_DEVICE_DENSITY_4Gb:		this->options |= ONENAND_HAS_2PLANE;	case ONENAND_DEVICE_DENSITY_2Gb:		/* 2Gb DDP don't have 2 plane */		if (!ONENAND_IS_DDP(this))			this->options |= ONENAND_HAS_2PLANE;		this->options |= ONENAND_HAS_UNLOCK_ALL;	case ONENAND_DEVICE_DENSITY_1Gb:		/* A-Die has all block unlock */		if (process)			this->options |= ONENAND_HAS_UNLOCK_ALL;		break;	default:		/* Some OneNAND has continuous lock scheme */		if (!process)			this->options |= ONENAND_HAS_CONT_LOCK;		break;	}	if (this->options & ONENAND_HAS_CONT_LOCK)		printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");	if (this->options & ONENAND_HAS_UNLOCK_ALL)		printk(KERN_DEBUG "Chip support all block unlock\n");	if (this->options & ONENAND_HAS_2PLANE)		printk(KERN_DEBUG "Chip has 2 plane\n");}/** * onenand_print_device_info - Print device ID * @param device        device ID * * Print device ID */char *onenand_print_device_info(int device, int version){	int vcc, demuxed, ddp, density;	char *dev_info = malloc(80);	char *p = dev_info;	vcc = device & ONENAND_DEVICE_VCC_MASK;	demuxed = device & ONENAND_DEVICE_IS_DEMUX;	ddp = device & ONENAND_DEVICE_IS_DDP;	density = device >> ONENAND_DEVICE_DENSITY_SHIFT;	p += sprintf(dev_info, "%sOneNAND%s %dMB %sV 16-bit (0x%02x)",	       demuxed ? "" : "Muxed ",	       ddp ? "(DDP)" : "",	       (16 << density), vcc ? "2.65/3.3" : "1.8", device);	sprintf(p, "\nOneNAND version = 0x%04x", version);	printk("%s\n", dev_info);	return dev_info;}static const struct onenand_manufacturers onenand_manuf_ids[] = {	{ONENAND_MFR_SAMSUNG, "Samsung"},};/** * onenand_check_maf - Check manufacturer ID * @param manuf         manufacturer ID * * Check manufacturer ID */static int onenand_check_maf(int manuf){	int size = ARRAY_SIZE(onenand_manuf_ids);	char *name;	int i;	for (i = 0; size; i++)		if (manuf == onenand_manuf_ids[i].id)			break;	if (i < size)		name = onenand_manuf_ids[i].name;	else		name = "Unknown";#ifdef ONENAND_DEBUG	printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", name, manuf);#endif	return i == size;}/** * onenand_probe - [OneNAND Interface] Probe the OneNAND device * @param mtd		MTD device structure * * OneNAND detection method: *   Compare the the values from command with ones from register */static int onenand_probe(struct mtd_info *mtd){	struct onenand_chip *this = mtd->priv;	int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id;	int density;	int syscfg;	/* Save system configuration 1 */	syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);	/* Clear Sync. Burst Read mode to read BootRAM */	this->write_word((syscfg & ~ONENAND_SYS_CFG1_SYNC_READ), this->base + ONENAND_REG_SYS_CFG1);	/* Send the command for reading device ID from BootRAM */	this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM);	/* Read manufacturer and device IDs from BootRAM */	bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0);	bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2);	/* Reset OneNAND to read default register values */	this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);	/* Wait reset */	this->wait(mtd, FL_RESETING);	/* Restore system configuration 1 */	this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);	/* Check manufacturer ID */	if (onenand_check_maf(bram_maf_id))		return -ENXIO;	/* Read manufacturer and device IDs from Register */	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);	dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);	ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);	/* Check OneNAND device */	if (maf_id != bram_maf_id || dev_id != bram_dev_id)		return -ENXIO;	/* FIXME : Current OneNAND MTD doesn't support Flex-OneNAND */	if (dev_id & (1 << 9)) {		printk("Not yet support Flex-OneNAND\n");		return -ENXIO;	}	/* Flash device information */	mtd->name = onenand_print_device_info(dev_id, ver_id);	this->device_id = dev_id;	this->version_id = ver_id;	density = onenand_get_density(dev_id);	this->chipsize = (16 << density) << 20;	/* Set density mask. it is used for DDP */	if (ONENAND_IS_DDP(this))		this->density_mask = (1 << (density + 6));	else		this->density_mask = 0;	/* OneNAND page size & block size */	/* The data buffer size is equal to page size */	mtd->writesize =	    this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);	mtd->oobsize = mtd->writesize >> 5;	/* Pagers per block is always 64 in OneNAND */	mtd->erasesize = mtd->writesize << 6;	this->erase_shift = ffs(mtd->erasesize) - 1;	this->page_shift = ffs(mtd->writesize) - 1;	this->ppb_shift = (this->erase_shift - this->page_shift);	this->page_mask = (mtd->erasesize / mtd->writesize) - 1;	/* It's real page size */	this->writesize = mtd->writesize;	/* REVIST: Multichip handling */	mtd->size = this->chipsize;	/* Check OneNAND features */	onenand_check_features(mtd);	mtd->flags = MTD_CAP_NANDFLASH;	mtd->erase = onenand_erase;	mtd->read = onenand_read;	mtd->write = onenand_write;	mtd->read_oob = onenand_read_oob;	mtd->write_oob = onenand_write_oob;	mtd->sync = onenand_sync;	mtd->block_isbad = onenand_block_isbad;	mtd->block_markbad = onenand_block_markbad;	return 0;}/** * onenand_scan - [OneNAND Interface] Scan for the OneNAND device * @param mtd		MTD device structure * @param maxchips	Number of chips to scan for * * This fills out all the not initialized function pointers * with the defaults. * The flash ID is read and the mtd/chip structures are * filled with the appropriate values. */int onenand_scan(struct mtd_info *mtd, int maxchips){	int i;	struct onenand_chip *this = mtd->priv;	if (!this->read_word)		this->read_word = onenand_readw;	if (!this->write_word)		this->write_word = onenand_writew;	if (!this->command)		this->command = onenand_command;	if (!this->wait)		this->wait = onenand_wait;	if (!this->bbt_wait)		this->bbt_wait = onenand_bbt_wait;	if (!this->read_bufferram)		this->read_bufferram = onenand_read_bufferram;	if (!this->read_spareram)		this->read_spareram = onenand_read_bufferram;	if (!this->write_bufferram)		this->write_bufferram = onenand_write_bufferram;	if (!this->block_markbad)		this->block_markbad = onenand_default_block_markbad;	if (!this->scan_bbt)		this->scan_bbt = onenand_default_bbt;	if (onenand_probe(mtd))		return -ENXIO;	/* Set Sync. Burst Read after probing */	if (this->mmcontrol) {		printk(KERN_INFO "OneNAND Sync. Burst Read support\n");		this->read_bufferram = onenand_sync_read_bufferram;	}	/* Allocate buffers, if necessary */	if (!this->page_buf) {		this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);		if (!this->page_buf) {			printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");			return -ENOMEM;		}		this->options |= ONENAND_PAGEBUF_ALLOC;	}	if (!this->oob_buf) {		this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);		if (!this->oob_buf) {			printk(KERN_ERR "onenand_scan: Can't allocate oob_buf\n");			if (this->options & ONENAND_PAGEBUF_ALLOC) {				this->options &= ~ONENAND_PAGEBUF_ALLOC;				kfree(this->page_buf);			}			return -ENOMEM;		}		this->options |= ONENAND_OOBBUF_ALLOC;	}	this->state = FL_READY;	/*	 * Allow subpage writes up to oobsize.	 */	switch (mtd->oobsize) {	case 64:		this->ecclayout = &onenand_oob_64;		mtd->subpage_sft = 2;		break;	case 32:		this->ecclayout = &onenand_oob_32;		mtd->subpage_sft = 1;		break;	default:		printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",			mtd->oobsize);		mtd->subpage_sft = 0;		/* To prevent kernel oops */		this->ecclayout = &onenand_oob_32;		break;	}	this->subpagesize = mtd->writesize >> mtd->subpage_sft;	/*	 * The number of bytes available for a client to place data into	 * the out of band area	 */	this->ecclayout->oobavail = 0;	for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES &&	    this->ecclayout->oobfree[i].length; i++)		this->ecclayout->oobavail +=			this->ecclayout->oobfree[i].length;	mtd->oobavail = this->ecclayout->oobavail;	mtd->ecclayout = this->ecclayout;	/* Unlock whole block */	onenand_unlock_all(mtd);	return this->scan_bbt(mtd);}/** * onenand_release - [OneNAND Interface] Free resources held by the OneNAND device * @param mtd		MTD device structure */void onenand_release(struct mtd_info *mtd){}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -