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

📄 cfi_cmdset_0002.c

📁 老版本的mtd-snap
💻 C
📖 第 1 页 / 共 4 页
字号:
			chipnum ++;			ofs = 0;			if (chipnum == cfi->numchips)				return 0;		}	}	/* Write buffer is worth it only if more than one word to write... */	while (len >= map_bankwidth(map) * 2) {		/* We must not cross write block boundaries */		int size = wbufsize - (ofs & (wbufsize-1));		if (size > len)			size = len;		if (size % map_bankwidth(map))			size -= size % map_bankwidth(map);		ret = do_write_buffer(map, &cfi->chips[chipnum], 				      ofs, buf, size);		if (ret)			return ret;		ofs += size;		buf += size;		(*retlen) += size;		len -= size;		if (ofs >> cfi->chipshift) {			chipnum ++; 			ofs = 0;			if (chipnum == cfi->numchips)				return 0;		}	}	if (len) {		size_t retlen_dregs = 0;		ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<<cfi->chipshift),					     len, &retlen_dregs, buf);		*retlen += retlen_dregs;		return ret;	}	return 0;}/* * Handle devices with one erase region, that only implement * the chip erase command. */static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip){	struct cfi_private *cfi = map->fldrv_priv;	unsigned long timeo = jiffies + HZ;	unsigned long int adr;	DECLARE_WAITQUEUE(wait, current);	int ret = 0;	adr = cfi->addr_unlock1;	spin_lock(chip->mutex);	ret = get_chip(map, chip, adr, FL_WRITING);	if (ret) {		spin_unlock(chip->mutex);		return ret;	}	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",	       __func__, chip->start );	XIP_INVAL_CACHED_RANGE(map, adr, map->size);	ENABLE_VPP(map);	xip_disable(map, chip, adr);	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);	cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);	cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	chip->state = FL_ERASING;	chip->erase_suspended = 0;	chip->in_progress_block_addr = adr;	INVALIDATE_CACHE_UDELAY(map, chip,				adr, map->size,				chip->erase_time*500);	timeo = jiffies + (HZ*20);	for (;;) {		if (chip->state != FL_ERASING) {			/* Someone's suspended the erase. Sleep */			set_current_state(TASK_UNINTERRUPTIBLE);			add_wait_queue(&chip->wq, &wait);			spin_unlock(chip->mutex);			schedule();			remove_wait_queue(&chip->wq, &wait);			spin_lock(chip->mutex);			continue;		}		if (chip->erase_suspended) {			/* This erase was suspended and resumed.			   Adjust the timeout */			timeo = jiffies + (HZ*20); /* FIXME */			chip->erase_suspended = 0;		}		if (chip_ready(map, adr))			break;		if (time_after(jiffies, timeo)) {			printk(KERN_WARNING "MTD %s(): software timeout\n",				__func__ );			break;		}		/* Latency issues. Drop the lock, wait a while and retry */		UDELAY(map, chip, adr, 1000000/HZ);	}	/* Did we succeed? */	if (!chip_good(map, adr, map_word_ff(map))) {		/* reset on all failures. */		map_write( map, CMD(0xF0), chip->start );		/* FIXME - should have reset delay before continuing */		ret = -EIO;	}	chip->state = FL_READY;	xip_enable(map, chip, adr);	put_chip(map, chip, adr);	spin_unlock(chip->mutex);	return ret;}static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk){	struct cfi_private *cfi = map->fldrv_priv;	unsigned long timeo = jiffies + HZ;	DECLARE_WAITQUEUE(wait, current);	int ret = 0;	adr += chip->start;	spin_lock(chip->mutex);	ret = get_chip(map, chip, adr, FL_ERASING);	if (ret) {		spin_unlock(chip->mutex);		return ret;	}	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",	       __func__, adr );	XIP_INVAL_CACHED_RANGE(map, adr, len);	ENABLE_VPP(map);	xip_disable(map, chip, adr);	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);	cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);	map_write(map, CMD(0x30), adr);	chip->state = FL_ERASING;	chip->erase_suspended = 0;	chip->in_progress_block_addr = adr;	INVALIDATE_CACHE_UDELAY(map, chip,				adr, len,				chip->erase_time*500);	timeo = jiffies + (HZ*20);	for (;;) {		if (chip->state != FL_ERASING) {			/* Someone's suspended the erase. Sleep */			set_current_state(TASK_UNINTERRUPTIBLE);			add_wait_queue(&chip->wq, &wait);			spin_unlock(chip->mutex);			schedule();			remove_wait_queue(&chip->wq, &wait);			spin_lock(chip->mutex);			continue;		}		if (chip->erase_suspended) {			/* This erase was suspended and resumed.			   Adjust the timeout */			timeo = jiffies + (HZ*20); /* FIXME */			chip->erase_suspended = 0;		}		if (chip_ready(map, adr)) {			xip_enable(map, chip, adr);			break;		}		if (time_after(jiffies, timeo)) {			xip_enable(map, chip, adr);			printk(KERN_WARNING "MTD %s(): software timeout\n",				__func__ );			break;		}		/* Latency issues. Drop the lock, wait a while and retry */		UDELAY(map, chip, adr, 1000000/HZ);	}	/* Did we succeed? */	if (!chip_good(map, adr, map_word_ff(map))) {		/* reset on all failures. */		map_write( map, CMD(0xF0), chip->start );		/* FIXME - should have reset delay before continuing */		ret = -EIO;	}	chip->state = FL_READY;	put_chip(map, chip, adr);	spin_unlock(chip->mutex);	return ret;}int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr){	unsigned long ofs, len;	int ret;	ofs = instr->addr;	len = instr->len;	ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);	if (ret)		return ret;	instr->state = MTD_ERASE_DONE;	mtd_erase_callback(instr);		return 0;}static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	int ret = 0;	if (instr->addr != 0)		return -EINVAL;	if (instr->len != mtd->size)		return -EINVAL;	ret = do_erase_chip(map, &cfi->chips[0]);	if (ret)		return ret;	instr->state = MTD_ERASE_DONE;	mtd_erase_callback(instr);		return 0;}static void cfi_amdstd_sync (struct mtd_info *mtd){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	int i;	struct flchip *chip;	int ret = 0;	DECLARE_WAITQUEUE(wait, current);	for (i=0; !ret && i<cfi->numchips; i++) {		chip = &cfi->chips[i];	retry:		spin_lock(chip->mutex);		switch(chip->state) {		case FL_READY:		case FL_STATUS:		case FL_CFI_QUERY:		case FL_JEDEC_QUERY:			chip->oldstate = chip->state;			chip->state = FL_SYNCING;			/* No need to wake_up() on this state change - 			 * as the whole point is that nobody can do anything			 * with the chip now anyway.			 */		case FL_SYNCING:			spin_unlock(chip->mutex);			break;		default:			/* Not an idle state */			add_wait_queue(&chip->wq, &wait);						spin_unlock(chip->mutex);			schedule();			remove_wait_queue(&chip->wq, &wait);						goto retry;		}	}	/* Unlock the chips again */	for (i--; i >=0; i--) {		chip = &cfi->chips[i];		spin_lock(chip->mutex);				if (chip->state == FL_SYNCING) {			chip->state = chip->oldstate;			wake_up(&chip->wq);		}		spin_unlock(chip->mutex);	}}static int cfi_amdstd_suspend(struct mtd_info *mtd){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	int i;	struct flchip *chip;	int ret = 0;	for (i=0; !ret && i<cfi->numchips; i++) {		chip = &cfi->chips[i];		spin_lock(chip->mutex);		switch(chip->state) {		case FL_READY:		case FL_STATUS:		case FL_CFI_QUERY:		case FL_JEDEC_QUERY:			chip->oldstate = chip->state;			chip->state = FL_PM_SUSPENDED;			/* No need to wake_up() on this state change - 			 * as the whole point is that nobody can do anything			 * with the chip now anyway.			 */		case FL_PM_SUSPENDED:			break;		default:			ret = -EAGAIN;			break;		}		spin_unlock(chip->mutex);	}	/* Unlock the chips again */	if (ret) {		for (i--; i >=0; i--) {			chip = &cfi->chips[i];			spin_lock(chip->mutex);					if (chip->state == FL_PM_SUSPENDED) {				chip->state = chip->oldstate;				wake_up(&chip->wq);			}			spin_unlock(chip->mutex);		}	}		return ret;}static void cfi_amdstd_resume(struct mtd_info *mtd){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	int i;	struct flchip *chip;	for (i=0; i<cfi->numchips; i++) {			chip = &cfi->chips[i];		spin_lock(chip->mutex);				if (chip->state == FL_PM_SUSPENDED) {			chip->state = FL_READY;			map_write(map, CMD(0xF0), chip->start);			wake_up(&chip->wq);		}		else			printk(KERN_ERR "Argh. Chip not in PM_SUSPENDED state upon resume()\n");		spin_unlock(chip->mutex);	}}static void cfi_amdstd_destroy(struct mtd_info *mtd){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	kfree(cfi->cmdset_priv);	kfree(cfi->cfiq);	kfree(cfi);	kfree(mtd->eraseregions);}static char im_name[]="cfi_cmdset_0002";static int __init cfi_amdstd_init(void){	inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002);	return 0;}static void __exit cfi_amdstd_exit(void){	inter_module_unregister(im_name);}module_init(cfi_amdstd_init);module_exit(cfi_amdstd_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Crossnet Co. <info@crossnet.co.jp> et al.");MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips");

⌨️ 快捷键说明

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