···11# drivers/mtd/chips/Kconfig22-# $Id: Kconfig,v 1.14 2005/02/08 17:11:15 nico Exp $22+# $Id: Kconfig,v 1.15 2005/06/06 23:04:35 tpoynor Exp $3344menu "RAM/ROM/Flash chip drivers"55 depends on MTD!=n···300300301301config MTD_XIP302302 bool "XIP aware MTD support"303303- depends on !SMP && MTD_CFI_INTELEXT && EXPERIMENTAL303303+ depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL304304 default y if XIP_KERNEL305305 help306306 This allows MTD support to work with flash memory which is also
+312-90
drivers/mtd/chips/cfi_cmdset_0002.c
···44 *55 * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>66 * Copyright (C) 2004 Arcom Control Systems Ltd <linux@arcom.com>77+ * Copyright (C) 2005 MontaVista Software Inc. <source@mvista.com>78 *89 * 2_by_8 routines added by Simon Munton910 *1011 * 4_by_16 work by Carolyn J. Smith1112 *1313+ * XIP support hooks by Vitaly Wool (based on code for Intel flash 1414+ * by Nicolas Pitre)1515+ * 1216 * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com1317 *1418 * This code is GPL1519 *1616- * $Id: cfi_cmdset_0002.c,v 1.116 2005/05/24 13:29:42 gleixner Exp $2020+ * $Id: cfi_cmdset_0002.c,v 1.117 2005/06/06 23:04:35 tpoynor Exp $1721 *1822 */1923···3834#include <linux/mtd/map.h>3935#include <linux/mtd/mtd.h>4036#include <linux/mtd/cfi.h>3737+#include <linux/mtd/xip.h>41384239#define AMD_BOOTLOC_BUG4340#define FORCE_WORD_WRITE 0···398393 * correctly and is therefore not done (particulary with interleaved chips399394 * as each chip must be checked independantly of the others).400395 */401401-static int chip_ready(struct map_info *map, unsigned long addr)396396+static int __xipram chip_ready(struct map_info *map, unsigned long addr)402397{403398 map_word d, t;404399···423418 * as each chip must be checked independantly of the others).424419 *425420 */426426-static int chip_good(struct map_info *map, unsigned long addr, map_word expected)421421+static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected)427422{428423 map_word oldd, curd;429424···453448454449 if (time_after(jiffies, timeo)) {455450 printk(KERN_ERR "Waiting for chip to be ready timed out.\n");456456- cfi_spin_unlock(chip->mutex);451451+ spin_unlock(chip->mutex);457452 return -EIO;458453 }459459- cfi_spin_unlock(chip->mutex);454454+ spin_unlock(chip->mutex);460455 cfi_udelay(1);461461- cfi_spin_lock(chip->mutex);456456+ spin_lock(chip->mutex);462457 /* Someone else might have been playing with it. */463458 goto retry;464459 }···506501 return -EIO;507502 }508503509509- cfi_spin_unlock(chip->mutex);504504+ spin_unlock(chip->mutex);510505 cfi_udelay(1);511511- cfi_spin_lock(chip->mutex);506506+ spin_lock(chip->mutex);512507 /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING.513508 So we can just loop here. */514509 }510510+ chip->state = FL_READY;511511+ return 0;512512+513513+ case FL_XIP_WHILE_ERASING:514514+ if (mode != FL_READY && mode != FL_POINT &&515515+ (!cfip || !(cfip->EraseSuspend&2)))516516+ goto sleep;517517+ chip->oldstate = chip->state;515518 chip->state = FL_READY;516519 return 0;517520···532519 sleep:533520 set_current_state(TASK_UNINTERRUPTIBLE);534521 add_wait_queue(&chip->wq, &wait);535535- cfi_spin_unlock(chip->mutex);522522+ spin_unlock(chip->mutex);536523 schedule();537524 remove_wait_queue(&chip->wq, &wait);538538- cfi_spin_lock(chip->mutex);525525+ spin_lock(chip->mutex);539526 goto resettime;540527 }541528}···553540 chip->state = FL_ERASING;554541 break;555542543543+ case FL_XIP_WHILE_ERASING:544544+ chip->state = chip->oldstate;545545+ chip->oldstate = FL_READY;546546+ break;547547+556548 case FL_READY:557549 case FL_STATUS:558550 /* We should really make set_vpp() count, rather than doing this */···569551 wake_up(&chip->wq);570552}571553554554+#ifdef CONFIG_MTD_XIP555555+556556+/*557557+ * No interrupt what so ever can be serviced while the flash isn't in array558558+ * mode. This is ensured by the xip_disable() and xip_enable() functions559559+ * enclosing any code path where the flash is known not to be in array mode.560560+ * And within a XIP disabled code path, only functions marked with __xipram561561+ * may be called and nothing else (it's a good thing to inspect generated562562+ * assembly to make sure inline functions were actually inlined and that gcc563563+ * didn't emit calls to its own support functions). Also configuring MTD CFI564564+ * support to a single buswidth and a single interleave is also recommended.565565+ */566566+#include <asm/hardware.h>567567+static void xip_disable(struct map_info *map, struct flchip *chip,568568+ unsigned long adr)569569+{570570+ /* TODO: chips with no XIP use should ignore and return */571571+ (void) map_read(map, adr); /* ensure mmu mapping is up to date */572572+ local_irq_disable();573573+}574574+575575+static void __xipram xip_enable(struct map_info *map, struct flchip *chip,576576+ unsigned long adr)577577+{578578+ struct cfi_private *cfi = map->fldrv_priv;579579+580580+ if (chip->state != FL_POINT && chip->state != FL_READY) {581581+ map_write(map, CMD(0xf0), adr);582582+ chip->state = FL_READY;583583+ }584584+ (void) map_read(map, adr);585585+ asm volatile (".rep 8; nop; .endr"); /* fill instruction prefetch */586586+ local_irq_enable();587587+}588588+589589+/*590590+ * When a delay is required for the flash operation to complete, the591591+ * xip_udelay() function is polling for both the given timeout and pending592592+ * (but still masked) hardware interrupts. Whenever there is an interrupt593593+ * pending then the flash erase operation is suspended, array mode restored 594594+ * and interrupts unmasked. Task scheduling might also happen at that595595+ * point. The CPU eventually returns from the interrupt or the call to596596+ * schedule() and the suspended flash operation is resumed for the remaining597597+ * of the delay period.598598+ *599599+ * Warning: this function _will_ fool interrupt latency tracing tools.600600+ */601601+602602+static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,603603+ unsigned long adr, int usec)604604+{605605+ struct cfi_private *cfi = map->fldrv_priv;606606+ struct cfi_pri_amdstd *extp = cfi->cmdset_priv;607607+ map_word status, OK = CMD(0x80);608608+ unsigned long suspended, start = xip_currtime();609609+ flstate_t oldstate;610610+611611+ do {612612+ cpu_relax();613613+ if (xip_irqpending() && extp &&614614+ ((chip->state == FL_ERASING && (extp->EraseSuspend & 2))) &&615615+ (cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) {616616+ /*617617+ * Let's suspend the erase operation when supported. 618618+ * Note that we currently don't try to suspend 619619+ * interleaved chips if there is already another 620620+ * operation suspended (imagine what happens621621+ * when one chip was already done with the current622622+ * operation while another chip suspended it, then623623+ * we resume the whole thing at once). Yes, it624624+ * can happen!625625+ */626626+ map_write(map, CMD(0xb0), adr);627627+ usec -= xip_elapsed_since(start);628628+ suspended = xip_currtime();629629+ do {630630+ if (xip_elapsed_since(suspended) > 100000) {631631+ /*632632+ * The chip doesn't want to suspend633633+ * after waiting for 100 msecs.634634+ * This is a critical error but there635635+ * is not much we can do here.636636+ */637637+ return;638638+ }639639+ status = map_read(map, adr);640640+ } while (!map_word_andequal(map, status, OK, OK));641641+642642+ /* Suspend succeeded */643643+ oldstate = chip->state;644644+ if (!map_word_bitsset(map, status, CMD(0x40)))645645+ break;646646+ chip->state = FL_XIP_WHILE_ERASING;647647+ chip->erase_suspended = 1;648648+ map_write(map, CMD(0xf0), adr);649649+ (void) map_read(map, adr);650650+ asm volatile (".rep 8; nop; .endr");651651+ local_irq_enable();652652+ spin_unlock(chip->mutex);653653+ asm volatile (".rep 8; nop; .endr");654654+ cond_resched();655655+656656+ /*657657+ * We're back. However someone else might have658658+ * decided to go write to the chip if we are in659659+ * a suspended erase state. If so let's wait660660+ * until it's done.661661+ */662662+ spin_lock(chip->mutex);663663+ while (chip->state != FL_XIP_WHILE_ERASING) {664664+ DECLARE_WAITQUEUE(wait, current);665665+ set_current_state(TASK_UNINTERRUPTIBLE);666666+ add_wait_queue(&chip->wq, &wait);667667+ spin_unlock(chip->mutex);668668+ schedule();669669+ remove_wait_queue(&chip->wq, &wait);670670+ spin_lock(chip->mutex);671671+ }672672+ /* Disallow XIP again */673673+ local_irq_disable();674674+675675+ /* Resume the write or erase operation */676676+ map_write(map, CMD(0x30), adr);677677+ chip->state = oldstate;678678+ start = xip_currtime();679679+ } else if (usec >= 1000000/HZ) {680680+ /*681681+ * Try to save on CPU power when waiting delay682682+ * is at least a system timer tick period.683683+ * No need to be extremely accurate here.684684+ */685685+ xip_cpu_idle();686686+ }687687+ status = map_read(map, adr);688688+ } while (!map_word_andequal(map, status, OK, OK)689689+ && xip_elapsed_since(start) < usec);690690+}691691+692692+#define UDELAY(map, chip, adr, usec) xip_udelay(map, chip, adr, usec)693693+694694+/*695695+ * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while696696+ * the flash is actively programming or erasing since we have to poll for697697+ * the operation to complete anyway. We can't do that in a generic way with698698+ * a XIP setup so do it before the actual flash operation in this case699699+ * and stub it out from INVALIDATE_CACHE_UDELAY.700700+ */701701+#define XIP_INVAL_CACHED_RANGE(map, from, size) \702702+ INVALIDATE_CACHED_RANGE(map, from, size)703703+704704+#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \705705+ UDELAY(map, chip, adr, usec)706706+707707+/*708708+ * Extra notes:709709+ *710710+ * Activating this XIP support changes the way the code works a bit. For711711+ * example the code to suspend the current process when concurrent access712712+ * happens is never executed because xip_udelay() will always return with the713713+ * same chip state as it was entered with. This is why there is no care for714714+ * the presence of add_wait_queue() or schedule() calls from within a couple715715+ * xip_disable()'d areas of code, like in do_erase_oneblock for example.716716+ * The queueing and scheduling are always happening within xip_udelay().717717+ *718718+ * Similarly, get_chip() and put_chip() just happen to always be executed719719+ * with chip->state set to FL_READY (or FL_XIP_WHILE_*) where flash state720720+ * is in array mode, therefore never executing many cases therein and not721721+ * causing any problem with XIP.722722+ */723723+724724+#else725725+726726+#define xip_disable(map, chip, adr)727727+#define xip_enable(map, chip, adr)728728+#define XIP_INVAL_CACHED_RANGE(x...)729729+730730+#define UDELAY(map, chip, adr, usec) \731731+do { \732732+ spin_unlock(chip->mutex); \733733+ cfi_udelay(usec); \734734+ spin_lock(chip->mutex); \735735+} while (0)736736+737737+#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \738738+do { \739739+ spin_unlock(chip->mutex); \740740+ INVALIDATE_CACHED_RANGE(map, adr, len); \741741+ cfi_udelay(usec); \742742+ spin_lock(chip->mutex); \743743+} while (0)744744+745745+#endif572746573747static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)574748{···773563 /* Ensure cmd read/writes are aligned. */ 774564 cmd_addr = adr & ~(map_bankwidth(map)-1); 775565776776- cfi_spin_lock(chip->mutex);566566+ spin_lock(chip->mutex);777567 ret = get_chip(map, chip, cmd_addr, FL_READY);778568 if (ret) {779779- cfi_spin_unlock(chip->mutex);569569+ spin_unlock(chip->mutex);780570 return ret;781571 }782572···789579790580 put_chip(map, chip, cmd_addr);791581792792- cfi_spin_unlock(chip->mutex);582582+ spin_unlock(chip->mutex);793583 return 0;794584}795585···843633 struct cfi_private *cfi = map->fldrv_priv;844634845635 retry:846846- cfi_spin_lock(chip->mutex);636636+ spin_lock(chip->mutex);847637848638 if (chip->state != FL_READY){849639#if 0···852642 set_current_state(TASK_UNINTERRUPTIBLE);853643 add_wait_queue(&chip->wq, &wait);854644855855- cfi_spin_unlock(chip->mutex);645645+ spin_unlock(chip->mutex);856646857647 schedule();858648 remove_wait_queue(&chip->wq, &wait);···881671 cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);882672883673 wake_up(&chip->wq);884884- cfi_spin_unlock(chip->mutex);674674+ spin_unlock(chip->mutex);885675886676 return 0;887677}···930720}931721932722933933-static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum)723723+static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum)934724{935725 struct cfi_private *cfi = map->fldrv_priv;936726 unsigned long timeo = jiffies + HZ;···950740951741 adr += chip->start;952742953953- cfi_spin_lock(chip->mutex);743743+ spin_lock(chip->mutex);954744 ret = get_chip(map, chip, adr, FL_WRITING);955745 if (ret) {956956- cfi_spin_unlock(chip->mutex);746746+ spin_unlock(chip->mutex);957747 return ret;958748 }959749···973763 goto op_done;974764 }975765766766+ XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));976767 ENABLE_VPP(map);768768+ xip_disable(map, chip, adr);977769 retry:978770 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);979771 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);···983771 map_write(map, datum, adr);984772 chip->state = FL_WRITING;985773986986- cfi_spin_unlock(chip->mutex);987987- cfi_udelay(chip->word_write_time);988988- cfi_spin_lock(chip->mutex);774774+ INVALIDATE_CACHE_UDELAY(map, chip,775775+ adr, map_bankwidth(map),776776+ chip->word_write_time);989777990778 /* See comment above for timeout value. */991779 timeo = jiffies + uWriteTimeout; ···996784997785 set_current_state(TASK_UNINTERRUPTIBLE);998786 add_wait_queue(&chip->wq, &wait);999999- cfi_spin_unlock(chip->mutex);787787+ spin_unlock(chip->mutex);1000788 schedule();1001789 remove_wait_queue(&chip->wq, &wait);1002790 timeo = jiffies + (HZ / 2); /* FIXME */10031003- cfi_spin_lock(chip->mutex);791791+ spin_lock(chip->mutex);1004792 continue;1005793 }1006794···1008796 break;10097971010798 if (time_after(jiffies, timeo)) {799799+ xip_enable(map, chip, adr);1011800 printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);801801+ xip_disable(map, chip, adr);1012802 break;1013803 }10148041015805 /* Latency issues. Drop the lock, wait a while and retry */10161016- cfi_spin_unlock(chip->mutex);10171017- cfi_udelay(1);10181018- cfi_spin_lock(chip->mutex);806806+ UDELAY(map, chip, adr, 1);1019807 }1020808 /* Did we succeed? */1021809 if (!chip_good(map, adr, datum)) {···10288161029817 ret = -EIO;1030818 }819819+ xip_enable(map, chip, adr);1031820 op_done:1032821 chip->state = FL_READY;1033822 put_chip(map, chip, adr);10341034- cfi_spin_unlock(chip->mutex);823823+ spin_unlock(chip->mutex);10358241036825 return ret;1037826}···1064851 map_word tmp_buf;10658521066853 retry:10671067- cfi_spin_lock(cfi->chips[chipnum].mutex);854854+ spin_lock(cfi->chips[chipnum].mutex);10688551069856 if (cfi->chips[chipnum].state != FL_READY) {1070857#if 0···1073860 set_current_state(TASK_UNINTERRUPTIBLE);1074861 add_wait_queue(&cfi->chips[chipnum].wq, &wait);107586210761076- cfi_spin_unlock(cfi->chips[chipnum].mutex);863863+ spin_unlock(cfi->chips[chipnum].mutex);10778641078865 schedule();1079866 remove_wait_queue(&cfi->chips[chipnum].wq, &wait);···1087874 /* Load 'tmp_buf' with old contents of flash */1088875 tmp_buf = map_read(map, bus_ofs+chipstart);108987610901090- cfi_spin_unlock(cfi->chips[chipnum].mutex);877877+ spin_unlock(cfi->chips[chipnum].mutex);10918781092879 /* Number of bytes to copy from buffer */1093880 n = min_t(int, len, map_bankwidth(map)-i);···1142929 map_word tmp_buf;11439301144931 retry1:11451145- cfi_spin_lock(cfi->chips[chipnum].mutex);932932+ spin_lock(cfi->chips[chipnum].mutex);11469331147934 if (cfi->chips[chipnum].state != FL_READY) {1148935#if 0···1151938 set_current_state(TASK_UNINTERRUPTIBLE);1152939 add_wait_queue(&cfi->chips[chipnum].wq, &wait);115394011541154- cfi_spin_unlock(cfi->chips[chipnum].mutex);941941+ spin_unlock(cfi->chips[chipnum].mutex);11559421156943 schedule();1157944 remove_wait_queue(&cfi->chips[chipnum].wq, &wait);···11649511165952 tmp_buf = map_read(map, ofs + chipstart);116695311671167- cfi_spin_unlock(cfi->chips[chipnum].mutex);954954+ spin_unlock(cfi->chips[chipnum].mutex);11689551169956 tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);1170957···1183970/*1184971 * FIXME: interleaved mode not tested, and probably not supported!1185972 */11861186-static inline int do_write_buffer(struct map_info *map, struct flchip *chip, 11871187- unsigned long adr, const u_char *buf, int len)973973+static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,974974+ unsigned long adr, const u_char *buf, 975975+ int len)1188976{1189977 struct cfi_private *cfi = map->fldrv_priv;1190978 unsigned long timeo = jiffies + HZ;···1199985 adr += chip->start;1200986 cmd_adr = adr;120198712021202- cfi_spin_lock(chip->mutex);988988+ spin_lock(chip->mutex);1203989 ret = get_chip(map, chip, adr, FL_WRITING);1204990 if (ret) {12051205- cfi_spin_unlock(chip->mutex);991991+ spin_unlock(chip->mutex);1206992 return ret;1207993 }1208994···1211997 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",1212998 __func__, adr, datum.x[0] );121399910001000+ XIP_INVAL_CACHED_RANGE(map, adr, len);12141001 ENABLE_VPP(map);10021002+ xip_disable(map, chip, cmd_adr);10031003+12151004 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);12161005 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);12171006 //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);···12441027 map_write(map, CMD(0x29), cmd_adr);12451028 chip->state = FL_WRITING;1246102912471247- cfi_spin_unlock(chip->mutex);12481248- cfi_udelay(chip->buffer_write_time);12491249- cfi_spin_lock(chip->mutex);10301030+ INVALIDATE_CACHE_UDELAY(map, chip,10311031+ adr, map_bankwidth(map),10321032+ chip->word_write_time);1250103312511034 timeo = jiffies + uWriteTimeout; 12521035···1257104012581041 set_current_state(TASK_UNINTERRUPTIBLE);12591042 add_wait_queue(&chip->wq, &wait);12601260- cfi_spin_unlock(chip->mutex);10431043+ spin_unlock(chip->mutex);12611044 schedule();12621045 remove_wait_queue(&chip->wq, &wait);12631046 timeo = jiffies + (HZ / 2); /* FIXME */12641264- cfi_spin_lock(chip->mutex);10471047+ spin_lock(chip->mutex);12651048 continue;12661049 }1267105012681268- if (chip_ready(map, adr))10511051+ if (chip_ready(map, adr)) {10521052+ xip_enable(map, chip, adr);12691053 goto op_done;10541054+ }1270105512711056 if( time_after(jiffies, timeo))12721057 break;1273105812741059 /* Latency issues. Drop the lock, wait a while and retry */12751275- cfi_spin_unlock(chip->mutex);12761276- cfi_udelay(1);12771277- cfi_spin_lock(chip->mutex);10601060+ UDELAY(map, chip, adr, 1);12781061 }12791279-12801280- printk(KERN_WARNING "MTD %s(): software timeout\n",12811281- __func__ );1282106212831063 /* reset on all failures. */12841064 map_write( map, CMD(0xF0), chip->start );10651065+ xip_enable(map, chip, adr);12851066 /* FIXME - should have reset delay before continuing */10671067+10681068+ printk(KERN_WARNING "MTD %s(): software timeout\n",10691069+ __func__ );1286107012871071 ret = -EIO;12881072 op_done:12891073 chip->state = FL_READY;12901074 put_chip(map, chip, adr);12911291- cfi_spin_unlock(chip->mutex);10751075+ spin_unlock(chip->mutex);1292107612931077 return ret;12941078}···13791161 * Handle devices with one erase region, that only implement13801162 * the chip erase command.13811163 */13821382-static inline int do_erase_chip(struct map_info *map, struct flchip *chip)11641164+static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)13831165{13841166 struct cfi_private *cfi = map->fldrv_priv;13851167 unsigned long timeo = jiffies + HZ;···1389117113901172 adr = cfi->addr_unlock1;1391117313921392- cfi_spin_lock(chip->mutex);11741174+ spin_lock(chip->mutex);13931175 ret = get_chip(map, chip, adr, FL_WRITING);13941176 if (ret) {13951395- cfi_spin_unlock(chip->mutex);11771177+ spin_unlock(chip->mutex);13961178 return ret;13971179 }1398118013991181 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",14001182 __func__, chip->start );1401118311841184+ XIP_INVAL_CACHED_RANGE(map, adr, map->size);14021185 ENABLE_VPP(map);11861186+ xip_disable(map, chip, adr);11871187+14031188 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);14041189 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);14051190 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);···14141193 chip->erase_suspended = 0;14151194 chip->in_progress_block_addr = adr;1416119514171417- cfi_spin_unlock(chip->mutex);14181418- msleep(chip->erase_time/2);14191419- cfi_spin_lock(chip->mutex);11961196+ INVALIDATE_CACHE_UDELAY(map, chip,11971197+ adr, map->size,11981198+ chip->erase_time*500);1420119914211200 timeo = jiffies + (HZ*20);14221201···14251204 /* Someone's suspended the erase. Sleep */14261205 set_current_state(TASK_UNINTERRUPTIBLE);14271206 add_wait_queue(&chip->wq, &wait);14281428- cfi_spin_unlock(chip->mutex);12071207+ spin_unlock(chip->mutex);14291208 schedule();14301209 remove_wait_queue(&chip->wq, &wait);14311431- cfi_spin_lock(chip->mutex);12101210+ spin_lock(chip->mutex);14321211 continue;14331212 }14341213 if (chip->erase_suspended) {···14481227 }1449122814501229 /* Latency issues. Drop the lock, wait a while and retry */14511451- cfi_spin_unlock(chip->mutex);14521452- set_current_state(TASK_UNINTERRUPTIBLE);14531453- schedule_timeout(1);14541454- cfi_spin_lock(chip->mutex);12301230+ UDELAY(map, chip, adr, 1000000/HZ);14551231 }14561232 /* Did we succeed? */14571233 if (!chip_good(map, adr, map_word_ff(map))) {···14601242 }1461124314621244 chip->state = FL_READY;12451245+ xip_enable(map, chip, adr);14631246 put_chip(map, chip, adr);14641464- cfi_spin_unlock(chip->mutex);12471247+ spin_unlock(chip->mutex);1465124814661249 return ret;14671250}146812511469125214701470-static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk)12531253+static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk)14711254{14721255 struct cfi_private *cfi = map->fldrv_priv;14731256 unsigned long timeo = jiffies + HZ;···1477125814781259 adr += chip->start;1479126014801480- cfi_spin_lock(chip->mutex);12611261+ spin_lock(chip->mutex);14811262 ret = get_chip(map, chip, adr, FL_ERASING);14821263 if (ret) {14831483- cfi_spin_unlock(chip->mutex);12641264+ spin_unlock(chip->mutex);14841265 return ret;14851266 }1486126714871268 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",14881269 __func__, adr );1489127012711271+ XIP_INVAL_CACHED_RANGE(map, adr, len);14901272 ENABLE_VPP(map);12731273+ xip_disable(map, chip, adr);12741274+14911275 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);14921276 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);14931277 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);···15011279 chip->state = FL_ERASING;15021280 chip->erase_suspended = 0;15031281 chip->in_progress_block_addr = adr;15041504-15051505- cfi_spin_unlock(chip->mutex);15061506- msleep(chip->erase_time/2);15071507- cfi_spin_lock(chip->mutex);12821282+12831283+ INVALIDATE_CACHE_UDELAY(map, chip,12841284+ adr, len,12851285+ chip->erase_time*500);1508128615091287 timeo = jiffies + (HZ*20);15101288···15131291 /* Someone's suspended the erase. Sleep */15141292 set_current_state(TASK_UNINTERRUPTIBLE);15151293 add_wait_queue(&chip->wq, &wait);15161516- cfi_spin_unlock(chip->mutex);12941294+ spin_unlock(chip->mutex);15171295 schedule();15181296 remove_wait_queue(&chip->wq, &wait);15191519- cfi_spin_lock(chip->mutex);12971297+ spin_lock(chip->mutex);15201298 continue;15211299 }15221300 if (chip->erase_suspended) {···15261304 chip->erase_suspended = 0;15271305 }1528130615291529- if (chip_ready(map, adr))13071307+ if (chip_ready(map, adr)) {13081308+ xip_enable(map, chip, adr);15301309 break;13101310+ }1531131115321312 if (time_after(jiffies, timeo)) {13131313+ xip_enable(map, chip, adr);15331314 printk(KERN_WARNING "MTD %s(): software timeout\n",15341315 __func__ );15351316 break;15361317 }1537131815381319 /* Latency issues. Drop the lock, wait a while and retry */15391539- cfi_spin_unlock(chip->mutex);15401540- set_current_state(TASK_UNINTERRUPTIBLE);15411541- schedule_timeout(1);15421542- cfi_spin_lock(chip->mutex);13201320+ UDELAY(map, chip, adr, 1000000/HZ);15431321 }15441322 /* Did we succeed? */15451323 if (!chip_good(map, adr, map_word_ff(map))) {···1552133015531331 chip->state = FL_READY;15541332 put_chip(map, chip, adr);15551555- cfi_spin_unlock(chip->mutex);13331333+ spin_unlock(chip->mutex);15561334 return ret;15571335}15581336···16121390 chip = &cfi->chips[i];1613139116141392 retry:16151615- cfi_spin_lock(chip->mutex);13931393+ spin_lock(chip->mutex);1616139416171395 switch(chip->state) {16181396 case FL_READY:···16261404 * with the chip now anyway.16271405 */16281406 case FL_SYNCING:16291629- cfi_spin_unlock(chip->mutex);14071407+ spin_unlock(chip->mutex);16301408 break;1631140916321410 default:16331411 /* Not an idle state */16341412 add_wait_queue(&chip->wq, &wait);1635141316361636- cfi_spin_unlock(chip->mutex);14141414+ spin_unlock(chip->mutex);1637141516381416 schedule();16391417···16481426 for (i--; i >=0; i--) {16491427 chip = &cfi->chips[i];1650142816511651- cfi_spin_lock(chip->mutex);14291429+ spin_lock(chip->mutex);1652143016531431 if (chip->state == FL_SYNCING) {16541432 chip->state = chip->oldstate;16551433 wake_up(&chip->wq);16561434 }16571657- cfi_spin_unlock(chip->mutex);14351435+ spin_unlock(chip->mutex);16581436 }16591437}16601438···16701448 for (i=0; !ret && i<cfi->numchips; i++) {16711449 chip = &cfi->chips[i];1672145016731673- cfi_spin_lock(chip->mutex);14511451+ spin_lock(chip->mutex);1674145216751453 switch(chip->state) {16761454 case FL_READY:···16901468 ret = -EAGAIN;16911469 break;16921470 }16931693- cfi_spin_unlock(chip->mutex);14711471+ spin_unlock(chip->mutex);16941472 }1695147316961474 /* Unlock the chips again */···16991477 for (i--; i >=0; i--) {17001478 chip = &cfi->chips[i];1701147917021702- cfi_spin_lock(chip->mutex);14801480+ spin_lock(chip->mutex);1703148117041482 if (chip->state == FL_PM_SUSPENDED) {17051483 chip->state = chip->oldstate;17061484 wake_up(&chip->wq);17071485 }17081708- cfi_spin_unlock(chip->mutex);14861486+ spin_unlock(chip->mutex);17091487 }17101488 }17111489···1724150217251503 chip = &cfi->chips[i];1726150417271727- cfi_spin_lock(chip->mutex);15051505+ spin_lock(chip->mutex);1728150617291507 if (chip->state == FL_PM_SUSPENDED) {17301508 chip->state = FL_READY;···17341512 else17351513 printk(KERN_ERR "Argh. Chip not in PM_SUSPENDED state upon resume()\n");1736151417371737- cfi_spin_unlock(chip->mutex);15151515+ spin_unlock(chip->mutex);17381516 }17391517}17401518
+3-3
drivers/mtd/chips/fwh_lock.h
···5858 * to flash memory - that means that we don't have to check status5959 * and timeout.6060 */6161- cfi_spin_lock(chip->mutex);6161+ spin_lock(chip->mutex);6262 ret = get_chip(map, chip, adr, FL_LOCKING);6363 if (ret) {6464- cfi_spin_unlock(chip->mutex);6464+ spin_unlock(chip->mutex);6565 return ret;6666 }6767···7171 /* Done and happy. */7272 chip->state = FL_READY;7373 put_chip(map, chip, adr);7474- cfi_spin_unlock(chip->mutex);7474+ spin_unlock(chip->mutex);7575 return 0;7676}7777
+6-5
drivers/mtd/maps/map_funcs.c
···11/*22- * $Id: map_funcs.c,v 1.9 2004/07/13 22:33:15 dwmw2 Exp $22+ * $Id: map_funcs.c,v 1.10 2005/06/06 23:04:36 tpoynor Exp $33 *44 * Out-of-line map I/O functions for simple maps when CONFIG_COMPLEX_MAPPINGS55 * is enabled.···99#include <linux/module.h>10101111#include <linux/mtd/map.h>1212+#include <linux/mtd/xip.h>12131313-static map_word simple_map_read(struct map_info *map, unsigned long ofs)1414+static map_word __xipram simple_map_read(struct map_info *map, unsigned long ofs)1415{1516 return inline_map_read(map, ofs);1617}17181818-static void simple_map_write(struct map_info *map, const map_word datum, unsigned long ofs)1919+static void __xipram simple_map_write(struct map_info *map, const map_word datum, unsigned long ofs)1920{2021 inline_map_write(map, datum, ofs);2122}22232323-static void simple_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)2424+static void __xipram simple_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)2425{2526 inline_map_copy_from(map, to, from, len);2627}27282828-static void simple_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)2929+static void __xipram simple_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)2930{3031 inline_map_copy_to(map, to, from, len);3132}