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

📄 mtd.patch

📁 patches for linux-2.6.
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
 static int cfi_intelext_suspend(struct mtd_info *mtd) { 	struct map_info *map = mtd->priv;@@ -2125,10 +2397,46 @@ 	} } +static int cfi_intelext_reset(struct mtd_info *mtd)+{+	struct map_info *map = mtd->priv;+	struct cfi_private *cfi = map->fldrv_priv;+	int i, ret;++	for (i=0; i < cfi->numchips; i++) {+		struct flchip *chip = &cfi->chips[i];++		/* force the completion of any ongoing operation+		   and switch to array mode so any bootloader in +		   flash is accessible for soft reboot. */+		spin_lock(chip->mutex);+		ret = get_chip(map, chip, chip->start, FL_SYNCING);+		if (!ret) {+			map_write(map, CMD(0xff), chip->start);+			chip->state = FL_READY;+		}+		spin_unlock(chip->mutex);+	}++	return 0;+}++static int cfi_intelext_reboot(struct notifier_block *nb, unsigned long val,+			       void *v)+{+	struct mtd_info *mtd;++	mtd = container_of(nb, struct mtd_info, reboot_notifier);+	cfi_intelext_reset(mtd);+	return NOTIFY_DONE;+}+ static void cfi_intelext_destroy(struct mtd_info *mtd) { 	struct map_info *map = mtd->priv; 	struct cfi_private *cfi = map->fldrv_priv;+	cfi_intelext_reset(mtd);+	unregister_reboot_notifier(&mtd->reboot_notifier); 	kfree(cfi->cmdset_priv); 	kfree(cfi->cfiq); 	kfree(cfi->chips[0].priv);@@ -2136,20 +2444,23 @@ 	kfree(mtd->eraseregions); } -static char im_name_1[]="cfi_cmdset_0001";-static char im_name_3[]="cfi_cmdset_0003";+static char im_name_0001[] = "cfi_cmdset_0001";+static char im_name_0003[] = "cfi_cmdset_0003";+static char im_name_0200[] = "cfi_cmdset_0200";  static int __init cfi_intelext_init(void) {-	inter_module_register(im_name_1, THIS_MODULE, &cfi_cmdset_0001);-	inter_module_register(im_name_3, THIS_MODULE, &cfi_cmdset_0001);+	inter_module_register(im_name_0001, THIS_MODULE, &cfi_cmdset_0001);+	inter_module_register(im_name_0003, THIS_MODULE, &cfi_cmdset_0001);+	inter_module_register(im_name_0200, THIS_MODULE, &cfi_cmdset_0001); 	return 0; }  static void __exit cfi_intelext_exit(void) {-	inter_module_unregister(im_name_1);-	inter_module_unregister(im_name_3);+	inter_module_unregister(im_name_0001);+	inter_module_unregister(im_name_0003);+	inter_module_unregister(im_name_0200); }  module_init(cfi_intelext_init);diff -Naur linux26-cvs/drivers/mtd/chips/cfi_cmdset_0002.c linux26-new/drivers/mtd/chips/cfi_cmdset_0002.c--- linux26-cvs/drivers/mtd/chips/cfi_cmdset_0002.c	2005-08-25 12:05:58.000000000 -0500+++ linux26-new/drivers/mtd/chips/cfi_cmdset_0002.c	2005-08-25 14:09:02.000000000 -0500@@ -4,16 +4,20 @@  *  * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>  * Copyright (C) 2004 Arcom Control Systems Ltd <linux@arcom.com>+ * Copyright (C) 2005 MontaVista Software Inc. <source@mvista.com>  *  * 2_by_8 routines added by Simon Munton  *  * 4_by_16 work by Carolyn J. Smith  *+ * XIP support hooks by Vitaly Wool (based on code for Intel flash + * by Nicolas Pitre)+ *   * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com  *  * This code is GPL  *- * $Id: cfi_cmdset_0002.c,v 1.114 2004/12/11 15:43:53 dedekind Exp $+ * $Id: cfi_cmdset_0002.c,v 1.120 2005/07/20 21:01:13 tpoynor Exp $  *  */ @@ -34,6 +38,7 @@ #include <linux/mtd/map.h> #include <linux/mtd/mtd.h> #include <linux/mtd/cfi.h>+#include <linux/mtd/xip.h>  #define AMD_BOOTLOC_BUG #define FORCE_WORD_WRITE 0@@ -43,6 +48,7 @@ #define MANUFACTURER_AMD	0x0001 #define MANUFACTURER_SST	0x00BF #define SST49LF004B	        0x0060+#define SST49LF008A		0x005a  static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);@@ -191,6 +197,7 @@ }; static struct cfi_fixup jedec_fixup_table[] = { 	{ MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },+	{ MANUFACTURER_SST, SST49LF008A, fixup_use_fwh_lock, NULL, }, 	{ 0, 0, NULL, NULL } }; @@ -246,6 +253,16 @@ 			return NULL; 		} +		if (extp->MajorVersion != '1' ||+		    (extp->MinorVersion < '0' || extp->MinorVersion > '4')) {+			printk(KERN_ERR "  Unknown Amd/Fujitsu Extended Query "+			       "version %c.%c.\n",  extp->MajorVersion,+			       extp->MinorVersion);+			kfree(extp);+			kfree(mtd);+			return NULL;+		}+ 		/* Install our own private info structure */ 		cfi->cmdset_priv = extp;	 @@ -391,7 +408,7 @@  * correctly and is therefore not done	(particulary with interleaved chips  * as each chip must be checked independantly of the others).  */-static int chip_ready(struct map_info *map, unsigned long addr)+static int __xipram chip_ready(struct map_info *map, unsigned long addr) { 	map_word d, t; @@ -401,6 +418,32 @@ 	return map_word_equal(map, d, t); } +/*+ * Return true if the chip is ready and has the correct value.+ *+ * Ready is one of: read mode, query mode, erase-suspend-read mode (in any+ * non-suspended sector) and it is indicated by no bits toggling.+ *+ * Error are indicated by toggling bits or bits held with the wrong value,+ * or with bits toggling.+ *+ * Note that anything more complicated than checking if no bits are toggling+ * (including checking DQ5 for an error status) is tricky to get working+ * correctly and is therefore not done	(particulary with interleaved chips+ * as each chip must be checked independantly of the others).+ *+ */+static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected)+{+	map_word oldd, curd;++	oldd = map_read(map, addr);+	curd = map_read(map, addr);++	return	map_word_equal(map, oldd, curd) && +		map_word_equal(map, curd, expected);+}+ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) { 	DECLARE_WAITQUEUE(wait, current);@@ -420,12 +463,12 @@  			if (time_after(jiffies, timeo)) { 				printk(KERN_ERR "Waiting for chip to be ready timed out.\n");-				cfi_spin_unlock(chip->mutex);+				spin_unlock(chip->mutex); 				return -EIO; 			}-			cfi_spin_unlock(chip->mutex);+			spin_unlock(chip->mutex); 			cfi_udelay(1);-			cfi_spin_lock(chip->mutex);+			spin_lock(chip->mutex); 			/* Someone else might have been playing with it. */ 			goto retry; 		}@@ -473,15 +516,23 @@ 				return -EIO; 			} 			-			cfi_spin_unlock(chip->mutex);+			spin_unlock(chip->mutex); 			cfi_udelay(1);-			cfi_spin_lock(chip->mutex);+			spin_lock(chip->mutex); 			/* Nobody will touch it while it's in state FL_ERASE_SUSPENDING. 			   So we can just loop here. */ 		} 		chip->state = FL_READY; 		return 0; +	case FL_XIP_WHILE_ERASING:+		if (mode != FL_READY && mode != FL_POINT &&+		    (!cfip || !(cfip->EraseSuspend&2)))+			goto sleep;+		chip->oldstate = chip->state;+		chip->state = FL_READY;+		return 0;+ 	case FL_POINT: 		/* Only if there's no operation suspended... */ 		if (mode == FL_READY && chip->oldstate == FL_READY)@@ -491,10 +542,10 @@ 	sleep: 		set_current_state(TASK_UNINTERRUPTIBLE); 		add_wait_queue(&chip->wq, &wait);-		cfi_spin_unlock(chip->mutex);+		spin_unlock(chip->mutex); 		schedule(); 		remove_wait_queue(&chip->wq, &wait);-		cfi_spin_lock(chip->mutex);+		spin_lock(chip->mutex); 		goto resettime; 	} }@@ -512,6 +563,11 @@ 		chip->state = FL_ERASING; 		break; +	case FL_XIP_WHILE_ERASING:+		chip->state = chip->oldstate;+		chip->oldstate = FL_READY;+		break;+ 	case FL_READY: 	case FL_STATUS: 		/* We should really make set_vpp() count, rather than doing this */@@ -523,6 +579,198 @@ 	wake_up(&chip->wq); } +#ifdef CONFIG_MTD_XIP++/*+ * No interrupt what so ever can be serviced while the flash isn't in array+ * mode.  This is ensured by the xip_disable() and xip_enable() functions+ * enclosing any code path where the flash is known not to be in array mode.+ * And within a XIP disabled code path, only functions marked with __xipram+ * may be called and nothing else (it's a good thing to inspect generated+ * assembly to make sure inline functions were actually inlined and that gcc+ * didn't emit calls to its own support functions). Also configuring MTD CFI+ * support to a single buswidth and a single interleave is also recommended.+ */++static void xip_disable(struct map_info *map, struct flchip *chip,+			unsigned long adr)+{+	/* TODO: chips with no XIP use should ignore and return */+	(void) map_read(map, adr); /* ensure mmu mapping is up to date */+	local_irq_disable();+}++static void __xipram xip_enable(struct map_info *map, struct flchip *chip,+				unsigned long adr)+{+	struct cfi_private *cfi = map->fldrv_priv;++	if (chip->state != FL_POINT && chip->state != FL_READY) {+		map_write(map, CMD(0xf0), adr);+		chip->state = FL_READY;+	}+	(void) map_read(map, adr);+	xip_iprefetch();+	local_irq_enable();+}++/*+ * When a delay is required for the flash operation to complete, the+ * xip_udelay() function is polling for both the given timeout and pending+ * (but still masked) hardware interrupts.  Whenever there is an interrupt+ * pending then the flash erase operation is suspended, array mode restored + * and interrupts unmasked.  Task scheduling might also happen at that+ * point.  The CPU eventually returns from the interrupt or the call to+ * schedule() and the suspended flash operation is resumed for the remaining+ * of the delay period.+ *+ * Warning: this function _will_ fool interrupt latency tracing tools.+ */++static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,+				unsigned long adr, int usec)+{+	struct cfi_private *cfi = map->fldrv_priv;+	struct cfi_pri_amdstd *extp = cfi->cmdset_priv;+	map_word status, OK = CMD(0x80);+	unsigned long suspended, start = xip_currtime();+	flstate_t oldstate;++	do {+		cpu_relax();+		if (xip_irqpending() && extp &&+		    ((chip->state == FL_ERASING && (extp->EraseSuspend & 2))) &&+		    (cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) {+			/*+			 * Let's suspend the erase operation when supported.  +			 * Note that we currently don't try to suspend +			 * interleaved chips if there is already another +			 * operation suspended (imagine what happens+			 * when one chip was already done with the current+			 * operation while another chip suspended it, then+			 * we resume the whole thing at once).  Yes, it+			 * can happen!+			 */+			map_write(map, CMD(0xb0), adr);+			usec -= xip_elapsed_since(start);+			suspended = xip_currtime();+			do {+				if (xip_elapsed_since(suspended) > 100000) {+					/*+					 * The chip doesn't want to suspend+					 * after waiting for 100 msecs.+					 * This is a critical error but there+					 * is not much we can do here.+					 */+					return;+				}+				status = map_read(map, adr);+			} while (!map_word_andequal(map, status, OK, OK));++			/* Suspend succeeded */+			oldstate = chip->state;+			if (!map_word_bitsset(map, status, CMD(0x40)))+				break;+			chip->state = FL_XIP_WHILE_ERASING;+			chip->erase_suspended = 1;+			map_write(map, CMD(0xf0), adr);+			(void) map_read(map, adr);+			asm volatile (".rep 8; nop; .endr");+			local_irq_enable();+			spin_unlock(chip->mutex);+			asm volatile (".rep 8; nop; .endr");+			cond_resched();++			/*+			 * We're back.  However someone else might have+			 * decided to go write to the chip if we are in+			 * a suspended erase state.  If so let's wait+			 * until it's done.+			 */+			spin_lock(chip->mutex);+			while (chip->state != FL_XIP_WHILE_ERASING) {+				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);+				spin_lock(chip->mutex);+			}+			/* Disallow XIP again */+			local_irq_disable();++			/* Resume the write or erase operation */+			map_write(map, CMD(0x30), adr);+			chip->state = oldstate;+			start = xip_currtime();+		} else if (usec >= 1000000/HZ) {+			/*+			 * Try to save on CPU power when waiting delay+			 * is at least a system timer tick period.+			 * No need to be extremely accurate here.+			 */+			xip_cpu_idle();+		}+		status = map_read(map, adr);+	} while (!map_word_andequal(map, status, OK, OK)+		 && xip_elapsed_since(start) < usec);+}++#define UDELAY(map, chip, adr, usec)  xip_udelay(map, chip, adr, usec)++/*+ * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while+ * the flash is actively programming or erasing since we have to poll for+ * the operation to complete anyway.  We can't do that in a generic way with+ * a XIP setup so do it before the actual flash operation in this case+ * and stub it out from INVALIDATE_CACHE_UDELAY.+ */+#define XIP_INVAL_CACHED_RANGE(map, from, size)  \+	INVALIDATE_CACHED_RANGE(map, from, size)++#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec)  \+	UDELAY(map, chip, adr, usec)++/*+ * Extra notes:+ *+ * Activating this XIP support changes the way the code works a bit.  For+ * example the code to suspend the current process when concurrent access+

⌨️ 快捷键说明

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