mtd/drivers/mtd/maps amd76xrom.c,1.12,1.13 ichxrom.c,1.8,1.9

ebiederman at lnxi.com ebiederman at lnxi.com
Thu Aug 12 02:40:26 EDT 2004


Update of /home/cvs/mtd/drivers/mtd/maps
In directory phoenix.infradead.org:/tmp/cvs-serv5114/mtd/maps

Modified Files:
	amd76xrom.c ichxrom.c 
Log Message:
- Move support firmware hub style lock and unlock into fhw_lock.h (from cfi_cmdset_0002)
- Move cfi_varsize_frob into cfi_util from cfi_cmdset_0001.c and cfi_cmdset_0002.c
- reduce gen_probe probe failuers to a debug level message
- Modify cfi_fixup to take a struct mtd_info instead of a struct map_info
  So that the fixup routines can modify the mtd functions.
- Modify cfi_cmdset_0001() to allocate and initialize the mtd structure
  before calling cfi_fixup.
- Modify cfi_cmdset_0002() to allocate and initialize the mtd structure
  before calling cfi_fixup.
- Refactor the hard coded fixups in cfi_cmdset_0001 and cfi_cmdset_0002
  so the improved cfi_fixup infrastructure.
- Rewrote amd76xrom and ichxrom.
  They now report their starting physical address in their name.
  They now both handle multiple bankwidth configurations
  They both can create multipe mtd devices.
  They both now assume the rom windows are properly opened by the BIOS
   or whatever runs previous to them.
  Their code is now synchromized so it is almost identical, 
     and could be a starting point for a x86_rom_probe.



Index: amd76xrom.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/maps/amd76xrom.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- amd76xrom.c	14 Jul 2004 14:44:31 -0000	1.12
+++ amd76xrom.c	12 Aug 2004 06:40:23 -0000	1.13
@@ -12,61 +12,73 @@
 #include <asm/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
+#include <linux/mtd/cfi.h>
+#include <linux/mtd/flashchip.h>
 #include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
+#include <linux/list.h>
 
 
 #define xstr(s) str(s)
 #define str(s) #s
 #define MOD_NAME xstr(KBUILD_BASENAME)
 
-#define MTD_DEV_NAME_LENGTH 16
+#define ADDRESS_NAME_LEN 18
+
+#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
+
+struct amd76xrom_window {
+	void *virt;
+	unsigned long phys;
+	unsigned long size;
+	struct list_head maps;
+	struct resource rsrc;
+	struct pci_dev *pdev;
+};
 
 struct amd76xrom_map_info {
+	struct list_head list;
 	struct map_info map;
 	struct mtd_info *mtd;
-	unsigned long window_addr;
-	u32 window_start, window_size;
-	struct pci_dev *pdev;
-	struct resource window_rsrc;
-	struct resource rom_rsrc;
-	char mtd_name[MTD_DEV_NAME_LENGTH];
+	struct resource rsrc;
+	char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
 };
 
