mtd/drivers/mtd/maps ichxrom.c,1.4,1.5

ebiederman at lnxi.com ebiederman at lnxi.com
Wed Jul 14 01:17:58 EDT 2004


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

Modified Files:
	ichxrom.c 
Log Message:
- In cfi_cmdset_0002 add error detection
- In cfi_cmdset_0002 add retries in do_write_one_word 
  For transient errors this make progress more likely.
  user space can only really retry at the block/sector level.
- In ichxrom add support for using non-firmware hub flash parts
- In ichxrom add support for using cfi flash parts
- In ichxrom add support for probing multiple bank widths.
  I still don't support multiple bank widths but this is as close as I come.


Index: ichxrom.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/maps/ichxrom.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ichxrom.c	12 Jul 2004 22:38:29 -0000	1.4
+++ ichxrom.c	14 Jul 2004 05:17:56 -0000	1.5
@@ -15,6 +15,7 @@
 #include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
+#include <linux/mtd/cfi.h>
 
 #define xstr(s) str(s)
 #define str(s) #s
@@ -24,6 +25,11 @@
 
 #define RESERVE_MEM_REGION 0
 
+
+#define MANUFACTURER_INTEL	0x0089
+#define I82802AB	0x00ad
+#define I82802AC	0x00ac
+
 #define ICHX_FWH_REGION_START	0xFF000000UL
 #define ICHX_FWH_REGION_SIZE	0x01000000UL
 #define BIOS_CNTL	0x4e
@@ -57,10 +63,22 @@
 	return addr - map->map_priv_1 + ICHX_FWH_REGION_START;
 }
 	
-static map_word ichxrom_read8(struct map_info *map, unsigned long ofs)
+static map_word ichxrom_read(struct map_info *map, unsigned long ofs)
 {
 	map_word val;
-	val.x[0] = __raw_readb(addr(map, ofs));
+	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;
 }
 
@@ -69,9 +87,16 @@
 	memcpy_fromio(to, addr(map, from), len);
 }
 
-static void ichxrom_write8(struct map_info *map, map_word d, unsigned long ofs)
+static void ichxrom_write(struct map_info *map, map_word d, unsigned long ofs)
 {
-	__raw_writeb(d.x[0], addr(map,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();
 }
 
@@ -86,9 +111,9 @@
 		.phys = NO_XIP,
 		.size = 0,
 		.bankwidth = 1,
-		.read = ichxrom_read8,
+		.read = ichxrom_read,
 		.copy_from = ichxrom_copy_from,
-		.write = ichxrom_write8,
+		.write = ichxrom_write,
 		.copy_to = ichxrom_copy_to,
 		/* Firmware hubs only use vpp when being programmed
 		 * in a factory setting.  So in-place programming
@@ -166,6 +191,8 @@
 	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
@@ -228,20 +255,41 @@
 	info->mtd = NULL;
 	info->map.map_priv_1 = info->window_addr;
 
-	map_size = ICHX_FWH_REGION_SIZE;
-	while(!info->mtd && (map_size > 0)) {
-		info->map.size = map_size;
-		info->mtd = do_map_probe("jedec_probe", &ichxrom_map.map);
-		map_size -= 512*1024;
+	/* 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;
+			}
+			map_size -= 512*1024;
+		}
+		if (info->mtd)
+			break;
 	}
 	if (!info->mtd) {
 		goto failed;
 	}
-	/* I know I can only be a firmware hub here so put
-	 * in the special lock and unlock routines.
-	 */
-	info->mtd->lock = ichxrom_lock;
-	info->mtd->unlock = ichxrom_unlock;
+	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(%u). fixing...\n",
+		       info->mtd->size, info->map.size);
+		info->mtd->size = info->map.size;
+	}
 		
 	info->mtd->owner = THIS_MODULE;
 	add_mtd_device(info->mtd);
@@ -298,7 +346,7 @@
 #endif
 }
 
-static struct pci_device_id ichxrom_pci_tbl[] = {
+static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, 
 	  PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, 
@@ -324,9 +372,10 @@
 static struct pci_dev *mydev;
 int __init init_ichxrom(void)
 {
-	struct pci_dev *pdev = NULL;
+	struct pci_dev *pdev;
 	struct pci_device_id *id;
 
+	pdev = NULL;
 	for (id = ichxrom_pci_tbl; id->vendor; id++) {
 		pdev = pci_find_device(id->vendor, id->device, NULL);
 		if (pdev) {





More information about the linux-mtd-cvs mailing list