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

📄 cfi_probe.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Common Flash Interface probe code.   (C) 2000 Red Hat. GPL'd.   $Id: cfi_probe.c,v 1.12 2000/07/03 13:29:16 dwmw2 Exp $*/#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <asm/io.h>#include <asm/byteorder.h>#include <linux/errno.h>#include <linux/malloc.h>#include <linux/mtd/map.h>#include <linux/mtd/cfi.h>struct mtd_info *cfi_probe(struct map_info *);static void print_cfi_ident(struct cfi_ident *);static void check_cmd_set(struct map_info *, int, unsigned long);static struct cfi_private *cfi_cfi_probe(struct map_info *);static const char im_name[] = "cfi_probe";/* This routine is made available to other mtd code via * inter_module_register.  It must only be accessed through * inter_module_get which will bump the use count of this module.  The * addresses passed back in mtd are valid as long as the use count of * this module is non-zero, i.e. between inter_module_get and * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000. */struct mtd_info *cfi_probe(struct map_info *map){	struct mtd_info *mtd = NULL;	struct cfi_private *cfi;	/* First probe the map to see if we have CFI stuff there. */	cfi = cfi_cfi_probe(map);		if (!cfi)		return NULL;	map->fldrv_priv = cfi;	map->im_name = im_name;	/* OK we liked it. Now find a driver for the command set it talks */	check_cmd_set(map, 1, cfi->chips[0].start); /* First the primary cmdset */	check_cmd_set(map, 0, cfi->chips[0].start); /* Then the secondary */		/* check_cmd_set() will have used inter_module_get to increase	   the use count of the module which provides the command set 	   driver. If we're quitting, we have to decrease it again.	*/	if(cfi->cmdset_setup) {		mtd = cfi->cmdset_setup(map);				if (mtd)			return mtd;		inter_module_put(cfi->im_name);	}	printk("No supported Vendor Command Set found\n");		kfree(cfi);	map->fldrv_priv = NULL;	return NULL;}static int cfi_probe_new_chip(struct map_info *map, unsigned long base,			      struct flchip *chips, struct cfi_private *cfi){	switch (map->buswidth) {			case 1: {		unsigned char tmp = map->read8(map, base + 0x55);		/* If there's a device there, put it in Query Mode */		map->write8(map, 0x98, base+0x55);				if (map->read8(map,base+0x10) == 'Q' &&		    map->read8(map,base+0x11) == 'R' &&		    map->read8(map,base+0x12) == 'Y') {			printk("%s: Found a CFI device at 0x%lx in 8 bit mode\n", map->name, base);			if (chips) {				/* Check previous chips for aliases */				printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__);				/* Put it back into Read Mode */				map->write8(map, 0x98, base+0x55);			}			return 1;		} else {			if (map->read8(map, base + 0x55) == 0x98) {				/* It looks like RAM. Put back the stuff we overwrote */				map->write8(map, tmp, base+0x55);			}			return 0;		}	}		case 2: {		__u16 tmp = map->read16(map, base + 0xaa);				/* If there's a device there, put it into Query Mode */		map->write16(map, 0x9898, base+0xAA);				if (map->read16(map, base+0x20) == cpu_to_le16(0x0051) &&		    map->read16(map, base+0x22) == cpu_to_le16(0x0052) &&		    map->read16(map, base+0x24) == cpu_to_le16(0x0059)) {			printk("%s: Found a CFI device at 0x%lx in 16 bit mode\n", map->name, base);			if (chips) {				/* Check previous chips for aliases */				int i;				for (i=0; i < cfi->numchips; i++) {					/* This chip should be in read mode if it's one 					   we've already touched. */					if (map->read16(map, chips[i].start+0x20) == cpu_to_le16(0x0051) &&					    map->read16(map, chips[i].start+0x22) == cpu_to_le16(0x0052) &&					    map->read16(map, chips[i].start+0x24) == cpu_to_le16(0x0059)){						/* Either the old chip has got 'Q''R''Y' in a most						   unfortunate place, or it's an alias of the new						   chip. Double-check that it's in read mode, and check. */						map->write16(map, 0xffff, chips[i].start+0x20);						if (map->read16(map, chips[i].start+0x20) == cpu_to_le16(0x0051) &&						    map->read16(map, chips[i].start+0x22) == cpu_to_le16(0x0052) &&						    map->read16(map, chips[i].start+0x24) == cpu_to_le16(0x0059)) {							/* Yes it's got QRY for data. Most unfortunate. 							   Stick the old one in read mode too. */							map->write16(map, 0xffff, base);							if (map->read16(map, base+0x20) == cpu_to_le16(0x0051) &&							    map->read16(map, base+0x22) == cpu_to_le16(0x0052) &&							    map->read16(map, base+0x24) == cpu_to_le16(0x0059)) {								/* OK, so has the new one. Assume it's an alias */								printk("T'was probably an alias for the chip at 0x%lx\n", chips[i].start);								return 1;							} /* else no, they're different, fall through. */						} else {							/* No the old one hasn't got QRY for data. Therefore,							   it's an alias of the new one. */							map->write16(map, 0xffff, base+0xaa);							/* Just to be paranoid. */							map->write16(map, 0xffff, chips[i].start+0xaa);							printk("T'was an alias for the chip at 0x%lx\n", chips[i].start);							return 1;						}					} 					/* No, the old one didn't look like it's in query mode. Next. */				}								/* OK, if we got to here, then none of the previous chips appear to				   be aliases for the current one. */				if (cfi->numchips == MAX_CFI_CHIPS) {					printk("%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS);					/* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */					return 1;				}				printk("Not an alias. Adding\n");				chips[cfi->numchips].start = base;				chips[cfi->numchips].state = FL_READY;				chips[cfi->numchips].mutex = &chips[cfi->numchips]._spinlock;				cfi->numchips++;				/* Put it back into Read Mode */				map->write16(map, 0xffff, base+0xaa);			}						return 1;		}			else if (map->read16(map, base+0x20) == 0x5151 &&			 map->read16(map, base+0x22) == 0x5252 &&			 map->read16(map, base+0x24) == 0x5959) {			printk("%s: Found a coupled pair of CFI devices at %lx in 8 bit mode\n",			       map->name, base);			if (chips) {				/* Check previous chips for aliases */				printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__);				/* Put it back into Read Mode */				map->write16(map, 0xffff, base+0xaa);			}			return 2;		} else {			if (map->read16(map, base+0xaa) == 0x9898) {				/* It looks like RAM. Put back the stuff we overwrote */				map->write16(map, tmp, base+0xaa);			}			return 0;		}	}			case 4: {		__u32 tmp = map->read32(map, base+0x154);				/* If there's a device there, put it into Query Mode */		map->write32(map, 0x98989898, base+0x154);				if (map->read32(map, base+0x40) == cpu_to_le32(0x00000051) &&		    map->read32(map, base+0x44) == cpu_to_le32(0x00000052) &&		    map->read32(map, base+0x48) == cpu_to_le32(0x00000059)) {				/* This isn't actually in the CFI spec - only x8 and x16 are. */			printk("%s: Found a CFI device at %lx in 32 bit mode\n", map->name, base);			if (chips) {				/* Check previous chips for aliases */				printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__);				/* Put it back into read mode */				map->write32(map, 0xffffffff, base+0x154);			}			return 1;		} 		else if (map->read32(map, base+0x40) == cpu_to_le32(0x00510051) &&			 map->read32(map, base+0x44) == cpu_to_le32(0x00520052) &&			 map->read32(map, base+0x48) == cpu_to_le32(0x00590059)) {			printk("%s: Found a coupled pair of CFI devices at location %lx in 16 bit mode\n", map->name, base);			if (chips) {				/* Check previous chips for aliases */				printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__);				/* Put it back into read mode */				map->write32(map, 0xffffffff, base+0x154);			}			return 2;		}		else if (map->read32(map, base+0x40) == 0x51515151 &&			 map->read32(map, base+0x44) == 0x52525252 &&			 map->read32(map, base+0x48) == 0x59595959) {			printk("%s: Found four side-by-side CFI devices at location %lx in 8 bit mode\n", map->name, base);			if (chips) {				/* Check previous chips for aliases */				printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__);				/* Put it back into read mode */				map->write32(map, 0xffffffff, base+0x154);			}			return 4;		} else {			if (map->read32(map, base+0x154) == 0x98989898) {				/* It looks like RAM. Put back the stuff we overwrote */				map->write32(map, tmp, base+0x154);			}			return 0;		}	}		default:		printk(KERN_WARNING "cfi_probe called with strange buswidth %d\n", map->buswidth);		return 0;	}}static struct cfi_private *cfi_cfi_probe(struct map_info *map){	unsigned long base=0;	struct cfi_private cfi;

⌨️ 快捷键说明

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