-
-static struct amd76xrom_map_info amd76xrom_map = {
-	.map = {
-		.name = MOD_NAME,
-		.size = 0,
-		.bankwidth = 1,
-	}
-	/* remaining fields of structure are initialized to 0 */
+static struct amd76xrom_window amd76xrom_window = {
+	.maps = LIST_HEAD_INIT(amd76xrom_window.maps),
 };
 
-
-static void amd76xrom_cleanup(struct amd76xrom_map_info *info)
+static void amd76xrom_cleanup(struct amd76xrom_window *window)
 {
+	struct amd76xrom_map_info *map, *scratch;
 	u8 byte;
 
-	/* Disable writes through the rom window */
-	pci_read_config_byte(info->pdev, 0x40, &byte);
-	pci_write_config_byte(info->pdev, 0x40, byte & ~1);
-
-	if (info->mtd) {
-		del_mtd_device(info->mtd);
-		map_destroy(info->mtd);
-		info->mtd = NULL;
-		info->map.virt = 0;
-	}
-	if (info->rom_rsrc.parent)
-		release_resource(&info->rom_rsrc);
-	if (info->window_rsrc.parent)
-		release_resource(&info->window_rsrc);
-
-	if (info->window_addr) {
-		iounmap((void *)(info->window_addr));
-		info->window_addr = 0;
+	if (window->pdev) {
+		/* Disable writes through the rom window */
+		pci_read_config_byte(window->pdev, 0x40, &byte);
+		pci_write_config_byte(window->pdev, 0x40, byte & ~1);
+	}
+
+	/* Free all of the mtd devices */
+	list_for_each_entry_safe(map, scratch, &window->maps, list) {
+		if (map->rsrc.parent) {
+			release_resource(&map->rsrc);
+		}
+		del_mtd_device(map->mtd);
+		map_destroy(map->mtd);
+		list_del(&map->list);
+		kfree(map);
+	}
+	if (window->rsrc.parent) 
+		release_resource(&window->rsrc);
+
+	if (window->virt) {
+		iounmap(window->virt);
+		window->virt = NULL;
+		window->phys = 0;
+		window->size = 0;
+		window->pdev = NULL;
 	}
 }
 
@@ -74,168 +86,181 @@
 static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
 	const struct pci_device_id *ent)
 {
-	struct rom_window {
-		u32 start;
-		u32 size;
-		u8 segen_bits;
-	};
-	static struct rom_window rom_window[] = {
-		/*
-		 * Need the 5MiB window for chips that have block lock/unlock
-		 * registers located below 4MiB window.
-		 */
-		{ 0xffb00000, 5*1024*1024, (1<<7) | (1<<6), },
-		{ 0xffc00000, 4*1024*1024, (1<<7), },
-		{ 0xffff0000, 64*1024,     0 },
-		{ 0         , 0,           0 },
-	};
-	static const u32 rom_probe_sizes[] = { 
-		5*1024*1024, 4*1024*1024, 2*1024*1024, 1024*1024, 512*1024, 
-		256*1024, 128*1024, 64*1024, 0};
 	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
 	u8 byte;
-	struct amd76xrom_map_info *info = &amd76xrom_map;
-	struct rom_window *window;
-	int i;
-	u32 rom_size;
-
-	info->pdev = pdev;
-	window = &rom_window[0];
-
-	while (window->size) {
-		/*
-		 * Try to reserve the window mem region.  If this fails then
-		 * it is likely due to a fragment of the window being
-		 * "reseved" by the BIOS.  In the case that the
-		 * request_mem_region() fails then once the rom size is
-		 * discovered we will try to reserve the unreserved fragment.
-		 */
-		info->window_rsrc.name = MOD_NAME;
-		info->window_rsrc.start = window->start;
-		info->window_rsrc.end = window->start + window->size - 1;
-		info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-		if (request_resource(&iomem_resource, &info->window_rsrc)) {
-			info->window_rsrc.parent = NULL;
-			printk(KERN_ERR MOD_NAME
-			       " %s(): Unable to register resource"
-			       " 0x%.08lx-0x%.08lx - kernel bug?\n",
-			       __func__,
-			       info->window_rsrc.start, info->window_rsrc.end);
-		}
+	struct amd76xrom_window *window = &amd76xrom_window;
+	struct amd76xrom_map_info *map;
+	unsigned long map_top;
+
+	/* Remember the pci dev I find the window in */
+	window->pdev = pdev;
+
+	/* Assume the rom window is properly setup, and find it's size */
+	pci_read_config_byte(pdev, 0x43, &byte);
+	if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) {
+		window->phys = 0xffb00000; /* 5MiB */
+	}
+	else if ((byte & (1<<7)) == (1<<7)) {
+		window->phys = 0xffc00000; /* 4MiB */
+	}
+	else {
+		window->phys = 0xffff0000; /* 64KiB */
+	}
+	window->size = 0xffffffffUL - window->phys + 1UL;
+	
+	/*
+	 * Try to reserve the window mem region.  If this fails then
+	 * it is likely due to a fragment of the window being
+	 * "reseved" by the BIOS.  In the case that the
+	 * request_mem_region() fails then once the rom size is
+	 * discovered we will try to reserve the unreserved fragment.
+	 */
+	window->rsrc.name = MOD_NAME;
+	window->rsrc.start = window->phys;
+	window->rsrc.end   = window->phys + window->size - 1;
+	window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	if (request_resource(&iomem_resource, &window->rsrc)) {
+		window->rsrc.parent = NULL;
+		printk(KERN_ERR MOD_NAME
+			" %s(): Unable to register resource"
+			" 0x%.08lx-0x%.08lx - kernel bug?\n",
+			__func__,
+			window->rsrc.start, window->rsrc.end);
+	}
 
-		/* Enable the selected rom window */
-		pci_read_config_byte(pdev, 0x43, &byte);
-		pci_write_config_byte(pdev, 0x43, byte | window->segen_bits);
-
-		/* Enable writes through the rom window */
-		pci_read_config_byte(pdev, 0x40, &byte);
-		pci_write_config_byte(pdev, 0x40, byte | 1);
-
-		/* FIXME handle registers 0x80 - 0x8C the bios region locks */
-
-		printk(KERN_NOTICE MOD_NAME " window : %x at %x\n", 
-		       window->size, window->start);
-		/* For write accesses caches are useless */
-		info->window_addr =
-			(unsigned long)ioremap_nocache(window->start,
-						       window->size);
-
-		if (!info->window_addr) {
-			printk(KERN_ERR "Failed to ioremap\n");
-			continue;
-		}
+#if 0
 
-		info->mtd = NULL;
+	/* Enable the selected rom window */
+	pci_read_config_byte(pdev, 0x43, &byte);
+	pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits);
+#endif
 
-		for(i = 0; (rom_size = rom_probe_sizes[i]); i++) {
-			char **chip_type;
-			if (rom_size > window->size) {
-				continue;
-			}
-			info->map.phys = window->start + window->size - rom_size;
-			info->map.virt = 
-				info->window_addr + window->size - rom_size;
-			info->map.size = rom_size;
-			simple_map_init(&info->map);
-			chip_type = rom_probe_types;
-			for(; !info->mtd && *chip_type; chip_type++) {
-				info->mtd = do_map_probe(*chip_type, &amd76xrom_map.map);
-			}
-			if (info->mtd) goto found_mtd;
-		}
-		iounmap((void *)(info->window_addr));
-		info->window_addr = 0;
+	/* Enable writes through the rom window */
+	pci_read_config_byte(pdev, 0x40, &byte);
+	pci_write_config_byte(pdev, 0x40, byte | 1);
+	
+	/* FIXME handle registers 0x80 - 0x8C the bios region locks */
+
+	/* For write accesses caches are useless */
+	window->virt = ioremap_nocache(window->phys, window->size);
+	if (!window->virt) {
+		printk(KERN_ERR MOD_NAME ": Failed to ioremap\n");
+		goto failed;
+	}
 
-		/* Disable writes through the rom window */
-		pci_read_config_byte(pdev, 0x40, &byte);
-		pci_write_config_byte(pdev, 0x40, byte & ~1);
+	/* Get the first address to look for an rom chip at */
+	map_top = window->phys;
 
-		window++;
-	}
-	goto failed;
+	/* Loop  trhough adn look for rom chips */
+	map = 0;
+	while((map_top - 1) < 0xffffffffUL) {
+		struct cfi_private *cfi;
+		unsigned long offset;
+		int i;
 
- found_mtd:
-	printk(KERN_NOTICE MOD_NAME " chip at offset: 0x%x\n",
-		window->size - rom_size);
-
-	info->mtd->owner = THIS_MODULE;
-
-	if (!info->window_rsrc.parent) {
-		/* failed to reserve entire window - try fragments */
-		info->window_rsrc.name = MOD_NAME;
-		info->window_rsrc.start = window->start;
-		info->window_rsrc.end = window->start + window->size - rom_size - 1;
-		info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-		if (request_resource(&iomem_resource, &info->window_rsrc)) {
-			printk(KERN_ERR MOD_NAME
-			       ": cannot reserve window resource fragment\n");
-#if 0
+		if (!map) {
+			map = kmalloc(sizeof(*map), GFP_KERNEL);
+		}
+		if (!map) {
+			printk(KERN_ERR MOD_NAME ": kmalloc failed");
+			goto failed;
+		}
+		memset(map, 0, sizeof(*map));
+		INIT_LIST_HEAD(&map->list);
+		map->map.name = map->map_name;
+		map->map.phys = map_top;
+		offset = map_top - window->phys;
+		map->map.virt = ((unsigned long)(window->virt)) + offset;
+		map->map.size = 0xffffffffUL - map_top + 1UL;
+		/* Set the name of the map to the address I am trying */
+		sprintf(map->map_name, "%s @%08lx",
+			MOD_NAME, map->map.phys);
+
+		/* There is not generic VPP support */
+		for(map->map.bankwidth = 32; map->map.bankwidth; 
+			map->map.bankwidth >>=1)
+		{
+			char **probe_type;
+			/* Skip bankwidths that are not supported */
+			if (!map_bankwidth_supported(map->map.bankwidth))
+				continue;
+
+			/* Setup the map methods */
+			simple_map_init(&map->map);
+			
+			/* Try all of the probe methods */
+			probe_type = rom_probe_types;
+			for(; *probe_type; probe_type++) {
+				map->mtd = do_map_probe(*probe_type, &map->map);
+				if (map->mtd)
+					goto found;
+			}
+		}
+		map_top += ROM_PROBE_STEP_SIZE;
+		continue;
+	found:
+		/* Trim the size of we are larger than the map */
+		if (map->mtd->size > map->map.size) {
+			printk(KERN_WARNING MOD_NAME
+				" rom(%u) larger than window(%lu). fixing...\n",
+				map->mtd->size, map->map.size);
+			map->mtd->size = map->map.size;
+		}
+		if (window->rsrc.parent) {
 			/*
-			 * The BIOS e820 usually reserves this so it isn't
-			 * usually an error.
+			 * Registering the MTD device in iomem may not be possible
+			 * if there is a BIOS "reserved" and BUSY range.  If this
+			 * fails then continue anyway.
 			 */
-			goto failed;
-#endif
+			map->rsrc.name  = map->map_name;
+			map->rsrc.start = map->map.phys;
+			map->rsrc.end   = map->map.phys + map->mtd->size - 1;
+			map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+			if (request_resource(&window->rsrc, &map->rsrc)) {
+				printk(KERN_ERR MOD_NAME
+					": cannot reserve MTD resource\n");
+				map->rsrc.parent = NULL;
+			}
 		}
-	}
 
-	add_mtd_device(info->mtd);
-	info->window_start = window->start;
-	info->window_size = window->size;
-
-	if (info->window_rsrc.parent) {
-		/*
-		 * Registering the MTD device in iomem may not be possible
-		 * if there is a BIOS "reserved" and BUSY range.  If this
-		 * fails then continue anyway.
-		 */
-		snprintf(info->mtd_name, MTD_DEV_NAME_LENGTH,
-			 "mtd%d", info->mtd->index);
-
-		info->rom_rsrc.name = info->mtd_name;
-		info->rom_rsrc.start = window->start + window->size - rom_size;
-		info->rom_rsrc.end = window->start + window->size - 1;
-		info->rom_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-		if (request_resource(&info->window_rsrc, &info->rom_rsrc)) {
-			printk(KERN_ERR MOD_NAME
-			       ": cannot reserve MTD resource\n");
-			info->rom_rsrc.parent = NULL;
+		/* Make the whole region visible in the map */
+		map->map.virt = (unsigned long)(window->virt);
+		map->map.phys = window->phys;
+		cfi = map->map.fldrv_priv;
+		for(i = 0; i < cfi->numchips; i++) {
+			cfi->chips[i].start += offset;
 		}
+		
+		/* Now that the mtd devices is complete claim and export it */
+		map->mtd->owner = THIS_MODULE;
+		add_mtd_device(map->mtd);
+
+
+		/* Calculate the new value of map_top */
+		map_top += map->mtd->size;
+
+		/* File away the map structure */
+		list_add(&map->list, &window->maps);
+		map = 0;
 	}
 
+	/* Free any left over map structures */
+	if (map) {
+		kfree(map);
+	}
 	return 0;
 
  failed:
-	amd76xrom_cleanup(info);
+	amd76xrom_cleanup(window);
 	return -ENODEV;
 }
 
 
 static void __devexit amd76xrom_remove_one (struct pci_dev *pdev)
 {
-	struct amd76xrom_map_info *info = &amd76xrom_map;
+	struct amd76xrom_window *window = &amd76xrom_window;
 
-	amd76xrom_cleanup(info);
+	amd76xrom_cleanup(window);
 }
 
 static struct pci_device_id amd76xrom_pci_tbl[] = {
@@ -270,7 +295,6 @@
 		}
 	}
 	if (pdev) {
-		amd76xrom_map.pdev = pdev;
 		return amd76xrom_init_one(pdev, &amd76xrom_pci_tbl[0]);
 	}
 	return -ENXIO;
@@ -281,7 +305,7 @@
 
 static void __exit cleanup_amd76xrom(void)
 {
-	amd76xrom_remove_one(amd76xrom_map.pdev);
+	amd76xrom_remove_one(amd76xrom_window.pdev);
 }
 
 module_init(init_amd76xrom);

Index: ichxrom.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/maps/ichxrom.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- ichxrom.c	16 Jul 2004 17:43:11 -0000	1.8
+++ ichxrom.c	12 Aug 2004 06:40:23 -0000	1.9
@@ -12,187 +12,87 @@
 #include <asm/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
+#include <linux/mtd/cfi.h>
+#include <linux/mtd/flashchip.h>
 #include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
-#include <linux/mtd/cfi.h>
+#include <linux/list.h>
 
 #define xstr(s) str(s)
 #define str(s) #s
 #define MOD_NAME xstr(KBUILD_BASENAME)
 
-#define MTD_DEV_NAME_LENGTH 16
-
-#define RESERVE_MEM_REGION 0
-
+#define ADDRESS_NAME_LEN 18
 
-#define MANUFACTURER_INTEL	0x0089
-#define I82802AB	0x00ad
-#define I82802AC	0x00ac
+#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
 
-#define ICHX_FWH_REGION_START	0xFF000000UL
-#define ICHX_FWH_REGION_SIZE	0x01000000UL
 #define BIOS_CNTL	0x4e
 #define FWH_DEC_EN1	0xE3
 #define FWH_DEC_EN2	0xF0
 #define FWH_SEL1	0xE8
 #define FWH_SEL2	0xEE
 
-struct ichxrom_map_info {
-	struct map_info map;
-	struct mtd_info *mtd;
-	unsigned long window_addr;
+struct ichxrom_window {
+	void * virt;
+	unsigned long phys;
+	unsigned long size;
+	struct list_head maps;
+	struct resource rsrc;
 	struct pci_dev *pdev;
-	struct resource window_rsrc;
-	struct resource rom_rsrc;
-	char mtd_name[MTD_DEV_NAME_LENGTH];
 };
 
-static inline unsigned long addr(struct map_info *map, unsigned long ofs)
-{
-	unsigned long offset;
-	offset = ((8*1024*1024) - map->size) + ofs;
-	if (offset >= (4*1024*1024)) {
-		offset += 0x400000;
-	}
-	return map->map_priv_1 + 0x400000 + offset;
-}
-
-static inline unsigned long dbg_addr(struct map_info *map, unsigned long addr)
-{
-	return addr - map->map_priv_1 + ICHX_FWH_REGION_START;
-}
-	
-static map_word ichxrom_read(struct map_info *map, unsigned long ofs)
-{
-	map_word val;
-	int i;
-	switch(map->bankwidth) {
-	case 1:	 val.x[0] = __raw_readb(addr(map, ofs)); break;
-	case 2:	 val.x[0] = __raw_readw(addr(map, ofs)); break;
-	case 4:	 val.x[0] = __raw_readl(addr(map, ofs)); break;
-#if BITS_PER_LONG >= 64
-	case 8:	 val.x[0] = __raw_readq(addr(map, ofs)); break;
-#endif
-	default: val.x[0] = 0; break;
-	}
-	for(i = 1; i < map_words(map); i++) {
-		val.x[i] = 0;
-	}
-	return val;
-}
-
-static void ichxrom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-{
-	memcpy_fromio(to, addr(map, from), len);
-}
-
-static void ichxrom_write(struct map_info *map, map_word d, unsigned long ofs)
-{
-	switch(map->bankwidth) {
-	case 1: __raw_writeb(d.x[0], addr(map,ofs)); break;
-	case 2: __raw_writew(d.x[0], addr(map,ofs)); break;
-	case 4: __raw_writel(d.x[0], addr(map,ofs)); break;
-#if BITS_PER_LONG >= 64
-	case 8: __raw_writeq(d.x[0], addr(map,ofs)); break;
-#endif
-	}
-	mb();
-}
-
-static void ichxrom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-{
-	memcpy_toio(addr(map, to), from, len);
-}
-
-static struct ichxrom_map_info ichxrom_map = {
-	.map = {
-		.name = MOD_NAME,
-		.phys = NO_XIP,
-		.size = 0,
-		.bankwidth = 1,
-		.read = ichxrom_read,
-		.copy_from = ichxrom_copy_from,
-		.write = ichxrom_write,
-		.copy_to = ichxrom_copy_to,
-		/* Firmware hubs only use vpp when being programmed
-		 * in a factory setting.  So in-place programming
-		 * needs to use a different method.
-		 */
-	},
-	/* remaining fields of structure are initialized to 0 */
+struct ichxrom_map_info {
+	struct list_head list;
+	struct map_info map;
+	struct mtd_info *mtd;
+	struct resource rsrc;
+	char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
 };
 
-enum fwh_lock_state {
-	FWH_DENY_WRITE = 1,
-	FWH_IMMUTABLE  = 2,
-	FWH_DENY_READ  = 4,
+static struct ichxrom_window ichxrom_window = {
+	.maps = LIST_HEAD_INIT(ichxrom_window.maps),
 };
 
-static void ichxrom_cleanup(struct ichxrom_map_info *info)
+static void ichxrom_cleanup(struct ichxrom_window *window)
 {
+	struct ichxrom_map_info *map, *scratch;
 	u16 word;
 
 	/* Disable writes through the rom window */
-	pci_read_config_word(info->pdev, BIOS_CNTL, &word);
-	pci_write_config_word(info->pdev, BIOS_CNTL, word & ~1);
-
-	if (info->mtd) {
-		del_mtd_device(info->mtd);
-		map_destroy(info->mtd);
-		info->mtd = NULL;
-		info->map.virt = 0;
-	}
-	if (info->rom_rsrc.parent)
-		release_resource(&info->rom_rsrc);
-	if (info->window_rsrc.parent)
-		release_resource(&info->window_rsrc);
-
-	if (info->window_addr) {
-		iounmap((void *)(info->window_addr));
-		info->window_addr = 0;
-	}
-}
-
+	pci_read_config_word(window->pdev, BIOS_CNTL, &word);
+	pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1);
 
-static int ichxrom_set_lock_state(struct mtd_info *mtd, loff_t ofs, size_t len,
-	enum fwh_lock_state state)
-{
-	struct map_info *map = mtd->priv;
-	unsigned long start = ofs;
-	unsigned long end = start + len -1;
-
-	/* FIXME do I need to guard against concurrency here? */
-	/* round down to 64K boundaries */
-	start = start & ~0xFFFF;
-	end = end & ~0xFFFF;
-	while (start <= end) {
-		unsigned long ctrl_addr;
-		ctrl_addr = addr(map, start) - 0x400000 + 2;
-		writeb(state, ctrl_addr);
-		start = start + 0x10000;
+	/* Free all of the mtd devices */
+	list_for_each_entry_safe(map, scratch, &window->maps, list) {
+		if (map->rsrc.parent)
+			release_resource(&map->rsrc);
+		del_mtd_device(map->mtd);
+		map_destroy(map->mtd);
+		list_del(&map->list);
+		kfree(map);
+	}
+	if (window->rsrc.parent)
+		release_resource(&window->rsrc);
+	if (window->virt) {
+		iounmap(window->virt);
+		window->virt = NULL;
+		window->phys = 0;
+		window->size = 0;
+		window->pdev = NULL;
 	}
-	return 0;
 }
 
-static int ichxrom_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
-	return ichxrom_set_lock_state(mtd, ofs, len, FWH_DENY_WRITE);
-}
-
-static int ichxrom_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
-	return ichxrom_set_lock_state(mtd, ofs, len, 0);
-}
 
 static int __devinit ichxrom_init_one (struct pci_dev *pdev,
 	const struct pci_device_id *ent)
 {
+	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+	struct ichxrom_window *window = &ichxrom_window;
+	struct ichxrom_map_info *map;
+	unsigned long map_top;
+	u8 byte;
 	u16 word;
-	struct ichxrom_map_info *info = &ichxrom_map;
-	unsigned long map_size;
-	static char *probes[] = { "cfi_probe", "jedec_probe" };
-	struct cfi_private *cfi;
 
 	/* For now I just handle the ichx and I assume there
 	 * are not a lot of resources up at the top of the address
@@ -204,26 +104,56 @@
 	 * Also you can page firmware hubs if an 8MB window isn't enough 
 	 * but don't currently handle that case either.
 	 */
+	window->pdev = pdev;
 
-	info->pdev = pdev;
+	/* Find a region continuous to the end of the ROM window  */
+	window->phys = 0;
+	pci_read_config_byte(pdev, FWH_DEC_EN1, &byte);
+	if (byte == 0xff) {
+		window->phys = 0xffc00000;
+		pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
+		if ((byte & 0x0f) == 0x0f) {
+			window->phys = 0xff400000;
+		}
+		else if ((byte & 0x0e) == 0x0e) {
+			window->phys = 0xff500000;
+		}
+		else if ((byte & 0x0c) == 0x0c) {
+			window->phys = 0xff600000;
+		}
+		else if ((byte & 0x08) == 0x08) {
+			window->phys = 0xff700000;
+		}
+	}
+	else if ((byte & 0xfe) == 0xfe) {
+		window->phys = 0xffc80000;
+	}
+	else if ((byte & 0xfc) == 0xfc) {
+		window->phys = 0xffd00000;
+	}
+	else if ((byte & 0xf8) == 0xf8) {
+		window->phys = 0xffd80000;
+	}
+	else if ((byte & 0xf0) == 0xf0) {
+		window->phys = 0xffe00000;
+	}
+	else if ((byte & 0xe0) == 0xe0) {
+		window->phys = 0xffe80000;
+	}
+	else if ((byte & 0xc0) == 0xc0) {
+		window->phys = 0xfff00000;
+	}
+	else if ((byte & 0x80) == 0x80) {
+		window->phys = 0xfff80000; 
+	}
 
-	/*
-	 * Try to reserve the window mem region.  If this fails then
-	 * it is likely due to the window being "reseved" by the BIOS.
-	 */
-	info->window_rsrc.name = MOD_NAME;
-	info->window_rsrc.start = ICHX_FWH_REGION_START;
-	info->window_rsrc.end = ICHX_FWH_REGION_START + ICHX_FWH_REGION_SIZE - 1;
-	info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-	if (request_resource(&iomem_resource, &info->window_rsrc)) {
-		info->window_rsrc.parent = NULL;
-		printk(KERN_ERR MOD_NAME
-		       " %s(): Unable to register resource"
-		       " 0x%.08lx-0x%.08lx - kernel bug?\n",
-		       __func__,
-		       info->window_rsrc.start, info->window_rsrc.end);
+	if (window->phys == 0) {
+		printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
+		goto failed;
 	}
-	
+	window->phys -= 0x400000UL;
+	window->size = (0xffffffffUL - window->phys) + 1UL;
+
 	/* Enable writes through the rom window */
 	pci_read_config_word(pdev, BIOS_CNTL, &word);
 	if (!(word & 1)  && (word & (1<<1))) {
@@ -235,115 +165,160 @@
 	}
 	pci_write_config_word(pdev, BIOS_CNTL, word | 1);
 
+	/*
+	 * Try to reserve the window mem region.  If this fails then
+	 * it is likely due to the window being "reseved" by the BIOS.
+	 */
+	window->rsrc.name = MOD_NAME;
+	window->rsrc.start = window->phys;
+	window->rsrc.end   = window->phys + window->size - 1;
+	window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	if (request_resource(&iomem_resource, &window->rsrc)) {
+		window->rsrc.parent = NULL;
+		printk(KERN_DEBUG MOD_NAME
+			": %s(): Unable to register resource"
+			" 0x%.08lx-0x%.08lx - kernel bug?\n",
+			__func__,
+			window->rsrc.start, window->rsrc.end);
+	}
 
 	/* Map the firmware hub into my address space. */
 	/* Does this use too much virtual address space? */
-	info->window_addr = (unsigned long)ioremap(
-		ICHX_FWH_REGION_START, ICHX_FWH_REGION_SIZE);
-	if (!info->window_addr) {
-		printk(KERN_ERR "Failed to ioremap\n");
+	window->virt = ioremap_nocache(window->phys, window->size);
+	if (!window->virt) {
+		printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
+			window->phys, window->size);
 		goto failed;
 	}
 
-	/* For now assume the firmware has setup all relevant firmware
-	 * windows.  We don't have enough information to handle this case
-	 * intelligently.
+	/* Get the first address to look for an rom chip at */
+	map_top = window->phys;
+	if ((window->phys & 0x3fffff) != 0) {
+		map_top = window->phys + 0x400000;
+	}
+#if 1
+	/* The probe sequence run over the firmware hub lock
+	 * registers sets them to 0x7 (no access).
+	 * Probe at most the last 4M of the address space.
 	 */
+	if (map_top < 0xffc00000) {
+		map_top = 0xffc00000;
+	}
+#endif
 
-	/* FIXME select the firmware hub and enable a window to it. */
+	/* Loop through and look for a rom chips */
+	map = 0;
+	while((map_top - 1) < 0xffffffffUL) {
+		struct cfi_private *cfi;
+		unsigned long offset;
+		int i;
 
-	info->mtd = NULL;
-	info->map.map_priv_1 = info->window_addr;
+		if (!map) {
+			map = kmalloc(sizeof(*map), GFP_KERNEL);
+		}
+		if (!map) {
+			printk(KERN_ERR MOD_NAME ": kmalloc failed");
+			goto failed;
+		}
+		memset(map, 0, sizeof(*map));
+		INIT_LIST_HEAD(&map->list);
+		map->map.name = map->map_name;
+		map->map.phys = map_top;
+		offset = map_top - window->phys;
+		map->map.virt = ((unsigned long)(window->virt)) + offset;
+		map->map.size = 0xffffffffUL - map_top + 1UL;
+		/* Set the name of the map to the address I am trying */
+		sprintf(map->map_name, "%s @%08lx",
+			MOD_NAME, map->map.phys);
 
-	/* Loop through the possible bankwidths */
-	for(ichxrom_map.map.bankwidth = 4; ichxrom_map.map.bankwidth; ichxrom_map.map.bankwidth >>= 1) {
-		map_size = ICHX_FWH_REGION_SIZE;
-		while(!info->mtd && (map_size > 0)) {
-			int i;
-			info->map.size = map_size;
-			for(i = 0; i < sizeof(probes)/sizeof(char *); i++) {
-				info->mtd = do_map_probe(probes[i], &ichxrom_map.map);
-				if (info->mtd)
-					break;
+		/* Firmware hubs only use vpp when being programmed
+		 * in a factory setting.  So in-place programming
+		 * needs to use a different method.
+		 */
+		for(map->map.bankwidth = 32; map->map.bankwidth; 
+			map->map.bankwidth >>= 1) 
+		{
+			char **probe_type;
+			/* Skip bankwidths that are not supported */
+			if (!map_bankwidth_supported(map->map.bankwidth))
+				continue;
+
+			/* Setup the map methods */
+			simple_map_init(&map->map);
+
+			/* Try all of the probe methods */
+			probe_type = rom_probe_types;
+			for(; *probe_type; probe_type++) {
+				map->mtd = do_map_probe(*probe_type, &map->map);
+				if (map->mtd)
+					goto found;
 			}
-			map_size -= 512*1024;
 		}
-		if (info->mtd)
-			break;
-	}
-	if (!info->mtd) {
-		goto failed;
-	}
-	cfi = ichxrom_map.map.fldrv_priv;
-	if ((cfi->mfr == MANUFACTURER_INTEL) && (
-		    (cfi->id == I82802AB) ||
-		    (cfi->id == I82802AC))) 
-	{
-		/* If it is a firmware hub put in the special lock
-		 * and unlock routines.
-		 */
-		info->mtd->lock = ichxrom_lock;
-		info->mtd->unlock = ichxrom_unlock;
-	}
-	if (info->mtd->size > info->map.size) {
-		printk(KERN_WARNING MOD_NAME " rom(%u) larger than window(%lu). fixing...\n",
-		       info->mtd->size, info->map.size);
-		info->mtd->size = info->map.size;
-	}
+		map_top += ROM_PROBE_STEP_SIZE;
+		continue;
+	found:
+		/* Trim the size if we are larger than the map */
+		if (map->mtd->size > map->map.size) {
+			printk(KERN_WARNING MOD_NAME 
+				" rom(%u) larger than window(%lu). fixing...\n",
+				map->mtd->size, map->map.size);
+			map->mtd->size = map->map.size;
+		}
+		if (window->rsrc.parent) {
+			/*
+			 * Registering the MTD device in iomem may not be possible
+			 * if there is a BIOS "reserved" and BUSY range.  If this
+			 * fails then continue anyway.
+			 */
+			map->rsrc.name  = map->map_name;
+			map->rsrc.start = map->map.phys;
+			map->rsrc.end   = map->map.phys + map->mtd->size - 1;
+			map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+			if (request_resource(&window->rsrc, &map->rsrc)) {
+				printk(KERN_ERR MOD_NAME
+					": cannot reserve MTD resource\n");
+				map->rsrc.parent = NULL;
+			}
+		}
+
+		/* Make the whole region visible in the map */
+		map->map.virt = (unsigned long)(window->virt);
+		map->map.phys = window->phys;
+		cfi = map->map.fldrv_priv;
+		for(i = 0; i < cfi->numchips; i++) {
+			cfi->chips[i].start += offset;
+		}
 		
-	info->mtd->owner = THIS_MODULE;
-	add_mtd_device(info->mtd);
+		/* Now that the mtd devices is complete claim and export it */
+		map->mtd->owner = THIS_MODULE;
+		add_mtd_device(map->mtd);
 
-	if (info->window_rsrc.parent) {
-		/*
-		 * Registering the MTD device in iomem may not be possible
-		 * if there is a BIOS "reserved" and BUSY range.  If this
-		 * fails then continue anyway.
-		 */
-		snprintf(info->mtd_name, MTD_DEV_NAME_LENGTH,
-			 "mtd%d", info->mtd->index);
 
-		info->rom_rsrc.name = info->mtd_name;
-		info->rom_rsrc.start = ICHX_FWH_REGION_START
-			+ ICHX_FWH_REGION_SIZE - map_size;
-		info->rom_rsrc.end = ICHX_FWH_REGION_START
-			+ ICHX_FWH_REGION_SIZE;
-		info->rom_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-		if (request_resource(&info->window_rsrc, &info->rom_rsrc)) {
-			printk(KERN_ERR MOD_NAME
-			       ": cannot reserve MTD resource\n");
-			info->rom_rsrc.parent = NULL;
-		}
+		/* Calculate the new value of map_top */
+		map_top += map->mtd->size;
+
+		/* File away the map structure */
+		list_add(&map->list, &window->maps);
+		map = 0;
+	}
+
+	/* Free any left over map structures */
+	if (map) {
+		kfree(map);
 	}
 
 	return 0;
 
  failed:
-	ichxrom_cleanup(info);
+	ichxrom_cleanup(window);
 	return -ENODEV;
 }
 
 
 static void __devexit ichxrom_remove_one (struct pci_dev *pdev)
 {
-	struct ichxrom_map_info *info = &ichxrom_map;
-	u16 word;
-
-	del_mtd_device(info->mtd);
-	map_destroy(info->mtd);
-	info->mtd = NULL;
-	info->map.map_priv_1 = 0;
-
-	iounmap((void *)(info->window_addr));
-	info->window_addr = 0;
-
-	/* Disable writes through the rom window */
-	pci_read_config_word(pdev, BIOS_CNTL, &word);
-	pci_write_config_word(pdev, BIOS_CNTL, word & ~1);
-
-#if RESERVE_MEM_REGION	
-	release_mem_region(ICHX_FWH_REGION_START, ICHX_FWH_REGION_SIZE);
-#endif
+	struct ichxrom_window *window = &ichxrom_window;
+	ichxrom_cleanup(window);
 }
 
 static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = {
@@ -371,7 +346,6 @@
 };
 #endif
 
-static struct pci_dev *mydev;
 int __init init_ichxrom(void)
 {
 	struct pci_dev *pdev;
@@ -385,7 +359,6 @@
 		}
 	}
 	if (pdev) {
-		mydev = pdev;
 		return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]);
 	}
 	return -ENXIO;
@@ -396,7 +369,7 @@
 
 static void __exit cleanup_ichxrom(void)
 {
-	ichxrom_remove_one(mydev);
+	ichxrom_remove_one(ichxrom_window.pdev);
 }
 
 module_init(init_ichxrom);





More information about the linux-mtd-cvs mailing list