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

📄 amd_flash.c

📁 老版本的mtd-snap
💻 C
📖 第 1 页 / 共 3 页
字号:
		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },			{ .offset = 0x1F0000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x1F8000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x1FC000, .erasesize = 0x04000, .numblocks =  1 }		}	}, {		.mfr_id = MANUFACTURER_TOSHIBA,		.dev_id = TC58FVB160,		.name = "Toshiba TC58FVB160",		.size = 0x00200000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }		}	}, {		.mfr_id = MANUFACTURER_FUJITSU,		.dev_id = MBM29LV160BE,		.name = "Fujitsu MBM29LV160BE",		.size = 0x00200000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }		}	}, {		.mfr_id = MANUFACTURER_AMD,		.dev_id = AM29LV800BB,		.name = "AMD AM29LV800BB",		.size = 0x00100000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }		}	}, {		.mfr_id = MANUFACTURER_AMD,		.dev_id = AM29F800BB,		.name = "AMD AM29F800BB",		.size = 0x00100000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }		}	}, {		.mfr_id = MANUFACTURER_AMD,		.dev_id = AM29LV800BT,		.name = "AMD AM29LV800BT",		.size = 0x00100000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },			{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }		}	}, {		.mfr_id = MANUFACTURER_AMD,		.dev_id = AM29F800BT,		.name = "AMD AM29F800BT",		.size = 0x00100000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },			{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }		}	}, {		.mfr_id = MANUFACTURER_AMD,		.dev_id = AM29LV800BB,		.name = "AMD AM29LV800BB",		.size = 0x00100000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },			{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }		}	}, {		.mfr_id = MANUFACTURER_FUJITSU,		.dev_id = MBM29LV800BB,		.name = "Fujitsu MBM29LV800BB",		.size = 0x00100000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }		}	}, {		.mfr_id = MANUFACTURER_ST,		.dev_id = M29W800T,		.name = "ST M29W800T",		.size = 0x00100000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },			{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }		}	}, {		.mfr_id = MANUFACTURER_ST,		.dev_id = M29W160DT,		.name = "ST M29W160DT",		.size = 0x00200000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },			{ .offset = 0x1F0000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x1F8000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x1FC000, .erasesize = 0x04000, .numblocks =  1 }		}	}, {		.mfr_id = MANUFACTURER_ST,		.dev_id = M29W160DB,		.name = "ST M29W160DB",		.size = 0x00200000,		.numeraseregions = 4,		.regions = {			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }		}	}, {		.mfr_id = MANUFACTURER_AMD,		.dev_id = AM29BDS323D,		.name = "AMD AM29BDS323D",		.size = 0x00400000,		.numeraseregions = 3,		.regions = {			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 48 },			{ .offset = 0x300000, .erasesize = 0x10000, .numblocks = 15 },			{ .offset = 0x3f0000, .erasesize = 0x02000, .numblocks =  8 },		}	}, {		.mfr_id = MANUFACTURER_ATMEL,		.dev_id = AT49xV16x,		.name = "Atmel AT49xV16x",		.size = 0x00200000,		.numeraseregions = 2,		.regions = {			{ .offset = 0x000000, .erasesize = 0x02000, .numblocks =  8 },			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }		}	}, {		.mfr_id = MANUFACTURER_ATMEL,		.dev_id = AT49xV16xT,		.name = "Atmel AT49xV16xT",		.size = 0x00200000,		.numeraseregions = 2,		.regions = {			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },			{ .offset = 0x1F0000, .erasesize = 0x02000, .numblocks =  8 }		}	} 	};	struct mtd_info *mtd;	struct flchip chips[MAX_AMD_CHIPS];	int table_pos[MAX_AMD_CHIPS];	struct amd_flash_private temp;	struct amd_flash_private *private;	u_long size;	unsigned long base;	int i;	int reg_idx;	int offset;	mtd = (struct mtd_info*)kmalloc(sizeof(*mtd), GFP_KERNEL);	if (!mtd) {		printk(KERN_WARNING		       "%s: kmalloc failed for info structure\n", map->name);		return NULL;	}	memset(mtd, 0, sizeof(*mtd));	mtd->priv = map;	memset(&temp, 0, sizeof(temp));	printk("%s: Probing for AMD compatible flash...\n", map->name);	if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table,					   sizeof(table)/sizeof(table[0])))	    == -1) {		printk(KERN_WARNING		       "%s: Found no AMD compatible device at location zero\n",		       map->name);		kfree(mtd);		return NULL;	}	chips[0].start = 0;	chips[0].state = FL_READY;	chips[0].mutex = &chips[0]._spinlock;	temp.numchips = 1;	for (size = mtd->size; size > 1; size >>= 1) {		temp.chipshift++;	}	switch (temp.interleave) {		case 2:			temp.chipshift += 1;			break;		case 4:			temp.chipshift += 2;			break;	}	/* Find out if there are any more chips in the map. */	for (base = (1 << temp.chipshift);	     base < map->size;	     base += (1 << temp.chipshift)) {	     	int numchips = temp.numchips;		table_pos[numchips] = probe_new_chip(mtd, base, chips,			&temp, table, sizeof(table)/sizeof(table[0]));	}	mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) *				    mtd->numeraseregions, GFP_KERNEL);	if (!mtd->eraseregions) { 		printk(KERN_WARNING "%s: Failed to allocate "		       "memory for MTD erase region info\n", map->name);		kfree(mtd);		map->fldrv_priv = NULL;		return NULL;	}	reg_idx = 0;	offset = 0;	for (i = 0; i < temp.numchips; i++) {		int dev_size;		int j;		dev_size = 0;		for (j = 0; j < table[table_pos[i]].numeraseregions; j++) {			mtd->eraseregions[reg_idx].offset = offset +				(table[table_pos[i]].regions[j].offset *				 temp.interleave);			mtd->eraseregions[reg_idx].erasesize =				table[table_pos[i]].regions[j].erasesize *				temp.interleave;			mtd->eraseregions[reg_idx].numblocks =				table[table_pos[i]].regions[j].numblocks;			if (mtd->erasesize <			    mtd->eraseregions[reg_idx].erasesize) {				mtd->erasesize =					mtd->eraseregions[reg_idx].erasesize;			}			dev_size += mtd->eraseregions[reg_idx].erasesize *				    mtd->eraseregions[reg_idx].numblocks;			reg_idx++;		}		offset += dev_size;	}	mtd->type = MTD_NORFLASH;	mtd->flags = MTD_CAP_NORFLASH;	mtd->name = map->name;	mtd->erase = amd_flash_erase;		mtd->read = amd_flash_read;		mtd->write = amd_flash_write;		mtd->sync = amd_flash_sync;		mtd->suspend = amd_flash_suspend;		mtd->resume = amd_flash_resume;		mtd->lock = amd_flash_lock;	mtd->unlock = amd_flash_unlock;	private = kmalloc(sizeof(*private) + (sizeof(struct flchip) *					      temp.numchips), GFP_KERNEL);	if (!private) {		printk(KERN_WARNING		       "%s: kmalloc failed for private structure\n", map->name);		kfree(mtd);		map->fldrv_priv = NULL;		return NULL;	}	memcpy(private, &temp, sizeof(temp));	memcpy(private->chips, chips,	       sizeof(struct flchip) * private->numchips);	for (i = 0; i < private->numchips; i++) {		init_waitqueue_head(&private->chips[i].wq);		spin_lock_init(&private->chips[i]._spinlock);	}	map->fldrv_priv = private;	map->fldrv = &amd_flash_chipdrv;	__module_get(THIS_MODULE);	return mtd;}static inline int read_one_chip(struct map_info *map, struct flchip *chip,			       loff_t adr, size_t len, u_char *buf){	DECLARE_WAITQUEUE(wait, current);	unsigned long timeo = jiffies + HZ;retry:	spin_lock_bh(chip->mutex);	if (chip->state != FL_READY){		printk(KERN_INFO "%s: waiting for chip to read, state = %d\n",		       map->name, chip->state);		set_current_state(TASK_UNINTERRUPTIBLE);		add_wait_queue(&chip->wq, &wait);                		spin_unlock_bh(chip->mutex);		schedule();		remove_wait_queue(&chip->wq, &wait);		if(signal_pending(current)) {			return -EINTR;		}		timeo = jiffies + HZ;		goto retry;	}		adr += chip->start;	chip->state = FL_READY;	map_copy_from(map, buf, adr, len);	wake_up(&chip->wq);	spin_unlock_bh(chip->mutex);	return 0;}static int amd_flash_read(struct mtd_info *mtd, loff_t from, size_t len,			  size_t *retlen, u_char *buf){	struct map_info *map = mtd->priv;	struct amd_flash_private *private = map->fldrv_priv;	unsigned long ofs;	int chipnum;	int ret = 0;	if ((from + len) > mtd->size) {		printk(KERN_WARNING "%s: read request past end of device "		       "(0x%lx)\n", map->name, (unsigned long)from + len);		return -EINVAL;	}	/* Offset within the first chip that the first read should start. */	chipnum = (from >> private->chipshift);	ofs = from - (chipnum <<  private->chipshift);	*retlen = 0;	while (len) {		unsigned long this_len;		if (chipnum >= private->numchips) {			break;		}		if ((len + ofs - 1) >> private->chipshift) {			this_len = (1 << private->chipshift) - ofs;		} else {			this_len = len;		}		ret = read_one_chip(map, &private->chips[chipnum], ofs,				    this_len, buf);		if (ret) {			break;		}		*retlen += this_len;		len -= this_len;		buf += this_len;		ofs = 0;		chipnum++;	}	return ret;}static int write_one_word(struct map_info *map, struct flchip *chip,			  unsigned long adr, __u32 datum){	unsigned long timeo = jiffies + HZ;	struct amd_flash_private *private = map->fldrv_priv;	DECLARE_WAITQUEUE(wait, current);	int ret = 0;	int times_left;retry:	spin_lock_bh(chip->mutex);	if (chip->state != FL_READY){		printk("%s: waiting for chip to write, state = %d\n",		       map->name, chip->state);		set_current_state(TASK_UNINTERRUPTIBLE);		add_wait_queue(&chip->wq, &wait);                		spin_unlock_bh(chip->mutex);		schedule();		remove_wait_queue(&chip->wq, &wait);		printk(KERN_INFO "%s: woke up to write\n", map->name);		if(signal_pending(current))			return -EINTR;		timeo = jiffies + HZ;		goto retry;	}		chip->state = FL_WRITING;	adr += chip->start;	ENABLE_VPP(map);	send_cmd(map, chip->start, CMD_PROGRAM_UNLOCK_DATA);	wide_write(map, datum, adr);	times_left = 500000;	while (times_left-- && flash_is_busy(map, adr, private->interleave)) { 		if (need_resched()) {			spin_unlock_bh(chip->mutex);			schedule();			spin_lock_bh(chip->mutex);		}	}	if (!times_left) {		printk(KERN_WARNING "%s: write to 0x%lx timed out!\n",		       map->name, adr);		ret = -EIO;	} else {		__u32 verify;		if ((verify = wide_read(map, adr)) != datum) {			printk(KERN_WARNING "%s: write to 0x%lx failed. "			       "datum = %x, verify = %x\n",			       map->name, adr, datum, verify);			ret = -EIO;		}	}	DISABLE_VPP(map);

⌨️ 快捷键说明

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