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

📄 cfi_cmdset_0002.c

📁 基于linux-2.6.28的mtd驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
			return -EINTR;#endif		timeo = jiffies + HZ;		goto retry;	}	adr += chip->start;	chip->state = FL_READY;	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(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	map_copy_from(map, buf, adr, len);	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(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	wake_up(&chip->wq);	spin_unlock(chip->mutex);	return 0;}static int cfi_amdstd_secsi_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	unsigned long ofs;	int chipnum;	int ret = 0;	/* ofs: offset within the first chip that the first read should start */	/* 8 secsi bytes per chip */	chipnum=from>>3;	ofs=from & 7;	*retlen = 0;	while (len) {		unsigned long thislen;		if (chipnum >= cfi->numchips)			break;		if ((len + ofs -1) >> 3)			thislen = (1<<3) - ofs;		else			thislen = len;		ret = do_read_secsi_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);		if (ret)			break;		*retlen += thislen;		len -= thislen;		buf += thislen;		ofs = 0;		chipnum++;	}	return ret;}static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum){	struct cfi_private *cfi = map->fldrv_priv;	unsigned long timeo = jiffies + HZ;	/*	 * We use a 1ms + 1 jiffies generic timeout for writes (most devices	 * have a max write time of a few hundreds usec). However, we should	 * use the maximum timeout value given by the chip at probe time	 * instead.  Unfortunately, struct flchip does have a field for	 * maximum timeout, only for typical which can be far too short	 * depending of the conditions.	 The ' + 1' is to avoid having a	 * timeout of 0 jiffies if HZ is smaller than 1000.	 */	unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;	int ret = 0;	map_word oldd;	int retry_cnt = 0;	adr += chip->start;	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(): WRITE 0x%.8lx(0x%.8lx)\n",	       __func__, adr, datum.x[0] );	/*	 * Check for a NOP for the case when the datum to write is already	 * present - it saves time and works around buggy chips that corrupt	 * data at other locations when 0xff is written to a location that	 * already contains 0xff.	 */	oldd = map_read(map, adr);	if (map_word_equal(map, oldd, datum)) {		DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n",		       __func__);		goto op_done;	}	XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));	ENABLE_VPP(map);	xip_disable(map, chip, adr); retry:	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(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	map_write(map, datum, adr);	chip->state = FL_WRITING;	INVALIDATE_CACHE_UDELAY(map, chip,				adr, map_bankwidth(map),				chip->word_write_time);	/* See comment above for timeout value. */	timeo = jiffies + uWriteTimeout;	for (;;) {		if (chip->state != FL_WRITING) {			/* Someone's suspended the write. Sleep */			DECLARE_WAITQUEUE(wait, current);			set_current_state(TASK_UNINTERRUPTIBLE);			add_wait_queue(&chip->wq, &wait);			spin_unlock(chip->mutex);			schedule();			remove_wait_queue(&chip->wq, &wait);			timeo = jiffies + (HZ / 2); /* FIXME */			spin_lock(chip->mutex);			continue;		}		if (time_after(jiffies, timeo) && !chip_ready(map, adr)){			xip_enable(map, chip, adr);			printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);			xip_disable(map, chip, adr);			break;		}		if (chip_ready(map, adr))			break;		/* Latency issues. Drop the lock, wait a while and retry */		UDELAY(map, chip, adr, 1);	}	/* Did we succeed? */	if (!chip_good(map, adr, datum)) {		/* reset on all failures. */		map_write( map, CMD(0xF0), chip->start );		/* FIXME - should have reset delay before continuing */		if (++retry_cnt <= MAX_WORD_RETRIES)			goto retry;		ret = -EIO;	}	xip_enable(map, chip, adr); op_done:	chip->state = FL_READY;	put_chip(map, chip, adr);	spin_unlock(chip->mutex);	return ret;}static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,				  size_t *retlen, const u_char *buf){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	int ret = 0;	int chipnum;	unsigned long ofs, chipstart;	DECLARE_WAITQUEUE(wait, current);	*retlen = 0;	if (!len)		return 0;	chipnum = to >> cfi->chipshift;	ofs = to  - (chipnum << cfi->chipshift);	chipstart = cfi->chips[chipnum].start;	/* If it's not bus-aligned, do the first byte write */	if (ofs & (map_bankwidth(map)-1)) {		unsigned long bus_ofs = ofs & ~(map_bankwidth(map)-1);		int i = ofs - bus_ofs;		int n = 0;		map_word tmp_buf; retry:		spin_lock(cfi->chips[chipnum].mutex);		if (cfi->chips[chipnum].state != FL_READY) {#if 0			printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);#endif			set_current_state(TASK_UNINTERRUPTIBLE);			add_wait_queue(&cfi->chips[chipnum].wq, &wait);			spin_unlock(cfi->chips[chipnum].mutex);			schedule();			remove_wait_queue(&cfi->chips[chipnum].wq, &wait);#if 0			if(signal_pending(current))				return -EINTR;#endif			goto retry;		}		/* Load 'tmp_buf' with old contents of flash */		tmp_buf = map_read(map, bus_ofs+chipstart);		spin_unlock(cfi->chips[chipnum].mutex);		/* Number of bytes to copy from buffer */		n = min_t(int, len, map_bankwidth(map)-i);		tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);		ret = do_write_oneword(map, &cfi->chips[chipnum],				       bus_ofs, tmp_buf);		if (ret)			return ret;		ofs += n;		buf += n;		(*retlen) += n;		len -= n;		if (ofs >> cfi->chipshift) {			chipnum ++;			ofs = 0;			if (chipnum == cfi->numchips)				return 0;		}	}	/* We are now aligned, write as much as possible */	while(len >= map_bankwidth(map)) {		map_word datum;		datum = map_word_load(map, buf);		ret = do_write_oneword(map, &cfi->chips[chipnum],				       ofs, datum);		if (ret)			return ret;		ofs += map_bankwidth(map);		buf += map_bankwidth(map);		(*retlen) += map_bankwidth(map);		len -= map_bankwidth(map);		if (ofs >> cfi->chipshift) {			chipnum ++;			ofs = 0;			if (chipnum == cfi->numchips)				return 0;			chipstart = cfi->chips[chipnum].start;		}	}	/* Write the trailing bytes if any */	if (len & (map_bankwidth(map)-1)) {		map_word tmp_buf; retry1:		spin_lock(cfi->chips[chipnum].mutex);		if (cfi->chips[chipnum].state != FL_READY) {#if 0			printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);#endif			set_current_state(TASK_UNINTERRUPTIBLE);			add_wait_queue(&cfi->chips[chipnum].wq, &wait);			spin_unlock(cfi->chips[chipnum].mutex);			schedule();			remove_wait_queue(&cfi->chips[chipnum].wq, &wait);#if 0			if(signal_pending(current))				return -EINTR;#endif			goto retry1;		}		tmp_buf = map_read(map, ofs + chipstart);		spin_unlock(cfi->chips[chipnum].mutex);		tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);		ret = do_write_oneword(map, &cfi->chips[chipnum],				ofs, tmp_buf);		if (ret)			return ret;		(*retlen) += len;	}	return 0;}/* * FIXME: interleaved mode not tested, and probably not supported! */static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,				    unsigned long adr, const u_char *buf,				    int len){	struct cfi_private *cfi = map->fldrv_priv;	unsigned long timeo = jiffies + HZ;	/* see comments in do_write_oneword() regarding uWriteTimeo. */	unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;	int ret = -EIO;	unsigned long cmd_adr;	int z, words;	map_word datum;	adr += chip->start;	cmd_adr = adr;	spin_lock(chip->mutex);	ret = get_chip(map, chip, adr, FL_WRITING);	if (ret) {		spin_unlock(chip->mutex);		return ret;	}	datum = map_word_load(map, buf);	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",	       __func__, adr, datum.x[0] );	XIP_INVAL_CACHED_RANGE(map, adr, len);	ENABLE_VPP(map);	xip_disable(map, chip, cmd_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(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);	/* Write Buffer Load */	map_write(map, CMD(0x25), cmd_adr);	chip->state = FL_WRITING_TO_BUFFER;	/* Write length of data to come */	words = len / map_bankwidth(map);	map_write(map, CMD(words - 1), cmd_adr);	/* Write data */	z = 0;	while(z < words * map_bankwidth(map)) {		datum = map_word_load(map, buf);		map_write(map, datum, adr + z);		z += map_bankwidth(map);		buf += map_bankwidth(map);	}	z -= map_bankwidth(map);	adr += z;	/* Write Buffer Program Confirm: GO GO GO */	map_write(map, CMD(0x29), cmd_adr);	chip->state = FL_WRITING;	INVALIDATE_CACHE_UDELAY(map, chip,				adr, map_bankwidth(map),				chip->word_write_time);	timeo = jiffies + uWriteTimeout;	for (;;) {		if (chip->state != FL_WRITING) {			/* Someone's suspended the write. Sleep */			DECLARE_WAITQUEUE(wait, current);			set_current_state(TASK_UNINTERRUPTIBLE);			add_wait_queue(&chip->wq, &wait);			spin_unlock(chip->mutex);			schedule();			remove_wait_queue(&chip->wq, &wait);			timeo = jiffies + (HZ / 2); /* FIXME */			spin_lock(chip->mutex);			continue;		}		if (time_after(jiffies, timeo) && !chip_ready(map, adr))			break;		if (chip_ready(map, adr)) {			xip_enable(map, chip, adr);			goto op_done;		}		/* Latency issues. Drop the lock, wait a while and retry */		UDELAY(map, chip, adr, 1);	}	/* reset on all failures. */	map_write( map, CMD(0xF0), chip->start );	xip_enable(map, chip, adr);	/* FIXME - should have reset delay before continuing */	printk(KERN_WARNING "MTD %s(): software timeout\n",	       __func__ );	ret = -EIO; op_done:	chip->state = FL_READY;	put_chip(map, chip, adr);	spin_unlock(chip->mutex);	return ret;}static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,				    size_t *retlen, const u_char *buf){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;	int ret = 0;	int chipnum;	unsigned long ofs;	*retlen = 0;	if (!len)		return 0;	chipnum = to >> cfi->chipshift;	ofs = to  - (chipnum << cfi->chipshift);	/* If it's not bus-aligned, do the first word write */	if (ofs & (map_bankwidth(map)-1)) {		size_t local_len = (-ofs)&(map_bankwidth(map)-1);		if (local_len > len)			local_len = len;		ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<<cfi->chipshift),					     local_len, retlen, buf);		if (ret)			return ret;		ofs += local_len;		buf += local_len;		len -= local_len;		if (ofs >> cfi->chipshift) {			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],

⌨️ 快捷键说明

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