···11# drivers/mtd/chips/Kconfig22-# $Id: Kconfig,v 1.13 2004/12/01 15:49:10 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···155155 If your flash chips are interleaved in eights - i.e. you have eight156156 flash chips addressed by each bus cycle, then say 'Y'.157157158158+config MTD_OTP159159+ bool "Protection Registers aka one-time programmable (OTP) bits"160160+ depends on MTD_CFI_ADV_OPTIONS161161+ default n162162+ help163163+ This enables support for reading, writing and locking so called164164+ "Protection Registers" present on some flash chips.165165+ A subset of them are pre-programmed at the factory with a166166+ unique set of values. The rest is user-programmable.167167+168168+ The user-programmable Protection Registers contain one-time169169+ programmable (OTP) bits; when programmed, register bits cannot be170170+ erased. Each Protection Register can be accessed multiple times to171171+ program individual bits, as long as the register remains unlocked.172172+173173+ Each Protection Register has an associated Lock Register bit. When a174174+ Lock Register bit is programmed, the associated Protection Register175175+ can only be read; it can no longer be programmed. Additionally,176176+ because the Lock Register bits themselves are OTP, when programmed,177177+ Lock Register bits cannot be erased. Therefore, when a Protection178178+ Register is locked, it cannot be unlocked.179179+180180+ This feature should therefore be used with extreme care. Any mistake181181+ in the programming of OTP bits will waste them.182182+158183config MTD_CFI_INTELEXT159184 tristate "Support for Intel/Sharp flash chips"160185 depends on MTD_GEN_PROBE···300275301276config MTD_XIP302277 bool "XIP aware MTD support"303303- depends on !SMP && MTD_CFI_INTELEXT && EXPERIMENTAL278278+ depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL304279 default y if XIP_KERNEL305280 help306281 This allows MTD support to work with flash memory which is also
···44 *55 * (C) 2000 Red Hat. GPL'd66 *77- * $Id: cfi_cmdset_0001.c,v 1.164 2004/11/16 18:29:00 dwmw2 Exp $77+ * $Id: cfi_cmdset_0001.c,v 1.178 2005/05/19 17:05:43 nico Exp $88 *99 * 1010 * 10/10/2000 Nicolas Pitre <nico@cam.org>···2929#include <linux/slab.h>3030#include <linux/delay.h>3131#include <linux/interrupt.h>3232+#include <linux/reboot.h>3233#include <linux/mtd/xip.h>3334#include <linux/mtd/map.h>3435#include <linux/mtd/mtd.h>···4948#define M50LPW080 0x002F50495150static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);5252-//static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);5353-//static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);5451static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);5552static int cfi_intelext_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);5653static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *);5754static void cfi_intelext_sync (struct mtd_info *);5855static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len);5956static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);5757+#ifdef CONFIG_MTD_OTP5858+static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);5959+static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);6060+static int cfi_intelext_write_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);6161+static int cfi_intelext_lock_user_prot_reg (struct mtd_info *, loff_t, size_t);6262+static int cfi_intelext_get_fact_prot_info (struct mtd_info *,6363+ struct otp_info *, size_t);6464+static int cfi_intelext_get_user_prot_info (struct mtd_info *,6565+ struct otp_info *, size_t);6666+#endif6067static int cfi_intelext_suspend (struct mtd_info *);6168static void cfi_intelext_resume (struct mtd_info *);6969+static int cfi_intelext_reboot (struct notifier_block *, unsigned long, void *);62706371static void cfi_intelext_destroy(struct mtd_info *);6472···262252 int nb_parts, i;263253264254 /* Protection Register info */265265- extra_size += (extp->NumProtectionFields - 1) * (4 + 6);255255+ extra_size += (extp->NumProtectionFields - 1) *256256+ sizeof(struct cfi_intelext_otpinfo);266257267258 /* Burst Read info */268259 extra_size += 6;···335324 mtd->resume = cfi_intelext_resume;336325 mtd->flags = MTD_CAP_NORFLASH;337326 mtd->name = map->name;338338-327327+328328+ mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;329329+339330 if (cfi->cfi_mode == CFI_MODE_CFI) {340331 /* 341332 * It's a real CFI chip, not one for which the probe···435422 mtd->eraseregions[i].numblocks);436423 }437424438438-#if 0439439- mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg;425425+#ifdef CONFIG_MTD_OTP440426 mtd->read_fact_prot_reg = cfi_intelext_read_fact_prot_reg;427427+ mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg;428428+ mtd->write_user_prot_reg = cfi_intelext_write_user_prot_reg;429429+ mtd->lock_user_prot_reg = cfi_intelext_lock_user_prot_reg;430430+ mtd->get_fact_prot_info = cfi_intelext_get_fact_prot_info;431431+ mtd->get_user_prot_info = cfi_intelext_get_user_prot_info;441432#endif442433443434 /* This function has the potential to distort the reality···450433 goto setup_err;451434452435 __module_get(THIS_MODULE);436436+ register_reboot_notifier(&mtd->reboot_notifier);453437 return mtd;454438455439 setup_err:···489471 int offs, numregions, numparts, partshift, numvirtchips, i, j;490472491473 /* Protection Register info */492492- offs = (extp->NumProtectionFields - 1) * (4 + 6);474474+ offs = (extp->NumProtectionFields - 1) *475475+ sizeof(struct cfi_intelext_otpinfo);493476494477 /* Burst Read info */495478 offs += 6;···582563 resettime:583564 timeo = jiffies + HZ;584565 retry:585585- if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING)) {566566+ if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE)) {586567 /*587568 * OK. We have possibility for contension on the write/erase588569 * operations which are global to the real chip and not per···826807 * assembly to make sure inline functions were actually inlined and that gcc827808 * didn't emit calls to its own support functions). Also configuring MTD CFI828809 * support to a single buswidth and a single interleave is also recommended.829829- * Note that not only IRQs are disabled but the preemption count is also830830- * increased to prevent other locking primitives (namely spin_unlock) from831831- * decrementing the preempt count to zero and scheduling the CPU away while832832- * not in array mode.833810 */834811835812static void xip_disable(struct map_info *map, struct flchip *chip,···833818{834819 /* TODO: chips with no XIP use should ignore and return */835820 (void) map_read(map, adr); /* ensure mmu mapping is up to date */836836- preempt_disable();837821 local_irq_disable();838822}839823···845831 chip->state = FL_READY;846832 }847833 (void) map_read(map, adr);848848- asm volatile (".rep 8; nop; .endr"); /* fill instruction prefetch */834834+ xip_iprefetch();849835 local_irq_enable();850850- preempt_enable();851836}852837853838/*···922909 (void) map_read(map, adr);923910 asm volatile (".rep 8; nop; .endr");924911 local_irq_enable();925925- preempt_enable();912912+ spin_unlock(chip->mutex);926913 asm volatile (".rep 8; nop; .endr");927914 cond_resched();928915···932919 * a suspended erase state. If so let's wait933920 * until it's done.934921 */935935- preempt_disable();922922+ spin_lock(chip->mutex);936923 while (chip->state != newstate) {937924 DECLARE_WAITQUEUE(wait, current);938925 set_current_state(TASK_UNINTERRUPTIBLE);939926 add_wait_queue(&chip->wq, &wait);940940- preempt_enable();927927+ spin_unlock(chip->mutex);941928 schedule();942929 remove_wait_queue(&chip->wq, &wait);943943- preempt_disable();930930+ spin_lock(chip->mutex);944931 }945932 /* Disallow XIP again */946933 local_irq_disable();···969956 * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while970957 * the flash is actively programming or erasing since we have to poll for971958 * the operation to complete anyway. We can't do that in a generic way with972972- * a XIP setup so do it before the actual flash operation in this case.959959+ * a XIP setup so do it before the actual flash operation in this case960960+ * and stub it out from INVALIDATE_CACHE_UDELAY.973961 */974974-#undef INVALIDATE_CACHED_RANGE975975-#define INVALIDATE_CACHED_RANGE(x...)976976-#define XIP_INVAL_CACHED_RANGE(map, from, size) \977977- do { if(map->inval_cache) map->inval_cache(map, from, size); } while(0)962962+#define XIP_INVAL_CACHED_RANGE(map, from, size) \963963+ INVALIDATE_CACHED_RANGE(map, from, size)964964+965965+#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \966966+ UDELAY(map, chip, adr, usec)978967979968/*980969 * Extra notes:···9999841000985#define xip_disable(map, chip, adr)1001986#define xip_enable(map, chip, adr)10021002-10031003-#define UDELAY(map, chip, adr, usec) cfi_udelay(usec)10041004-1005987#define XIP_INVAL_CACHED_RANGE(x...)988988+989989+#define UDELAY(map, chip, adr, usec) \990990+do { \991991+ spin_unlock(chip->mutex); \992992+ cfi_udelay(usec); \993993+ spin_lock(chip->mutex); \994994+} while (0)995995+996996+#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \997997+do { \998998+ spin_unlock(chip->mutex); \999999+ INVALIDATE_CACHED_RANGE(map, adr, len); \10001000+ cfi_udelay(usec); \10011001+ spin_lock(chip->mutex); \10021002+} while (0)1006100310071004#endif10081005···12031176 return ret;12041177}1205117812061206-#if 012071207-static int __xipram cfi_intelext_read_prot_reg (struct mtd_info *mtd,12081208- loff_t from, size_t len,12091209- size_t *retlen,12101210- u_char *buf,12111211- int base_offst, int reg_sz)12121212-{12131213- struct map_info *map = mtd->priv;12141214- struct cfi_private *cfi = map->fldrv_priv;12151215- struct cfi_pri_intelext *extp = cfi->cmdset_priv;12161216- struct flchip *chip;12171217- int ofs_factor = cfi->interleave * cfi->device_type;12181218- int count = len;12191219- int chip_num, offst;12201220- int ret;12211221-12221222- chip_num = ((unsigned int)from/reg_sz);12231223- offst = from - (reg_sz*chip_num)+base_offst;12241224-12251225- while (count) {12261226- /* Calculate which chip & protection register offset we need */12271227-12281228- if (chip_num >= cfi->numchips)12291229- goto out;12301230-12311231- chip = &cfi->chips[chip_num];12321232-12331233- spin_lock(chip->mutex);12341234- ret = get_chip(map, chip, chip->start, FL_JEDEC_QUERY);12351235- if (ret) {12361236- spin_unlock(chip->mutex);12371237- return (len-count)?:ret;12381238- }12391239-12401240- xip_disable(map, chip, chip->start);12411241-12421242- if (chip->state != FL_JEDEC_QUERY) {12431243- map_write(map, CMD(0x90), chip->start);12441244- chip->state = FL_JEDEC_QUERY;12451245- }12461246-12471247- while (count && ((offst-base_offst) < reg_sz)) {12481248- *buf = map_read8(map,(chip->start+((extp->ProtRegAddr+1)*ofs_factor)+offst));12491249- buf++;12501250- offst++;12511251- count--;12521252- }12531253-12541254- xip_enable(map, chip, chip->start);12551255- put_chip(map, chip, chip->start);12561256- spin_unlock(chip->mutex);12571257-12581258- /* Move on to the next chip */12591259- chip_num++;12601260- offst = base_offst;12611261- }12621262-12631263- out: 12641264- return len-count;12651265-}12661266-12671267-static int cfi_intelext_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)12681268-{12691269- struct map_info *map = mtd->priv;12701270- struct cfi_private *cfi = map->fldrv_priv;12711271- struct cfi_pri_intelext *extp=cfi->cmdset_priv;12721272- int base_offst,reg_sz;12731273-12741274- /* Check that we actually have some protection registers */12751275- if(!extp || !(extp->FeatureSupport&64)){12761276- printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name);12771277- return 0;12781278- }12791279-12801280- base_offst=(1<<extp->FactProtRegSize);12811281- reg_sz=(1<<extp->UserProtRegSize);12821282-12831283- return cfi_intelext_read_prot_reg(mtd, from, len, retlen, buf, base_offst, reg_sz);12841284-}12851285-12861286-static int cfi_intelext_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)12871287-{12881288- struct map_info *map = mtd->priv;12891289- struct cfi_private *cfi = map->fldrv_priv;12901290- struct cfi_pri_intelext *extp=cfi->cmdset_priv;12911291- int base_offst,reg_sz;12921292-12931293- /* Check that we actually have some protection registers */12941294- if(!extp || !(extp->FeatureSupport&64)){12951295- printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name);12961296- return 0;12971297- }12981298-12991299- base_offst=0;13001300- reg_sz=(1<<extp->FactProtRegSize);13011301-13021302- return cfi_intelext_read_prot_reg(mtd, from, len, retlen, buf, base_offst, reg_sz);13031303-}13041304-#endif13051305-13061179static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,13071307- unsigned long adr, map_word datum)11801180+ unsigned long adr, map_word datum, int mode)13081181{13091182 struct cfi_private *cfi = map->fldrv_priv;13101310- map_word status, status_OK;11831183+ map_word status, status_OK, write_cmd;13111184 unsigned long timeo;13121185 int z, ret=0;13131186···1215128812161289 /* Let's determine this according to the interleave only once */12171290 status_OK = CMD(0x80);12911291+ switch (mode) {12921292+ case FL_WRITING: write_cmd = CMD(0x40); break;12931293+ case FL_OTP_WRITE: write_cmd = CMD(0xc0); break;12941294+ default: return -EINVAL;12951295+ }1218129612191297 spin_lock(chip->mutex);12201220- ret = get_chip(map, chip, adr, FL_WRITING);12981298+ ret = get_chip(map, chip, adr, mode);12211299 if (ret) {12221300 spin_unlock(chip->mutex);12231301 return ret;···12311299 XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));12321300 ENABLE_VPP(map);12331301 xip_disable(map, chip, adr);12341234- map_write(map, CMD(0x40), adr);13021302+ map_write(map, write_cmd, adr);12351303 map_write(map, datum, adr);12361236- chip->state = FL_WRITING;13041304+ chip->state = mode;1237130512381238- spin_unlock(chip->mutex);12391239- INVALIDATE_CACHED_RANGE(map, adr, map_bankwidth(map));12401240- UDELAY(map, chip, adr, chip->word_write_time);12411241- spin_lock(chip->mutex);13061306+ INVALIDATE_CACHE_UDELAY(map, chip,13071307+ adr, map_bankwidth(map),13081308+ chip->word_write_time);1242130912431310 timeo = jiffies + (HZ/2);12441311 z = 0;12451312 for (;;) {12461246- if (chip->state != FL_WRITING) {13131313+ if (chip->state != mode) {12471314 /* Someone's suspended the write. Sleep */12481315 DECLARE_WAITQUEUE(wait, current);12491316···12701339 }1271134012721341 /* Latency issues. Drop the lock, wait a while and retry */12731273- spin_unlock(chip->mutex);12741342 z++;12751343 UDELAY(map, chip, adr, 1);12761276- spin_lock(chip->mutex);12771344 }12781345 if (!z) {12791346 chip->word_write_time--;···13281399 datum = map_word_load_partial(map, datum, buf, gap, n);1329140013301401 ret = do_write_oneword(map, &cfi->chips[chipnum],13311331- bus_ofs, datum);14021402+ bus_ofs, datum, FL_WRITING);13321403 if (ret) 13331404 return ret;13341405···13491420 map_word datum = map_word_load(map, buf);1350142113511422 ret = do_write_oneword(map, &cfi->chips[chipnum],13521352- ofs, datum);14231423+ ofs, datum, FL_WRITING);13531424 if (ret)13541425 return ret;13551426···13731444 datum = map_word_load_partial(map, datum, buf, 0, len);1374144513751446 ret = do_write_oneword(map, &cfi->chips[chipnum],13761376- ofs, datum);14471447+ ofs, datum, FL_WRITING);13771448 if (ret) 13781449 return ret;13791450···14351506 if (map_word_andequal(map, status, status_OK, status_OK))14361507 break;1437150814381438- spin_unlock(chip->mutex);14391509 UDELAY(map, chip, cmd_adr, 1);14401440- spin_lock(chip->mutex);1441151014421511 if (++z > 20) {14431512 /* Argh. Not ready for write to buffer */···14811554 map_write(map, CMD(0xd0), cmd_adr);14821555 chip->state = FL_WRITING;1483155614841484- spin_unlock(chip->mutex);14851485- INVALIDATE_CACHED_RANGE(map, adr, len);14861486- UDELAY(map, chip, cmd_adr, chip->buffer_write_time);14871487- spin_lock(chip->mutex);15571557+ INVALIDATE_CACHE_UDELAY(map, chip, 15581558+ cmd_adr, len,15591559+ chip->buffer_write_time);1488156014891561 timeo = jiffies + (HZ/2);14901562 z = 0;···15151589 }1516159015171591 /* Latency issues. Drop the lock, wait a while and retry */15181518- spin_unlock(chip->mutex);15191519- UDELAY(map, chip, cmd_adr, 1);15201592 z++;15211521- spin_lock(chip->mutex);15931593+ UDELAY(map, chip, cmd_adr, 1);15221594 }15231595 if (!z) {15241596 chip->buffer_write_time--;···16441720 chip->state = FL_ERASING;16451721 chip->erase_suspended = 0;1646172216471647- spin_unlock(chip->mutex);16481648- INVALIDATE_CACHED_RANGE(map, adr, len);16491649- UDELAY(map, chip, adr, chip->erase_time*1000/2);16501650- spin_lock(chip->mutex);17231723+ INVALIDATE_CACHE_UDELAY(map, chip,17241724+ adr, len,17251725+ chip->erase_time*1000/2);1651172616521727 /* FIXME. Use a timer to check this, and return immediately. */16531728 /* Once the state machine's known to be working I'll do that */···16911768 }1692176916931770 /* Latency issues. Drop the lock, wait a while and retry */16941694- spin_unlock(chip->mutex);16951771 UDELAY(map, chip, adr, 1000000/HZ);16961696- spin_lock(chip->mutex);16971772 }1698177316991774 /* We've broken this before. It doesn't hurt to be safe */···1701178017021781 /* check for lock bit */17031782 if (map_word_bitsset(map, status, CMD(0x3a))) {17041704- unsigned char chipstatus;17831783+ unsigned long chipstatus;1705178417061785 /* Reset the error bits */17071786 map_write(map, CMD(0x50), adr);17081787 map_write(map, CMD(0x70), adr);17091788 xip_enable(map, chip, adr);1710178917111711- chipstatus = status.x[0];17121712- if (!map_word_equal(map, status, CMD(chipstatus))) {17131713- int i, w;17141714- for (w=0; w<map_words(map); w++) {17151715- for (i = 0; i<cfi_interleave(cfi); i++) {17161716- chipstatus |= status.x[w] >> (cfi->device_type * 8);17171717- }17181718- }17191719- printk(KERN_WARNING "Status is not identical for all chips: 0x%lx. Merging to give 0x%02x\n",17201720- status.x[0], chipstatus);17211721- }17901790+ chipstatus = MERGESTATUS(status);1722179117231792 if ((chipstatus & 0x30) == 0x30) {17241724- printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%x\n", chipstatus);17931793+ printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%lx\n", chipstatus);17251794 ret = -EIO;17261795 } else if (chipstatus & 0x02) {17271796 /* Protection bit set */17281797 ret = -EROFS;17291798 } else if (chipstatus & 0x8) {17301799 /* Voltage */17311731- printk(KERN_WARNING "Chip reports voltage low on erase: status 0x%x\n", chipstatus);18001800+ printk(KERN_WARNING "Chip reports voltage low on erase: status 0x%lx\n", chipstatus);17321801 ret = -EIO;17331802 } else if (chipstatus & 0x20) {17341803 if (retries--) {17351735- printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x. Retrying...\n", adr, chipstatus);18041804+ printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus);17361805 timeo = jiffies + HZ;17371806 put_chip(map, chip, adr);17381807 spin_unlock(chip->mutex);17391808 goto retry;17401809 }17411741- printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x\n", adr, chipstatus);18101810+ printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%lx\n", adr, chipstatus);17421811 ret = -EIO;17431812 }17441813 } else {···1793188217941883 if (chip->state == FL_SYNCING) {17951884 chip->state = chip->oldstate;18851885+ chip->oldstate = FL_READY;17961886 wake_up(&chip->wq);17971887 }17981888 spin_unlock(chip->mutex);···18091897 struct cfi_private *cfi = map->fldrv_priv;18101898 int status, ofs_factor = cfi->interleave * cfi->device_type;1811189919001900+ adr += chip->start;18121901 xip_disable(map, chip, adr+(2*ofs_factor));18131813- cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);19021902+ map_write(map, CMD(0x90), adr+(2*ofs_factor));18141903 chip->state = FL_JEDEC_QUERY;18151904 status = cfi_read_query(map, adr+(2*ofs_factor));18161905 xip_enable(map, chip, 0);···18281915 unsigned long adr, int len, void *thunk)18291916{18301917 struct cfi_private *cfi = map->fldrv_priv;19181918+ struct cfi_pri_intelext *extp = cfi->cmdset_priv;18311919 map_word status, status_OK;18321920 unsigned long timeo = jiffies + HZ;18331921 int ret;···18581944 } else18591945 BUG();1860194618611861- spin_unlock(chip->mutex);18621862- UDELAY(map, chip, adr, 1000000/HZ);18631863- spin_lock(chip->mutex);19471947+ /*19481948+ * If Instant Individual Block Locking supported then no need19491949+ * to delay.19501950+ */19511951+19521952+ if (!extp || !(extp->FeatureSupport & (1 << 5)))19531953+ UDELAY(map, chip, adr, 1000000/HZ);1864195418651955 /* FIXME. Use a timer to check this, and return immediately. */18661956 /* Once the state machine's known to be working I'll do that */···18911973 }1892197418931975 /* Latency issues. Drop the lock, wait a while and retry */18941894- spin_unlock(chip->mutex);18951976 UDELAY(map, chip, adr, 1);18961896- spin_lock(chip->mutex);18971977 }1898197818991979 /* Done and happy. */···1949203319502034 return ret;19512035}20362036+20372037+#ifdef CONFIG_MTD_OTP20382038+20392039+typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, 20402040+ u_long data_offset, u_char *buf, u_int size,20412041+ u_long prot_offset, u_int groupno, u_int groupsize);20422042+20432043+static int __xipram20442044+do_otp_read(struct map_info *map, struct flchip *chip, u_long offset,20452045+ u_char *buf, u_int size, u_long prot, u_int grpno, u_int grpsz)20462046+{20472047+ struct cfi_private *cfi = map->fldrv_priv;20482048+ int ret;20492049+20502050+ spin_lock(chip->mutex);20512051+ ret = get_chip(map, chip, chip->start, FL_JEDEC_QUERY);20522052+ if (ret) {20532053+ spin_unlock(chip->mutex);20542054+ return ret;20552055+ }20562056+20572057+ /* let's ensure we're not reading back cached data from array mode */20582058+ INVALIDATE_CACHED_RANGE(map, chip->start + offset, size);20592059+20602060+ xip_disable(map, chip, chip->start);20612061+ if (chip->state != FL_JEDEC_QUERY) {20622062+ map_write(map, CMD(0x90), chip->start);20632063+ chip->state = FL_JEDEC_QUERY;20642064+ }20652065+ map_copy_from(map, buf, chip->start + offset, size);20662066+ xip_enable(map, chip, chip->start);20672067+20682068+ /* then ensure we don't keep OTP data in the cache */20692069+ INVALIDATE_CACHED_RANGE(map, chip->start + offset, size);20702070+20712071+ put_chip(map, chip, chip->start);20722072+ spin_unlock(chip->mutex);20732073+ return 0;20742074+}20752075+20762076+static int20772077+do_otp_write(struct map_info *map, struct flchip *chip, u_long offset,20782078+ u_char *buf, u_int size, u_long prot, u_int grpno, u_int grpsz)20792079+{20802080+ int ret;20812081+20822082+ while (size) {20832083+ unsigned long bus_ofs = offset & ~(map_bankwidth(map)-1);20842084+ int gap = offset - bus_ofs;20852085+ int n = min_t(int, size, map_bankwidth(map)-gap);20862086+ map_word datum = map_word_ff(map);20872087+20882088+ datum = map_word_load_partial(map, datum, buf, gap, n);20892089+ ret = do_write_oneword(map, chip, bus_ofs, datum, FL_OTP_WRITE);20902090+ if (ret) 20912091+ return ret;20922092+20932093+ offset += n;20942094+ buf += n;20952095+ size -= n;20962096+ }20972097+20982098+ return 0;20992099+}21002100+21012101+static int21022102+do_otp_lock(struct map_info *map, struct flchip *chip, u_long offset,21032103+ u_char *buf, u_int size, u_long prot, u_int grpno, u_int grpsz)21042104+{21052105+ struct cfi_private *cfi = map->fldrv_priv;21062106+ map_word datum;21072107+21082108+ /* make sure area matches group boundaries */21092109+ if (size != grpsz)21102110+ return -EXDEV;21112111+21122112+ datum = map_word_ff(map);21132113+ datum = map_word_clr(map, datum, CMD(1 << grpno));21142114+ return do_write_oneword(map, chip, prot, datum, FL_OTP_WRITE);21152115+}21162116+21172117+static int cfi_intelext_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,21182118+ size_t *retlen, u_char *buf,21192119+ otp_op_t action, int user_regs)21202120+{21212121+ struct map_info *map = mtd->priv;21222122+ struct cfi_private *cfi = map->fldrv_priv;21232123+ struct cfi_pri_intelext *extp = cfi->cmdset_priv;21242124+ struct flchip *chip;21252125+ struct cfi_intelext_otpinfo *otp;21262126+ u_long devsize, reg_prot_offset, data_offset;21272127+ u_int chip_num, chip_step, field, reg_fact_size, reg_user_size;21282128+ u_int groups, groupno, groupsize, reg_fact_groups, reg_user_groups;21292129+ int ret;21302130+21312131+ *retlen = 0;21322132+21332133+ /* Check that we actually have some OTP registers */21342134+ if (!extp || !(extp->FeatureSupport & 64) || !extp->NumProtectionFields)21352135+ return -ENODATA;21362136+21372137+ /* we need real chips here not virtual ones */21382138+ devsize = (1 << cfi->cfiq->DevSize) * cfi->interleave;21392139+ chip_step = devsize >> cfi->chipshift;21402140+ chip_num = 0;21412141+21422142+ /* Some chips have OTP located in the _top_ partition only.21432143+ For example: Intel 28F256L18T (T means top-parameter device) */21442144+ if (cfi->mfr == MANUFACTURER_INTEL) {21452145+ switch (cfi->id) {21462146+ case 0x880b:21472147+ case 0x880c:21482148+ case 0x880d:21492149+ chip_num = chip_step - 1;21502150+ }21512151+ }21522152+21532153+ for ( ; chip_num < cfi->numchips; chip_num += chip_step) {21542154+ chip = &cfi->chips[chip_num];21552155+ otp = (struct cfi_intelext_otpinfo *)&extp->extra[0];21562156+21572157+ /* first OTP region */21582158+ field = 0;21592159+ reg_prot_offset = extp->ProtRegAddr;21602160+ reg_fact_groups = 1;21612161+ reg_fact_size = 1 << extp->FactProtRegSize;21622162+ reg_user_groups = 1;21632163+ reg_user_size = 1 << extp->UserProtRegSize;21642164+21652165+ while (len > 0) {21662166+ /* flash geometry fixup */21672167+ data_offset = reg_prot_offset + 1;21682168+ data_offset *= cfi->interleave * cfi->device_type;21692169+ reg_prot_offset *= cfi->interleave * cfi->device_type;21702170+ reg_fact_size *= cfi->interleave;21712171+ reg_user_size *= cfi->interleave;21722172+21732173+ if (user_regs) {21742174+ groups = reg_user_groups;21752175+ groupsize = reg_user_size;21762176+ /* skip over factory reg area */21772177+ groupno = reg_fact_groups;21782178+ data_offset += reg_fact_groups * reg_fact_size;21792179+ } else {21802180+ groups = reg_fact_groups;21812181+ groupsize = reg_fact_size;21822182+ groupno = 0;21832183+ }21842184+21852185+ while (len > 0 && groups > 0) {21862186+ if (!action) {21872187+ /*21882188+ * Special case: if action is NULL21892189+ * we fill buf with otp_info records.21902190+ */21912191+ struct otp_info *otpinfo;21922192+ map_word lockword;21932193+ len -= sizeof(struct otp_info);21942194+ if (len <= 0)21952195+ return -ENOSPC;21962196+ ret = do_otp_read(map, chip,21972197+ reg_prot_offset,21982198+ (u_char *)&lockword,21992199+ map_bankwidth(map),22002200+ 0, 0, 0);22012201+ if (ret)22022202+ return ret;22032203+ otpinfo = (struct otp_info *)buf;22042204+ otpinfo->start = from;22052205+ otpinfo->length = groupsize;22062206+ otpinfo->locked =22072207+ !map_word_bitsset(map, lockword,22082208+ CMD(1 << groupno));22092209+ from += groupsize;22102210+ buf += sizeof(*otpinfo);22112211+ *retlen += sizeof(*otpinfo);22122212+ } else if (from >= groupsize) {22132213+ from -= groupsize;22142214+ data_offset += groupsize;22152215+ } else {22162216+ int size = groupsize;22172217+ data_offset += from;22182218+ size -= from;22192219+ from = 0;22202220+ if (size > len)22212221+ size = len;22222222+ ret = action(map, chip, data_offset,22232223+ buf, size, reg_prot_offset,22242224+ groupno, groupsize);22252225+ if (ret < 0)22262226+ return ret;22272227+ buf += size;22282228+ len -= size;22292229+ *retlen += size;22302230+ data_offset += size;22312231+ }22322232+ groupno++;22332233+ groups--;22342234+ }22352235+22362236+ /* next OTP region */22372237+ if (++field == extp->NumProtectionFields)22382238+ break;22392239+ reg_prot_offset = otp->ProtRegAddr;22402240+ reg_fact_groups = otp->FactGroups;22412241+ reg_fact_size = 1 << otp->FactProtRegSize;22422242+ reg_user_groups = otp->UserGroups;22432243+ reg_user_size = 1 << otp->UserProtRegSize;22442244+ otp++;22452245+ }22462246+ }22472247+22482248+ return 0;22492249+}22502250+22512251+static int cfi_intelext_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,22522252+ size_t len, size_t *retlen,22532253+ u_char *buf)22542254+{22552255+ return cfi_intelext_otp_walk(mtd, from, len, retlen,22562256+ buf, do_otp_read, 0);22572257+}22582258+22592259+static int cfi_intelext_read_user_prot_reg(struct mtd_info *mtd, loff_t from,22602260+ size_t len, size_t *retlen,22612261+ u_char *buf)22622262+{22632263+ return cfi_intelext_otp_walk(mtd, from, len, retlen,22642264+ buf, do_otp_read, 1);22652265+}22662266+22672267+static int cfi_intelext_write_user_prot_reg(struct mtd_info *mtd, loff_t from,22682268+ size_t len, size_t *retlen,22692269+ u_char *buf)22702270+{22712271+ return cfi_intelext_otp_walk(mtd, from, len, retlen,22722272+ buf, do_otp_write, 1);22732273+}22742274+22752275+static int cfi_intelext_lock_user_prot_reg(struct mtd_info *mtd,22762276+ loff_t from, size_t len)22772277+{22782278+ size_t retlen;22792279+ return cfi_intelext_otp_walk(mtd, from, len, &retlen,22802280+ NULL, do_otp_lock, 1);22812281+}22822282+22832283+static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd, 22842284+ struct otp_info *buf, size_t len)22852285+{22862286+ size_t retlen;22872287+ int ret;22882288+22892289+ ret = cfi_intelext_otp_walk(mtd, 0, len, &retlen, (u_char *)buf, NULL, 0);22902290+ return ret ? : retlen;22912291+}22922292+22932293+static int cfi_intelext_get_user_prot_info(struct mtd_info *mtd,22942294+ struct otp_info *buf, size_t len)22952295+{22962296+ size_t retlen;22972297+ int ret;22982298+22992299+ ret = cfi_intelext_otp_walk(mtd, 0, len, &retlen, (u_char *)buf, NULL, 1);23002300+ return ret ? : retlen;23012301+}23022302+23032303+#endif1952230419532305static int cfi_intelext_suspend(struct mtd_info *mtd)19542306{···23092125 }23102126}2311212721282128+static int cfi_intelext_reset(struct mtd_info *mtd)21292129+{21302130+ struct map_info *map = mtd->priv;21312131+ struct cfi_private *cfi = map->fldrv_priv;21322132+ int i, ret;21332133+21342134+ for (i=0; i < cfi->numchips; i++) {21352135+ struct flchip *chip = &cfi->chips[i];21362136+21372137+ /* force the completion of any ongoing operation21382138+ and switch to array mode so any bootloader in 21392139+ flash is accessible for soft reboot. */21402140+ spin_lock(chip->mutex);21412141+ ret = get_chip(map, chip, chip->start, FL_SYNCING);21422142+ if (!ret) {21432143+ map_write(map, CMD(0xff), chip->start);21442144+ chip->state = FL_READY;21452145+ }21462146+ spin_unlock(chip->mutex);21472147+ }21482148+21492149+ return 0;21502150+}21512151+21522152+static int cfi_intelext_reboot(struct notifier_block *nb, unsigned long val,21532153+ void *v)21542154+{21552155+ struct mtd_info *mtd;21562156+21572157+ mtd = container_of(nb, struct mtd_info, reboot_notifier);21582158+ cfi_intelext_reset(mtd);21592159+ return NOTIFY_DONE;21602160+}21612161+23122162static void cfi_intelext_destroy(struct mtd_info *mtd)23132163{23142164 struct map_info *map = mtd->priv;23152165 struct cfi_private *cfi = map->fldrv_priv;21662166+ cfi_intelext_reset(mtd);21672167+ unregister_reboot_notifier(&mtd->reboot_notifier);23162168 kfree(cfi->cmdset_priv);23172169 kfree(cfi->cfiq);23182170 kfree(cfi->chips[0].priv);
+380-123
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.114 2004/12/11 15:43:53 dedekind Exp $2020+ * $Id: cfi_cmdset_0002.c,v 1.118 2005/07/04 22:34:29 gleixner 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···4843#define MANUFACTURER_AMD 0x00014944#define MANUFACTURER_SST 0x00BF5045#define SST49LF004B 0x00604646+#define SST49LF008A 0x005a51475248static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);5349static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);···197191};198192static struct cfi_fixup jedec_fixup_table[] = {199193 { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },194194+ { MANUFACTURER_SST, SST49LF008A, fixup_use_fwh_lock, NULL, },200195 { 0, 0, NULL, NULL }201196};202197···398391 * correctly and is therefore not done (particulary with interleaved chips399392 * as each chip must be checked independantly of the others).400393 */401401-static int chip_ready(struct map_info *map, unsigned long addr)394394+static int __xipram chip_ready(struct map_info *map, unsigned long addr)402395{403396 map_word d, t;404397···406399 t = map_read(map, addr);407400408401 return map_word_equal(map, d, t);402402+}403403+404404+/*405405+ * Return true if the chip is ready and has the correct value.406406+ *407407+ * Ready is one of: read mode, query mode, erase-suspend-read mode (in any408408+ * non-suspended sector) and it is indicated by no bits toggling.409409+ *410410+ * Error are indicated by toggling bits or bits held with the wrong value,411411+ * or with bits toggling.412412+ *413413+ * Note that anything more complicated than checking if no bits are toggling414414+ * (including checking DQ5 for an error status) is tricky to get working415415+ * correctly and is therefore not done (particulary with interleaved chips416416+ * as each chip must be checked independantly of the others).417417+ *418418+ */419419+static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected)420420+{421421+ map_word oldd, curd;422422+423423+ oldd = map_read(map, addr);424424+ curd = map_read(map, addr);425425+426426+ return map_word_equal(map, oldd, curd) && 427427+ map_word_equal(map, curd, expected);409428}410429411430static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)···453420454421 if (time_after(jiffies, timeo)) {455422 printk(KERN_ERR "Waiting for chip to be ready timed out.\n");456456- cfi_spin_unlock(chip->mutex);423423+ spin_unlock(chip->mutex);457424 return -EIO;458425 }459459- cfi_spin_unlock(chip->mutex);426426+ spin_unlock(chip->mutex);460427 cfi_udelay(1);461461- cfi_spin_lock(chip->mutex);428428+ spin_lock(chip->mutex);462429 /* Someone else might have been playing with it. */463430 goto retry;464431 }···506473 return -EIO;507474 }508475509509- cfi_spin_unlock(chip->mutex);476476+ spin_unlock(chip->mutex);510477 cfi_udelay(1);511511- cfi_spin_lock(chip->mutex);478478+ spin_lock(chip->mutex);512479 /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING.513480 So we can just loop here. */514481 }482482+ chip->state = FL_READY;483483+ return 0;484484+485485+ case FL_XIP_WHILE_ERASING:486486+ if (mode != FL_READY && mode != FL_POINT &&487487+ (!cfip || !(cfip->EraseSuspend&2)))488488+ goto sleep;489489+ chip->oldstate = chip->state;515490 chip->state = FL_READY;516491 return 0;517492···532491 sleep:533492 set_current_state(TASK_UNINTERRUPTIBLE);534493 add_wait_queue(&chip->wq, &wait);535535- cfi_spin_unlock(chip->mutex);494494+ spin_unlock(chip->mutex);536495 schedule();537496 remove_wait_queue(&chip->wq, &wait);538538- cfi_spin_lock(chip->mutex);497497+ spin_lock(chip->mutex);539498 goto resettime;540499 }541500}···553512 chip->state = FL_ERASING;554513 break;555514515515+ case FL_XIP_WHILE_ERASING:516516+ chip->state = chip->oldstate;517517+ chip->oldstate = FL_READY;518518+ break;519519+556520 case FL_READY:557521 case FL_STATUS:558522 /* We should really make set_vpp() count, rather than doing this */···569523 wake_up(&chip->wq);570524}571525526526+#ifdef CONFIG_MTD_XIP527527+528528+/*529529+ * No interrupt what so ever can be serviced while the flash isn't in array530530+ * mode. This is ensured by the xip_disable() and xip_enable() functions531531+ * enclosing any code path where the flash is known not to be in array mode.532532+ * And within a XIP disabled code path, only functions marked with __xipram533533+ * may be called and nothing else (it's a good thing to inspect generated534534+ * assembly to make sure inline functions were actually inlined and that gcc535535+ * didn't emit calls to its own support functions). Also configuring MTD CFI536536+ * support to a single buswidth and a single interleave is also recommended.537537+ */538538+539539+static void xip_disable(struct map_info *map, struct flchip *chip,540540+ unsigned long adr)541541+{542542+ /* TODO: chips with no XIP use should ignore and return */543543+ (void) map_read(map, adr); /* ensure mmu mapping is up to date */544544+ local_irq_disable();545545+}546546+547547+static void __xipram xip_enable(struct map_info *map, struct flchip *chip,548548+ unsigned long adr)549549+{550550+ struct cfi_private *cfi = map->fldrv_priv;551551+552552+ if (chip->state != FL_POINT && chip->state != FL_READY) {553553+ map_write(map, CMD(0xf0), adr);554554+ chip->state = FL_READY;555555+ }556556+ (void) map_read(map, adr);557557+ xip_iprefetch();558558+ local_irq_enable();559559+}560560+561561+/*562562+ * When a delay is required for the flash operation to complete, the563563+ * xip_udelay() function is polling for both the given timeout and pending564564+ * (but still masked) hardware interrupts. Whenever there is an interrupt565565+ * pending then the flash erase operation is suspended, array mode restored 566566+ * and interrupts unmasked. Task scheduling might also happen at that567567+ * point. The CPU eventually returns from the interrupt or the call to568568+ * schedule() and the suspended flash operation is resumed for the remaining569569+ * of the delay period.570570+ *571571+ * Warning: this function _will_ fool interrupt latency tracing tools.572572+ */573573+574574+static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,575575+ unsigned long adr, int usec)576576+{577577+ struct cfi_private *cfi = map->fldrv_priv;578578+ struct cfi_pri_amdstd *extp = cfi->cmdset_priv;579579+ map_word status, OK = CMD(0x80);580580+ unsigned long suspended, start = xip_currtime();581581+ flstate_t oldstate;582582+583583+ do {584584+ cpu_relax();585585+ if (xip_irqpending() && extp &&586586+ ((chip->state == FL_ERASING && (extp->EraseSuspend & 2))) &&587587+ (cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) {588588+ /*589589+ * Let's suspend the erase operation when supported. 590590+ * Note that we currently don't try to suspend 591591+ * interleaved chips if there is already another 592592+ * operation suspended (imagine what happens593593+ * when one chip was already done with the current594594+ * operation while another chip suspended it, then595595+ * we resume the whole thing at once). Yes, it596596+ * can happen!597597+ */598598+ map_write(map, CMD(0xb0), adr);599599+ usec -= xip_elapsed_since(start);600600+ suspended = xip_currtime();601601+ do {602602+ if (xip_elapsed_since(suspended) > 100000) {603603+ /*604604+ * The chip doesn't want to suspend605605+ * after waiting for 100 msecs.606606+ * This is a critical error but there607607+ * is not much we can do here.608608+ */609609+ return;610610+ }611611+ status = map_read(map, adr);612612+ } while (!map_word_andequal(map, status, OK, OK));613613+614614+ /* Suspend succeeded */615615+ oldstate = chip->state;616616+ if (!map_word_bitsset(map, status, CMD(0x40)))617617+ break;618618+ chip->state = FL_XIP_WHILE_ERASING;619619+ chip->erase_suspended = 1;620620+ map_write(map, CMD(0xf0), adr);621621+ (void) map_read(map, adr);622622+ asm volatile (".rep 8; nop; .endr");623623+ local_irq_enable();624624+ spin_unlock(chip->mutex);625625+ asm volatile (".rep 8; nop; .endr");626626+ cond_resched();627627+628628+ /*629629+ * We're back. However someone else might have630630+ * decided to go write to the chip if we are in631631+ * a suspended erase state. If so let's wait632632+ * until it's done.633633+ */634634+ spin_lock(chip->mutex);635635+ while (chip->state != FL_XIP_WHILE_ERASING) {636636+ DECLARE_WAITQUEUE(wait, current);637637+ set_current_state(TASK_UNINTERRUPTIBLE);638638+ add_wait_queue(&chip->wq, &wait);639639+ spin_unlock(chip->mutex);640640+ schedule();641641+ remove_wait_queue(&chip->wq, &wait);642642+ spin_lock(chip->mutex);643643+ }644644+ /* Disallow XIP again */645645+ local_irq_disable();646646+647647+ /* Resume the write or erase operation */648648+ map_write(map, CMD(0x30), adr);649649+ chip->state = oldstate;650650+ start = xip_currtime();651651+ } else if (usec >= 1000000/HZ) {652652+ /*653653+ * Try to save on CPU power when waiting delay654654+ * is at least a system timer tick period.655655+ * No need to be extremely accurate here.656656+ */657657+ xip_cpu_idle();658658+ }659659+ status = map_read(map, adr);660660+ } while (!map_word_andequal(map, status, OK, OK)661661+ && xip_elapsed_since(start) < usec);662662+}663663+664664+#define UDELAY(map, chip, adr, usec) xip_udelay(map, chip, adr, usec)665665+666666+/*667667+ * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while668668+ * the flash is actively programming or erasing since we have to poll for669669+ * the operation to complete anyway. We can't do that in a generic way with670670+ * a XIP setup so do it before the actual flash operation in this case671671+ * and stub it out from INVALIDATE_CACHE_UDELAY.672672+ */673673+#define XIP_INVAL_CACHED_RANGE(map, from, size) \674674+ INVALIDATE_CACHED_RANGE(map, from, size)675675+676676+#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \677677+ UDELAY(map, chip, adr, usec)678678+679679+/*680680+ * Extra notes:681681+ *682682+ * Activating this XIP support changes the way the code works a bit. For683683+ * example the code to suspend the current process when concurrent access684684+ * happens is never executed because xip_udelay() will always return with the685685+ * same chip state as it was entered with. This is why there is no care for686686+ * the presence of add_wait_queue() or schedule() calls from within a couple687687+ * xip_disable()'d areas of code, like in do_erase_oneblock for example.688688+ * The queueing and scheduling are always happening within xip_udelay().689689+ *690690+ * Similarly, get_chip() and put_chip() just happen to always be executed691691+ * with chip->state set to FL_READY (or FL_XIP_WHILE_*) where flash state692692+ * is in array mode, therefore never executing many cases therein and not693693+ * causing any problem with XIP.694694+ */695695+696696+#else697697+698698+#define xip_disable(map, chip, adr)699699+#define xip_enable(map, chip, adr)700700+#define XIP_INVAL_CACHED_RANGE(x...)701701+702702+#define UDELAY(map, chip, adr, usec) \703703+do { \704704+ spin_unlock(chip->mutex); \705705+ cfi_udelay(usec); \706706+ spin_lock(chip->mutex); \707707+} while (0)708708+709709+#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \710710+do { \711711+ spin_unlock(chip->mutex); \712712+ INVALIDATE_CACHED_RANGE(map, adr, len); \713713+ cfi_udelay(usec); \714714+ spin_lock(chip->mutex); \715715+} while (0)716716+717717+#endif572718573719static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)574720{···773535 /* Ensure cmd read/writes are aligned. */ 774536 cmd_addr = adr & ~(map_bankwidth(map)-1); 775537776776- cfi_spin_lock(chip->mutex);538538+ spin_lock(chip->mutex);777539 ret = get_chip(map, chip, cmd_addr, FL_READY);778540 if (ret) {779779- cfi_spin_unlock(chip->mutex);541541+ spin_unlock(chip->mutex);780542 return ret;781543 }782544···789551790552 put_chip(map, chip, cmd_addr);791553792792- cfi_spin_unlock(chip->mutex);554554+ spin_unlock(chip->mutex);793555 return 0;794556}795557···843605 struct cfi_private *cfi = map->fldrv_priv;844606845607 retry:846846- cfi_spin_lock(chip->mutex);608608+ spin_lock(chip->mutex);847609848610 if (chip->state != FL_READY){849611#if 0···852614 set_current_state(TASK_UNINTERRUPTIBLE);853615 add_wait_queue(&chip->wq, &wait);854616855855- cfi_spin_unlock(chip->mutex);617617+ spin_unlock(chip->mutex);856618857619 schedule();858620 remove_wait_queue(&chip->wq, &wait);···881643 cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);882644883645 wake_up(&chip->wq);884884- cfi_spin_unlock(chip->mutex);646646+ spin_unlock(chip->mutex);885647886648 return 0;887649}···930692}931693932694933933-static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum)695695+static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum)934696{935697 struct cfi_private *cfi = map->fldrv_priv;936698 unsigned long timeo = jiffies + HZ;···950712951713 adr += chip->start;952714953953- cfi_spin_lock(chip->mutex);715715+ spin_lock(chip->mutex);954716 ret = get_chip(map, chip, adr, FL_WRITING);955717 if (ret) {956956- cfi_spin_unlock(chip->mutex);718718+ spin_unlock(chip->mutex);957719 return ret;958720 }959721···973735 goto op_done;974736 }975737738738+ XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));976739 ENABLE_VPP(map);740740+ xip_disable(map, chip, adr);977741 retry:978742 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);979743 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);···983743 map_write(map, datum, adr);984744 chip->state = FL_WRITING;985745986986- cfi_spin_unlock(chip->mutex);987987- cfi_udelay(chip->word_write_time);988988- cfi_spin_lock(chip->mutex);746746+ INVALIDATE_CACHE_UDELAY(map, chip,747747+ adr, map_bankwidth(map),748748+ chip->word_write_time);989749990750 /* See comment above for timeout value. */991751 timeo = jiffies + uWriteTimeout; ···996756997757 set_current_state(TASK_UNINTERRUPTIBLE);998758 add_wait_queue(&chip->wq, &wait);999999- cfi_spin_unlock(chip->mutex);759759+ spin_unlock(chip->mutex);1000760 schedule();1001761 remove_wait_queue(&chip->wq, &wait);1002762 timeo = jiffies + (HZ / 2); /* FIXME */10031003- cfi_spin_lock(chip->mutex);763763+ spin_lock(chip->mutex);1004764 continue;1005765 }10067661007767 if (chip_ready(map, adr))10081008- goto op_done;768768+ break;100976910101010- if (time_after(jiffies, timeo))770770+ if (time_after(jiffies, timeo)) {771771+ xip_enable(map, chip, adr);772772+ printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);773773+ xip_disable(map, chip, adr);1011774 break;775775+ }10127761013777 /* Latency issues. Drop the lock, wait a while and retry */10141014- cfi_spin_unlock(chip->mutex);10151015- cfi_udelay(1);10161016- cfi_spin_lock(chip->mutex);778778+ UDELAY(map, chip, adr, 1);1017779 }780780+ /* Did we succeed? */781781+ if (!chip_good(map, adr, datum)) {782782+ /* reset on all failures. */783783+ map_write( map, CMD(0xF0), chip->start );784784+ /* FIXME - should have reset delay before continuing */101878510191019- printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);786786+ if (++retry_cnt <= MAX_WORD_RETRIES) 787787+ goto retry;102078810211021- /* reset on all failures. */10221022- map_write( map, CMD(0xF0), chip->start );10231023- /* FIXME - should have reset delay before continuing */10241024- if (++retry_cnt <= MAX_WORD_RETRIES) 10251025- goto retry;10261026-10271027- ret = -EIO;789789+ ret = -EIO;790790+ }791791+ xip_enable(map, chip, adr);1028792 op_done:1029793 chip->state = FL_READY;1030794 put_chip(map, chip, adr);10311031- cfi_spin_unlock(chip->mutex);795795+ spin_unlock(chip->mutex);10327961033797 return ret;1034798}···1064820 map_word tmp_buf;10658211066822 retry:10671067- cfi_spin_lock(cfi->chips[chipnum].mutex);823823+ spin_lock(cfi->chips[chipnum].mutex);10688241069825 if (cfi->chips[chipnum].state != FL_READY) {1070826#if 0···1073829 set_current_state(TASK_UNINTERRUPTIBLE);1074830 add_wait_queue(&cfi->chips[chipnum].wq, &wait);107583110761076- cfi_spin_unlock(cfi->chips[chipnum].mutex);832832+ spin_unlock(cfi->chips[chipnum].mutex);10778331078834 schedule();1079835 remove_wait_queue(&cfi->chips[chipnum].wq, &wait);···1087843 /* Load 'tmp_buf' with old contents of flash */1088844 tmp_buf = map_read(map, bus_ofs+chipstart);108984510901090- cfi_spin_unlock(cfi->chips[chipnum].mutex);846846+ spin_unlock(cfi->chips[chipnum].mutex);10918471092848 /* Number of bytes to copy from buffer */1093849 n = min_t(int, len, map_bankwidth(map)-i);···1142898 map_word tmp_buf;11438991144900 retry1:11451145- cfi_spin_lock(cfi->chips[chipnum].mutex);901901+ spin_lock(cfi->chips[chipnum].mutex);11469021147903 if (cfi->chips[chipnum].state != FL_READY) {1148904#if 0···1151907 set_current_state(TASK_UNINTERRUPTIBLE);1152908 add_wait_queue(&cfi->chips[chipnum].wq, &wait);115390911541154- cfi_spin_unlock(cfi->chips[chipnum].mutex);910910+ spin_unlock(cfi->chips[chipnum].mutex);11559111156912 schedule();1157913 remove_wait_queue(&cfi->chips[chipnum].wq, &wait);···11649201165921 tmp_buf = map_read(map, ofs + chipstart);116692211671167- cfi_spin_unlock(cfi->chips[chipnum].mutex);923923+ spin_unlock(cfi->chips[chipnum].mutex);11689241169925 tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);1170926···1183939/*1184940 * FIXME: interleaved mode not tested, and probably not supported!1185941 */11861186-static inline int do_write_buffer(struct map_info *map, struct flchip *chip, 11871187- unsigned long adr, const u_char *buf, int len)942942+static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,943943+ unsigned long adr, const u_char *buf, 944944+ int len)1188945{1189946 struct cfi_private *cfi = map->fldrv_priv;1190947 unsigned long timeo = jiffies + HZ;···1199954 adr += chip->start;1200955 cmd_adr = adr;120195612021202- cfi_spin_lock(chip->mutex);957957+ spin_lock(chip->mutex);1203958 ret = get_chip(map, chip, adr, FL_WRITING);1204959 if (ret) {12051205- cfi_spin_unlock(chip->mutex);960960+ spin_unlock(chip->mutex);1206961 return ret;1207962 }1208963···1211966 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",1212967 __func__, adr, datum.x[0] );1213968969969+ XIP_INVAL_CACHED_RANGE(map, adr, len);1214970 ENABLE_VPP(map);971971+ xip_disable(map, chip, cmd_adr);972972+1215973 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);1216974 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);1217975 //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);···1244996 map_write(map, CMD(0x29), cmd_adr);1245997 chip->state = FL_WRITING;124699812471247- cfi_spin_unlock(chip->mutex);12481248- cfi_udelay(chip->buffer_write_time);12491249- cfi_spin_lock(chip->mutex);999999+ INVALIDATE_CACHE_UDELAY(map, chip,10001000+ adr, map_bankwidth(map),10011001+ chip->word_write_time);1250100212511003 timeo = jiffies + uWriteTimeout; 12521004···1257100912581010 set_current_state(TASK_UNINTERRUPTIBLE);12591011 add_wait_queue(&chip->wq, &wait);12601260- cfi_spin_unlock(chip->mutex);10121012+ spin_unlock(chip->mutex);12611013 schedule();12621014 remove_wait_queue(&chip->wq, &wait);12631015 timeo = jiffies + (HZ / 2); /* FIXME */12641264- cfi_spin_lock(chip->mutex);10161016+ spin_lock(chip->mutex);12651017 continue;12661018 }1267101912681268- if (chip_ready(map, adr))10201020+ if (chip_ready(map, adr)) {10211021+ xip_enable(map, chip, adr);12691022 goto op_done;10231023+ }1270102412711025 if( time_after(jiffies, timeo))12721026 break;1273102712741028 /* 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);10291029+ UDELAY(map, chip, adr, 1);12781030 }12791279-12801280- printk(KERN_WARNING "MTD %s(): software timeout\n",12811281- __func__ );1282103112831032 /* reset on all failures. */12841033 map_write( map, CMD(0xF0), chip->start );10341034+ xip_enable(map, chip, adr);12851035 /* FIXME - should have reset delay before continuing */10361036+10371037+ printk(KERN_WARNING "MTD %s(): software timeout\n",10381038+ __func__ );1286103912871040 ret = -EIO;12881041 op_done:12891042 chip->state = FL_READY;12901043 put_chip(map, chip, adr);12911291- cfi_spin_unlock(chip->mutex);10441044+ spin_unlock(chip->mutex);1292104512931046 return ret;12941047}···13791130 * Handle devices with one erase region, that only implement13801131 * the chip erase command.13811132 */13821382-static inline int do_erase_chip(struct map_info *map, struct flchip *chip)11331133+static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)13831134{13841135 struct cfi_private *cfi = map->fldrv_priv;13851136 unsigned long timeo = jiffies + HZ;···1389114013901141 adr = cfi->addr_unlock1;1391114213921392- cfi_spin_lock(chip->mutex);11431143+ spin_lock(chip->mutex);13931144 ret = get_chip(map, chip, adr, FL_WRITING);13941145 if (ret) {13951395- cfi_spin_unlock(chip->mutex);11461146+ spin_unlock(chip->mutex);13961147 return ret;13971148 }1398114913991150 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",14001151 __func__, chip->start );1401115211531153+ XIP_INVAL_CACHED_RANGE(map, adr, map->size);14021154 ENABLE_VPP(map);11551155+ xip_disable(map, chip, adr);11561156+14031157 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);14041158 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);14051159 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);···14141162 chip->erase_suspended = 0;14151163 chip->in_progress_block_addr = adr;1416116414171417- cfi_spin_unlock(chip->mutex);14181418- msleep(chip->erase_time/2);14191419- cfi_spin_lock(chip->mutex);11651165+ INVALIDATE_CACHE_UDELAY(map, chip,11661166+ adr, map->size,11671167+ chip->erase_time*500);1420116814211169 timeo = jiffies + (HZ*20);14221170···14251173 /* Someone's suspended the erase. Sleep */14261174 set_current_state(TASK_UNINTERRUPTIBLE);14271175 add_wait_queue(&chip->wq, &wait);14281428- cfi_spin_unlock(chip->mutex);11761176+ spin_unlock(chip->mutex);14291177 schedule();14301178 remove_wait_queue(&chip->wq, &wait);14311431- cfi_spin_lock(chip->mutex);11791179+ spin_lock(chip->mutex);14321180 continue;14331181 }14341182 if (chip->erase_suspended) {···14391187 }1440118814411189 if (chip_ready(map, adr))14421442- goto op_done;14431443-14441444- if (time_after(jiffies, timeo))14451190 break;1446119111921192+ if (time_after(jiffies, timeo)) {11931193+ printk(KERN_WARNING "MTD %s(): software timeout\n",11941194+ __func__ );11951195+ break;11961196+ }11971197+14471198 /* Latency issues. Drop the lock, wait a while and retry */14481448- cfi_spin_unlock(chip->mutex);14491449- set_current_state(TASK_UNINTERRUPTIBLE);14501450- schedule_timeout(1);14511451- cfi_spin_lock(chip->mutex);11991199+ UDELAY(map, chip, adr, 1000000/HZ);12001200+ }12011201+ /* Did we succeed? */12021202+ if (!chip_good(map, adr, map_word_ff(map))) {12031203+ /* reset on all failures. */12041204+ map_write( map, CMD(0xF0), chip->start );12051205+ /* FIXME - should have reset delay before continuing */12061206+12071207+ ret = -EIO;14521208 }1453120914541454- printk(KERN_WARNING "MTD %s(): software timeout\n",14551455- __func__ );14561456-14571457- /* reset on all failures. */14581458- map_write( map, CMD(0xF0), chip->start );14591459- /* FIXME - should have reset delay before continuing */14601460-14611461- ret = -EIO;14621462- op_done:14631210 chip->state = FL_READY;12111211+ xip_enable(map, chip, adr);14641212 put_chip(map, chip, adr);14651465- cfi_spin_unlock(chip->mutex);12131213+ spin_unlock(chip->mutex);1466121414671215 return ret;14681216}146912171470121814711471-static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk)12191219+static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk)14721220{14731221 struct cfi_private *cfi = map->fldrv_priv;14741222 unsigned long timeo = jiffies + HZ;···1477122514781226 adr += chip->start;1479122714801480- cfi_spin_lock(chip->mutex);12281228+ spin_lock(chip->mutex);14811229 ret = get_chip(map, chip, adr, FL_ERASING);14821230 if (ret) {14831483- cfi_spin_unlock(chip->mutex);12311231+ spin_unlock(chip->mutex);14841232 return ret;14851233 }1486123414871235 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",14881236 __func__, adr );1489123712381238+ XIP_INVAL_CACHED_RANGE(map, adr, len);14901239 ENABLE_VPP(map);12401240+ xip_disable(map, chip, adr);12411241+14911242 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);14921243 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);14931244 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);···15011246 chip->state = FL_ERASING;15021247 chip->erase_suspended = 0;15031248 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);12491249+12501250+ INVALIDATE_CACHE_UDELAY(map, chip,12511251+ adr, len,12521252+ chip->erase_time*500);1508125315091254 timeo = jiffies + (HZ*20);15101255···15131258 /* Someone's suspended the erase. Sleep */15141259 set_current_state(TASK_UNINTERRUPTIBLE);15151260 add_wait_queue(&chip->wq, &wait);15161516- cfi_spin_unlock(chip->mutex);12611261+ spin_unlock(chip->mutex);15171262 schedule();15181263 remove_wait_queue(&chip->wq, &wait);15191519- cfi_spin_lock(chip->mutex);12641264+ spin_lock(chip->mutex);15201265 continue;15211266 }15221267 if (chip->erase_suspended) {···15261271 chip->erase_suspended = 0;15271272 }1528127315291529- if (chip_ready(map, adr))15301530- goto op_done;15311531-15321532- if (time_after(jiffies, timeo))12741274+ if (chip_ready(map, adr)) {12751275+ xip_enable(map, chip, adr);15331276 break;12771277+ }12781278+12791279+ if (time_after(jiffies, timeo)) {12801280+ xip_enable(map, chip, adr);12811281+ printk(KERN_WARNING "MTD %s(): software timeout\n",12821282+ __func__ );12831283+ break;12841284+ }1534128515351286 /* Latency issues. Drop the lock, wait a while and retry */15361536- cfi_spin_unlock(chip->mutex);15371537- set_current_state(TASK_UNINTERRUPTIBLE);15381538- schedule_timeout(1);15391539- cfi_spin_lock(chip->mutex);12871287+ UDELAY(map, chip, adr, 1000000/HZ);15401288 }15411541-15421542- printk(KERN_WARNING "MTD %s(): software timeout\n",15431543- __func__ );15441544-15451545- /* reset on all failures. */15461546- map_write( map, CMD(0xF0), chip->start );15471547- /* FIXME - should have reset delay before continuing */12891289+ /* Did we succeed? */12901290+ if (!chip_good(map, adr, map_word_ff(map))) {12911291+ /* reset on all failures. */12921292+ map_write( map, CMD(0xF0), chip->start );12931293+ /* FIXME - should have reset delay before continuing */1548129415491549- ret = -EIO;15501550- op_done:12951295+ ret = -EIO;12961296+ }12971297+15511298 chip->state = FL_READY;15521299 put_chip(map, chip, adr);15531553- cfi_spin_unlock(chip->mutex);13001300+ spin_unlock(chip->mutex);15541301 return ret;15551302}15561303···16121355 chip = &cfi->chips[i];1613135616141357 retry:16151615- cfi_spin_lock(chip->mutex);13581358+ spin_lock(chip->mutex);1616135916171360 switch(chip->state) {16181361 case FL_READY:···16261369 * with the chip now anyway.16271370 */16281371 case FL_SYNCING:16291629- cfi_spin_unlock(chip->mutex);13721372+ spin_unlock(chip->mutex);16301373 break;1631137416321375 default:16331376 /* Not an idle state */16341377 add_wait_queue(&chip->wq, &wait);1635137816361636- cfi_spin_unlock(chip->mutex);13791379+ spin_unlock(chip->mutex);1637138016381381 schedule();16391382···16481391 for (i--; i >=0; i--) {16491392 chip = &cfi->chips[i];1650139316511651- cfi_spin_lock(chip->mutex);13941394+ spin_lock(chip->mutex);1652139516531396 if (chip->state == FL_SYNCING) {16541397 chip->state = chip->oldstate;16551398 wake_up(&chip->wq);16561399 }16571657- cfi_spin_unlock(chip->mutex);14001400+ spin_unlock(chip->mutex);16581401 }16591402}16601403···16701413 for (i=0; !ret && i<cfi->numchips; i++) {16711414 chip = &cfi->chips[i];1672141516731673- cfi_spin_lock(chip->mutex);14161416+ spin_lock(chip->mutex);1674141716751418 switch(chip->state) {16761419 case FL_READY:···16901433 ret = -EAGAIN;16911434 break;16921435 }16931693- cfi_spin_unlock(chip->mutex);14361436+ spin_unlock(chip->mutex);16941437 }1695143816961439 /* Unlock the chips again */···16991442 for (i--; i >=0; i--) {17001443 chip = &cfi->chips[i];1701144417021702- cfi_spin_lock(chip->mutex);14451445+ spin_lock(chip->mutex);1703144617041447 if (chip->state == FL_PM_SUSPENDED) {17051448 chip->state = chip->oldstate;17061449 wake_up(&chip->wq);17071450 }17081708- cfi_spin_unlock(chip->mutex);14511451+ spin_unlock(chip->mutex);17091452 }17101453 }17111454···1724146717251468 chip = &cfi->chips[i];1726146917271727- cfi_spin_lock(chip->mutex);14701470+ spin_lock(chip->mutex);1728147117291472 if (chip->state == FL_PM_SUSPENDED) {17301473 chip->state = FL_READY;···17341477 else17351478 printk(KERN_ERR "Argh. Chip not in PM_SUSPENDED state upon resume()\n");1736147917371737- cfi_spin_unlock(chip->mutex);14801480+ spin_unlock(chip->mutex);17381481 }17391482}17401483
+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
+2-2
drivers/mtd/chips/gen_probe.c
···22 * Routines common to all CFI-type probes.33 * (C) 2001-2003 Red Hat, Inc.44 * GPL'd55- * $Id: gen_probe.c,v 1.21 2004/08/14 15:14:05 dwmw2 Exp $55+ * $Id: gen_probe.c,v 1.22 2005/01/24 23:49:50 rmk Exp $66 */7788#include <linux/kernel.h>···162162 int max_chips = map_bankwidth(map); /* And minimum 1 */163163 int nr_chips, type;164164165165- for (nr_chips = min_chips; nr_chips <= max_chips; nr_chips <<= 1) {165165+ for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) {166166167167 if (!cfi_interleave_supported(nr_chips))168168 continue;
+27-1
drivers/mtd/chips/jedec_probe.c
···11/* 22 Common Flash Interface probe code.33 (C) 2000 Red Hat. GPL'd.44- $Id: jedec_probe.c,v 1.61 2004/11/19 20:52:16 thayne Exp $44+ $Id: jedec_probe.c,v 1.63 2005/02/14 16:30:32 bjd Exp $55 See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5)66 for the standard this probe goes back to.77···142142#define SST29LE512 0x003d143143#define SST39LF800 0x2781144144#define SST39LF160 0x2782145145+#define SST39VF1601 0x234b145146#define SST39LF512 0x00D4146147#define SST39LF010 0x00D5147148#define SST39LF020 0x00D6···14491448 ERASEINFO(0x1000,256),14501449 ERASEINFO(0x1000,256)14511450 }14511451+ }, {14521452+ .mfr_id = MANUFACTURER_SST, /* should be CFI */14531453+ .dev_id = SST39VF1601,14541454+ .name = "SST 39VF1601",14551455+ .uaddr = {14561456+ [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */14571457+ [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */14581458+ },14591459+ .DevSize = SIZE_2MiB,14601460+ .CmdSet = P_ID_AMD_STD,14611461+ .NumEraseRegions= 2,14621462+ .regions = {14631463+ ERASEINFO(0x1000,256),14641464+ ERASEINFO(0x1000,256)14651465+ }1452146614531467 }, {14541468 .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */···18721856 case CFI_DEVICETYPE_X8:18731857 mfr = (__u8)finfo->mfr_id;18741858 id = (__u8)finfo->dev_id;18591859+18601860+ /* bjd: it seems that if we do this, we can end up18611861+ * detecting 16bit flashes as an 8bit device, even though18621862+ * there aren't.18631863+ */18641864+ if (finfo->dev_id > 0xff) {18651865+ DEBUG( MTD_DEBUG_LEVEL3, "%s(): ID is not 8bit\n",18661866+ __func__);18671867+ goto match_done;18681868+ }18751869 break;18761870 case CFI_DEVICETYPE_X16:18771871 mfr = (__u16)finfo->mfr_id;
···11/*======================================================================2233- $Id: slram.c,v 1.33 2005/01/05 18:05:13 dwmw2 Exp $33+ $Id: slram.c,v 1.34 2005/01/06 21:16:42 jwboyer Exp $4455 This driver provides a method to access memory not used by the kernel66 itself (i.e. if the kernel commandline mem=xxx is used). To actually···5050#include <linux/mtd/mtd.h>51515252#define SLRAM_MAX_DEVICES_PARAMS 6 /* 3 parameters / device */5353+#define SLRAM_BLK_SZ 0x400053545455#define T(fmt, args...) printk(KERN_DEBUG fmt, ## args)5556#define E(fmt, args...) printk(KERN_NOTICE fmt, ## args)···109108{110109 slram_priv_t *priv = mtd->priv;111110111111+ if (from + len > mtd->size)112112+ return -EINVAL;113113+112114 *mtdbuf = priv->start + from;113115 *retlen = len;114116 return(0);···125121 size_t *retlen, u_char *buf)126122{127123 slram_priv_t *priv = mtd->priv;128128-124124+125125+ if (from > mtd->size)126126+ return -EINVAL;127127+128128+ if (from + len > mtd->size)129129+ len = mtd->size - from;130130+129131 memcpy(buf, priv->start + from, len);130132131133 *retlen = len;···142132 size_t *retlen, const u_char *buf)143133{144134 slram_priv_t *priv = mtd->priv;135135+136136+ if (to + len > mtd->size)137137+ return -EINVAL;145138146139 memcpy(priv->start + to, buf, len);147140···201188 (*curmtd)->mtdinfo->name = name;202189 (*curmtd)->mtdinfo->size = length;203190 (*curmtd)->mtdinfo->flags = MTD_CLEAR_BITS | MTD_SET_BITS |204204- MTD_WRITEB_WRITEABLE | MTD_VOLATILE;191191+ MTD_WRITEB_WRITEABLE | MTD_VOLATILE | MTD_CAP_RAM;205192 (*curmtd)->mtdinfo->erase = slram_erase;206193 (*curmtd)->mtdinfo->point = slram_point;207194 (*curmtd)->mtdinfo->unpoint = slram_unpoint;···209196 (*curmtd)->mtdinfo->write = slram_write;210197 (*curmtd)->mtdinfo->owner = THIS_MODULE;211198 (*curmtd)->mtdinfo->type = MTD_RAM;212212- (*curmtd)->mtdinfo->erasesize = 0x0;199199+ (*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ;213200214201 if (add_mtd_device((*curmtd)->mtdinfo)) {215202 E("slram: Failed to register new device\n");···274261 }275262 T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n",276263 devname, devstart, devlength);277277- if ((devstart < 0) || (devlength < 0)) {264264+ if ((devstart < 0) || (devlength < 0) || (devlength % SLRAM_BLK_SZ != 0)) {278265 E("slram: Illegal start / length parameter.\n");279266 return(-EINVAL);280267 }
+3-2
drivers/mtd/ftl.c
···11/* This version ported to the Linux-MTD system by dwmw2@infradead.org22- * $Id: ftl.c,v 1.54 2004/11/16 18:33:15 dwmw2 Exp $22+ * $Id: ftl.c,v 1.55 2005/01/17 13:47:21 hvr Exp $33 *44 * Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>55 * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups···357357 if (!erase) 358358 return -ENOMEM;359359360360+ erase->mtd = part->mbd.mtd;360361 erase->callback = ftl_erase_callback;361362 erase->addr = xfer->Offset;362363 erase->len = 1 << part->header.EraseUnitSize;···1097109610981097int init_ftl(void)10991098{11001100- DEBUG(0, "$Id: ftl.c,v 1.54 2004/11/16 18:33:15 dwmw2 Exp $\n");10991099+ DEBUG(0, "$Id: ftl.c,v 1.55 2005/01/17 13:47:21 hvr Exp $\n");1101110011021101 return register_mtd_blktrans(&ftl_tr);11031102}
+36-81
drivers/mtd/maps/Kconfig
···11# drivers/mtd/maps/Kconfig22-# $Id: Kconfig,v 1.42 2005/01/05 16:59:50 dwmw2 Exp $22+# $Id: Kconfig,v 1.55 2005/07/02 01:53:24 tpoynor Exp $3344menu "Mapping drivers for chip access"55 depends on MTD!=n···122122 More info at123123 <http://www.arcomcontrols.com/products/icp/pc104/processors/SBC_GX1.htm>.124124125125-config MTD_ELAN_104NC126126- tristate "CFI Flash device mapped on Arcom ELAN-104NC"127127- depends on X86 && MTD_CFI_INTELEXT && MTD_PARTITIONS && MTD_COMPLEX_MAPPINGS128128- help129129- This provides a driver for the on-board flash of the Arcom Control130130- System's ELAN-104NC development board. By default the flash131131- is split into 3 partitions which are accessed as separate MTD132132- devices. This board utilizes Intel StrataFlash. More info at133133- <http://www.arcomcontrols.com/products/icp/pc104/processors/ELAN104NC.htm>.134134-135125config MTD_LUBBOCK136126 tristate "CFI Flash device mapped on Intel Lubbock XScale eval board"137127 depends on ARCH_LUBBOCK && MTD_CFI_INTELEXT && MTD_PARTITIONS138128 help139129 This provides a driver for the on-board flash of the Intel140130 'Lubbock' XScale evaluation board.131131+132132+config MTD_MAINSTONE133133+ tristate "CFI Flash device mapped on Intel Mainstone XScale eval board"134134+ depends on MACH_MAINSTONE && MTD_CFI_INTELEXT135135+ select MTD_PARTITIONS136136+ help137137+ This provides a driver for the on-board flash of the Intel138138+ 'Mainstone PXA27x evaluation board.141139142140config MTD_OCTAGON143141 tristate "JEDEC Flash device mapped on Octagon 5066 SBC"···211213 help212214 Support for flash chips on NETtel/SecureEdge/SnapGear boards.213215214214-config MTD_PB1XXX215215- tristate "Flash devices on Alchemy PB1xxx boards"216216- depends on MIPS && ( MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 )216216+config MTD_ALCHEMY217217+ tristate ' AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support' 218218+ depends on MIPS && SOC_AU1X00217219 help218218- Flash memory access on Alchemy Pb1000/Pb1100/Pb1500 boards219219-220220-config MTD_PB1XXX_BOOT221221- bool "PB1x00 boot flash device"222222- depends on MTD_PB1XXX && ( MIPS_PB1100 || MIPS_PB1500 )223223- help224224- Use the first of the two 32MiB flash banks on Pb1100/Pb1500 board.225225- You can say 'Y' to both this and 'MTD_PB1XXX_USER' below, to use226226- both banks.227227-228228-config MTD_PB1XXX_USER229229- bool "PB1x00 user flash device"230230- depends on MTD_PB1XXX && ( MIPS_PB1100 || MIPS_PB1500 )231231- default y if MTD_PB1XX_BOOT = n232232- help233233- Use the second of the two 32MiB flash banks on Pb1100/Pb1500 board.234234- You can say 'Y' to both this and 'MTD_PB1XXX_BOOT' above, to use235235- both banks.236236-237237-config MTD_PB1550238238- tristate "Flash devices on Alchemy PB1550 board"239239- depends on MIPS && MIPS_PB1550240240- help241241- Flash memory access on Alchemy Pb1550 board242242-243243-config MTD_PB1550_BOOT244244- bool "PB1550 boot flash device"245245- depends on MTD_PB1550246246- help247247- Use the first of the two 64MiB flash banks on Pb1550 board.248248- You can say 'Y' to both this and 'MTD_PB1550_USER' below, to use249249- both banks.250250-251251-config MTD_PB1550_USER252252- bool "PB1550 user flash device"253253- depends on MTD_PB1550254254- default y if MTD_PB1550_BOOT = n255255- help256256- Use the second of the two 64MiB flash banks on Pb1550 board.257257- You can say 'Y' to both this and 'MTD_PB1550_BOOT' above, to use258258- both banks.259259-260260-config MTD_DB1550261261- tristate "Flash devices on Alchemy DB1550 board"262262- depends on MIPS && MIPS_DB1550263263- help264264- Flash memory access on Alchemy Db1550 board265265-266266-config MTD_DB1550_BOOT267267- bool "DB1550 boot flash device"268268- depends on MTD_DB1550269269- help270270- Use the first of the two 64MiB flash banks on Db1550 board.271271- You can say 'Y' to both this and 'MTD_DB1550_USER' below, to use272272- both banks.273273-274274-config MTD_DB1550_USER275275- bool "DB1550 user flash device"276276- depends on MTD_DB1550277277- default y if MTD_DB1550_BOOT = n278278- help279279- Use the second of the two 64MiB flash banks on Db1550 board.280280- You can say 'Y' to both this and 'MTD_DB1550_BOOT' above, to use281281- both banks.220220+ Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards282221283222config MTD_DILNETPC284223 tristate "CFI Flash device mapped on DIL/Net PC"···523588 This enables access to the flash chips on the Interface MPC-1211(CTP/PCI/MPC-SH02).524589 If you have such a board, say 'Y'.525590591591+config MTD_OMAP_NOR592592+ tristate "TI OMAP board mappings"593593+ depends on MTD_CFI && ARCH_OMAP594594+ help595595+ This enables access to the NOR flash chips on TI OMAP-based596596+ boards defining flash platform devices and flash platform data.597597+ These boards include the Innovator, H2, H3, OSK, Perseus2, and598598+ more. If you have such a board, say 'Y'.599599+526600# This needs CFI or JEDEC, depending on the cards found.527601config MTD_PCI528602 tristate "PCI MTD driver"···591647 Map driver for Dy-4 SVME/DMV-182 board.592648593649config MTD_BAST594594- tristate "Map driver for Simtec BAST (EB2410ITX)"595595- depends on ARCH_BAST650650+ tristate "Map driver for Simtec BAST (EB2410ITX) or Thorcom VR1000"651651+ depends on ARCH_BAST || MACH_VR1000596652 select MTD_PARTITIONS597653 select MTD_MAP_BANK_WIDTH_16598654 select MTD_JEDECPROBE599655 help600600- Map driver for NOR flash on the Simtec BAST (EB2410ITX).656656+ Map driver for NOR flash on the Simtec BAST (EB2410ITX), or the657657+ Thorcom VR1000601658602659 Note, this driver *cannot* over-ride the WP link on the603660 board, or currently detect the state of the link.···613668 depends on MTD && ARCH_PXA614669 help615670 This enables access to the flash chip on the Sharp SL Series of PDAs.671671+672672+config MTD_PLATRAM673673+ tristate "Map driver for platform device RAM (mtd-ram)"674674+ depends on MTD675675+ select MTD_RAM676676+ help677677+ Map driver for RAM areas described via the platform device678678+ system.679679+680680+ This selection automatically selects the map_ram driver.616681617682endmenu618683
···11/* linux/drivers/mtd/maps/bast_flash.c22 *33- * Copyright (c) 2004 Simtec Electronics44- * Ben Dooks <ben@simtec.co.uk>33+ * Copyright (c) 2004-2005 Simtec Electronics44+ * Ben Dooks <ben@simtec.co.uk>55 *66 * Simtec Bast (EB2410ITX) NOR MTD Mapping driver77 *88 * Changelog:99 * 20-Sep-2004 BJD Initial version1010+ * 17-Jan-2005 BJD Add whole device if no partitions found1011 *1111- * $Id: bast-flash.c,v 1.1 2004/09/21 14:29:04 bjd Exp $1212+ * $Id: bast-flash.c,v 1.2 2005/01/18 11:13:47 bjd Exp $1213 *1314 * This program is free software; you can redistribute it and/or modify1415 * it under the terms of the GNU General Public License as published by···4746#include <asm/arch/bast-cpld.h>48474948#ifdef CONFIG_MTD_BAST_MAXSIZE5050-#define AREA_MAXSIZE (CONFIG_MTD_BAST_MAXSIZE * (1024*1024))4949+#define AREA_MAXSIZE (CONFIG_MTD_BAST_MAXSIZE * SZ_1M)5150#else5252-#define AREA_MAXSIZE (32*1024*1024)5151+#define AREA_MAXSIZE (32 * SZ_1M)5352#endif54535554#define PFX "bast-flash: "···190189 err = add_mtd_partitions(info->mtd, info->partitions, err);191190 if (err) 192191 printk(KERN_ERR PFX "cannot add/parse partitions\n");192192+ } else {193193+ err = add_mtd_device(info->mtd);193194 }194195195196 if (err == 0)
-187
drivers/mtd/maps/db1550-flash.c
···11-/*22- * Flash memory access on Alchemy Db1550 board33- * 44- * $Id: db1550-flash.c,v 1.7 2004/11/04 13:24:14 gleixner Exp $55- *66- * (C) 2004 Embedded Edge, LLC, based on db1550-flash.c:77- * (C) 2003, 2004 Pete Popov <ppopov@embeddedalley.com>88- * 99- */1010-1111-#include <linux/config.h>1212-#include <linux/init.h>1313-#include <linux/module.h>1414-#include <linux/types.h>1515-#include <linux/kernel.h>1616-1717-#include <linux/mtd/mtd.h>1818-#include <linux/mtd/map.h>1919-#include <linux/mtd/partitions.h>2020-2121-#include <asm/io.h>2222-2323-#ifdef DEBUG_RW2424-#define DBG(x...) printk(x)2525-#else2626-#define DBG(x...) 2727-#endif2828-2929-static unsigned long window_addr;3030-static unsigned long window_size;3131-3232-3333-static struct map_info db1550_map = {3434- .name = "Db1550 flash",3535-};3636-3737-static unsigned char flash_bankwidth = 4;3838-3939-/* 4040- * Support only 64MB NOR Flash parts4141- */4242-4343-#if defined(CONFIG_MTD_DB1550_BOOT) && defined(CONFIG_MTD_DB1550_USER)4444-#define DB1550_BOTH_BANKS4545-#elif defined(CONFIG_MTD_DB1550_BOOT) && !defined(CONFIG_MTD_DB1550_USER)4646-#define DB1550_BOOT_ONLY4747-#elif !defined(CONFIG_MTD_DB1550_BOOT) && defined(CONFIG_MTD_DB1550_USER)4848-#define DB1550_USER_ONLY4949-#endif5050-5151-#ifdef DB1550_BOTH_BANKS5252-/* both banks will be used. Combine the first bank and the first 5353- * part of the second bank together into a single jffs/jffs25454- * partition.5555- */5656-static struct mtd_partition db1550_partitions[] = {5757- /* assume boot[2:0]:swap is '0000' or '1000', which translates to:5858- * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash5959- * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash6060- */6161- {6262- .name = "User FS",6363- .size = (0x1FC00000 - 0x18000000),6464- .offset = 0x00000006565- },{6666- .name = "yamon",6767- .size = 0x0100000,6868- .offset = MTDPART_OFS_APPEND,6969- .mask_flags = MTD_WRITEABLE7070- },{7171- .name = "raw kernel",7272- .size = (0x300000 - 0x40000), /* last 256KB is yamon env */7373- .offset = MTDPART_OFS_APPEND,7474- }7575-};7676-#elif defined(DB1550_BOOT_ONLY)7777-static struct mtd_partition db1550_partitions[] = {7878- /* assume boot[2:0]:swap is '0000' or '1000', which translates to:7979- * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash8080- */8181- {8282- .name = "User FS",8383- .size = 0x03c00000,8484- .offset = 0x00000008585- },{8686- .name = "yamon",8787- .size = 0x0100000,8888- .offset = MTDPART_OFS_APPEND,8989- .mask_flags = MTD_WRITEABLE9090- },{9191- .name = "raw kernel",9292- .size = (0x300000-0x40000), /* last 256KB is yamon env */9393- .offset = MTDPART_OFS_APPEND,9494- }9595-};9696-#elif defined(DB1550_USER_ONLY)9797-static struct mtd_partition db1550_partitions[] = {9898- /* assume boot[2:0]:swap is '0000' or '1000', which translates to:9999- * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash100100- */101101- {102102- .name = "User FS",103103- .size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */104104- .offset = 0x0000000105105- },{106106- .name = "raw kernel",107107- .size = MTDPART_SIZ_FULL,108108- .offset = MTDPART_OFS_APPEND,109109- }110110-};111111-#else112112-#error MTD_DB1550 define combo error /* should never happen */113113-#endif114114-115115-#define NB_OF(x) (sizeof(x)/sizeof(x[0]))116116-117117-static struct mtd_info *mymtd;118118-119119-/*120120- * Probe the flash density and setup window address and size121121- * based on user CONFIG options. There are times when we don't122122- * want the MTD driver to be probing the boot or user flash,123123- * so having the option to enable only one bank is important.124124- */125125-int setup_flash_params(void)126126-{127127-#if defined(DB1550_BOTH_BANKS)128128- window_addr = 0x18000000;129129- window_size = 0x8000000; 130130-#elif defined(DB1550_BOOT_ONLY)131131- window_addr = 0x1C000000;132132- window_size = 0x4000000; 133133-#else /* USER ONLY */134134- window_addr = 0x18000000;135135- window_size = 0x4000000; 136136-#endif137137- return 0;138138-}139139-140140-int __init db1550_mtd_init(void)141141-{142142- struct mtd_partition *parts;143143- int nb_parts = 0;144144-145145- /* Default flash bankwidth */146146- db1550_map.bankwidth = flash_bankwidth;147147-148148- if (setup_flash_params()) 149149- return -ENXIO;150150-151151- /*152152- * Static partition definition selection153153- */154154- parts = db1550_partitions;155155- nb_parts = NB_OF(db1550_partitions);156156- db1550_map.size = window_size;157157-158158- /*159159- * Now let's probe for the actual flash. Do it here since160160- * specific machine settings might have been set above.161161- */162162- printk(KERN_NOTICE "Db1550 flash: probing %d-bit flash bus\n", 163163- db1550_map.bankwidth*8);164164- db1550_map.virt = ioremap(window_addr, window_size);165165- mymtd = do_map_probe("cfi_probe", &db1550_map);166166- if (!mymtd) return -ENXIO;167167- mymtd->owner = THIS_MODULE;168168-169169- add_mtd_partitions(mymtd, parts, nb_parts);170170- return 0;171171-}172172-173173-static void __exit db1550_mtd_cleanup(void)174174-{175175- if (mymtd) {176176- del_mtd_partitions(mymtd);177177- map_destroy(mymtd);178178- iounmap((void *) db1550_map.virt);179179- }180180-}181181-182182-module_init(db1550_mtd_init);183183-module_exit(db1550_mtd_cleanup);184184-185185-MODULE_AUTHOR("Embedded Edge, LLC");186186-MODULE_DESCRIPTION("Db1550 mtd map driver");187187-MODULE_LICENSE("GPL");
-226
drivers/mtd/maps/db1x00-flash.c
···11-/*22- * Flash memory access on Alchemy Db1xxx boards33- * 44- * $Id: db1x00-flash.c,v 1.6 2004/11/04 13:24:14 gleixner Exp $55- *66- * (C) 2003 Pete Popov <ppopov@embeddedalley.com>77- * 88- */99-1010-#include <linux/config.h>1111-#include <linux/module.h>1212-#include <linux/types.h>1313-#include <linux/init.h>1414-#include <linux/kernel.h>1515-1616-#include <linux/mtd/mtd.h>1717-#include <linux/mtd/map.h>1818-#include <linux/mtd/partitions.h>1919-2020-#include <asm/io.h>2121-2222-#ifdef DEBUG_RW2323-#define DBG(x...) printk(x)2424-#else2525-#define DBG(x...) 2626-#endif2727-2828-/* MTD CONFIG OPTIONS */2929-#if defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)3030-#define DB1X00_BOTH_BANKS3131-#elif defined(CONFIG_MTD_DB1X00_BOOT) && !defined(CONFIG_MTD_DB1X00_USER)3232-#define DB1X00_BOOT_ONLY3333-#elif !defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)3434-#define DB1X00_USER_ONLY3535-#endif3636-3737-static unsigned long window_addr;3838-static unsigned long window_size;3939-static unsigned long flash_size;4040-4141-static unsigned short *bcsr = (unsigned short *)0xAE000000;4242-static unsigned char flash_bankwidth = 4;4343-4444-/* 4545- * The Db1x boards support different flash densities. We setup4646- * the mtd_partition structures below for default of 64Mbit 4747- * flash densities, and override the partitions sizes, if4848- * necessary, after we check the board status register.4949- */5050-5151-#ifdef DB1X00_BOTH_BANKS5252-/* both banks will be used. Combine the first bank and the first 5353- * part of the second bank together into a single jffs/jffs25454- * partition.5555- */5656-static struct mtd_partition db1x00_partitions[] = {5757- {5858- .name = "User FS",5959- .size = 0x1c00000,6060- .offset = 0x00000006161- },{6262- .name = "yamon",6363- .size = 0x0100000,6464- .offset = MTDPART_OFS_APPEND,6565- .mask_flags = MTD_WRITEABLE6666- },{6767- .name = "raw kernel",6868- .size = (0x300000-0x40000), /* last 256KB is env */6969- .offset = MTDPART_OFS_APPEND,7070- }7171-};7272-#elif defined(DB1X00_BOOT_ONLY)7373-static struct mtd_partition db1x00_partitions[] = {7474- {7575- .name = "User FS",7676- .size = 0x00c00000,7777- .offset = 0x00000007878- },{7979- .name = "yamon",8080- .size = 0x0100000,8181- .offset = MTDPART_OFS_APPEND,8282- .mask_flags = MTD_WRITEABLE8383- },{8484- .name = "raw kernel",8585- .size = (0x300000-0x40000), /* last 256KB is env */8686- .offset = MTDPART_OFS_APPEND,8787- }8888-};8989-#elif defined(DB1X00_USER_ONLY)9090-static struct mtd_partition db1x00_partitions[] = {9191- {9292- .name = "User FS",9393- .size = 0x0e00000,9494- .offset = 0x00000009595- },{9696- .name = "raw kernel",9797- .size = MTDPART_SIZ_FULL,9898- .offset = MTDPART_OFS_APPEND,9999- }100100-};101101-#else102102-#error MTD_DB1X00 define combo error /* should never happen */103103-#endif104104-#define NB_OF(x) (sizeof(x)/sizeof(x[0]))105105-106106-#define NAME "Db1x00 Linux Flash"107107-108108-static struct map_info db1xxx_mtd_map = {109109- .name = NAME,110110-};111111-112112-static struct mtd_partition *parsed_parts;113113-static struct mtd_info *db1xxx_mtd;114114-115115-/*116116- * Probe the flash density and setup window address and size117117- * based on user CONFIG options. There are times when we don't118118- * want the MTD driver to be probing the boot or user flash,119119- * so having the option to enable only one bank is important.120120- */121121-int setup_flash_params(void)122122-{123123- switch ((bcsr[2] >> 14) & 0x3) {124124- case 0: /* 64Mbit devices */125125- flash_size = 0x800000; /* 8MB per part */126126-#if defined(DB1X00_BOTH_BANKS)127127- window_addr = 0x1E000000;128128- window_size = 0x2000000; 129129-#elif defined(DB1X00_BOOT_ONLY)130130- window_addr = 0x1F000000;131131- window_size = 0x1000000; 132132-#else /* USER ONLY */133133- window_addr = 0x1E000000;134134- window_size = 0x1000000; 135135-#endif136136- break;137137- case 1:138138- /* 128 Mbit devices */139139- flash_size = 0x1000000; /* 16MB per part */140140-#if defined(DB1X00_BOTH_BANKS)141141- window_addr = 0x1C000000;142142- window_size = 0x4000000;143143- /* USERFS from 0x1C00 0000 to 0x1FC0 0000 */144144- db1x00_partitions[0].size = 0x3C00000;145145-#elif defined(DB1X00_BOOT_ONLY)146146- window_addr = 0x1E000000;147147- window_size = 0x2000000;148148- /* USERFS from 0x1E00 0000 to 0x1FC0 0000 */149149- db1x00_partitions[0].size = 0x1C00000;150150-#else /* USER ONLY */151151- window_addr = 0x1C000000;152152- window_size = 0x2000000;153153- /* USERFS from 0x1C00 0000 to 0x1DE00000 */154154- db1x00_partitions[0].size = 0x1DE0000;155155-#endif156156- break;157157- case 2:158158- /* 256 Mbit devices */159159- flash_size = 0x4000000; /* 64MB per part */160160-#if defined(DB1X00_BOTH_BANKS)161161- return 1;162162-#elif defined(DB1X00_BOOT_ONLY)163163- /* Boot ROM flash bank only; no user bank */164164- window_addr = 0x1C000000;165165- window_size = 0x4000000;166166- /* USERFS from 0x1C00 0000 to 0x1FC00000 */167167- db1x00_partitions[0].size = 0x3C00000;168168-#else /* USER ONLY */169169- return 1;170170-#endif171171- break;172172- default:173173- return 1;174174- }175175- db1xxx_mtd_map.size = window_size;176176- db1xxx_mtd_map.bankwidth = flash_bankwidth;177177- db1xxx_mtd_map.phys = window_addr;178178- db1xxx_mtd_map.bankwidth = flash_bankwidth;179179- return 0;180180-}181181-182182-int __init db1x00_mtd_init(void)183183-{184184- struct mtd_partition *parts;185185- int nb_parts = 0;186186-187187- if (setup_flash_params()) 188188- return -ENXIO;189189-190190- /*191191- * Static partition definition selection192192- */193193- parts = db1x00_partitions;194194- nb_parts = NB_OF(db1x00_partitions);195195-196196- /*197197- * Now let's probe for the actual flash. Do it here since198198- * specific machine settings might have been set above.199199- */200200- printk(KERN_NOTICE "Db1xxx flash: probing %d-bit flash bus\n", 201201- db1xxx_mtd_map.bankwidth*8);202202- db1xxx_mtd_map.virt = ioremap(window_addr, window_size);203203- db1xxx_mtd = do_map_probe("cfi_probe", &db1xxx_mtd_map);204204- if (!db1xxx_mtd) return -ENXIO;205205- db1xxx_mtd->owner = THIS_MODULE;206206-207207- add_mtd_partitions(db1xxx_mtd, parts, nb_parts);208208- return 0;209209-}210210-211211-static void __exit db1x00_mtd_cleanup(void)212212-{213213- if (db1xxx_mtd) {214214- del_mtd_partitions(db1xxx_mtd);215215- map_destroy(db1xxx_mtd);216216- if (parsed_parts)217217- kfree(parsed_parts);218218- }219219-}220220-221221-module_init(db1x00_mtd_init);222222-module_exit(db1x00_mtd_cleanup);223223-224224-MODULE_AUTHOR("Pete Popov");225225-MODULE_DESCRIPTION("Db1x00 mtd map driver");226226-MODULE_LICENSE("GPL");
-228
drivers/mtd/maps/elan-104nc.c
···11-/* elan-104nc.c -- MTD map driver for Arcom Control Systems ELAN-104NC22-33- Copyright (C) 2000 Arcom Control System Ltd44-55- This program is free software; you can redistribute it and/or modify66- it under the terms of the GNU General Public License as published by77- the Free Software Foundation; either version 2 of the License, or88- (at your option) any later version.99-1010- This program is distributed in the hope that it will be useful,1111- but WITHOUT ANY WARRANTY; without even the implied warranty of1212- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- GNU General Public License for more details.1414-1515- You should have received a copy of the GNU General Public License1616- along with this program; if not, write to the Free Software1717- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA1818-1919- $Id: elan-104nc.c,v 1.25 2004/11/28 09:40:39 dwmw2 Exp $2020-2121-The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x162222-mode. This drivers uses the CFI probe and Intel Extended Command Set drivers.2323-2424-The flash is accessed as follows:2525-2626- 32 kbyte memory window at 0xb0000-0xb7fff2727-2828- 16 bit I/O port (0x22) for some sort of paging.2929-3030-The single flash device is divided into 3 partition which appear as separate3131-MTD devices.3232-3333-Linux thinks that the I/O port is used by the PIC and hence check_region() will3434-always fail. So we don't do it. I just hope it doesn't break anything.3535-*/3636-#include <linux/module.h>3737-#include <linux/slab.h>3838-#include <linux/ioport.h>3939-#include <linux/init.h>4040-#include <asm/io.h>4141-4242-#include <linux/mtd/map.h>4343-#include <linux/mtd/mtd.h>4444-#include <linux/mtd/partitions.h>4545-4646-#define WINDOW_START 0xb00004747-/* Number of bits in offset. */4848-#define WINDOW_SHIFT 154949-#define WINDOW_LENGTH (1 << WINDOW_SHIFT)5050-/* The bits for the offset into the window. */5151-#define WINDOW_MASK (WINDOW_LENGTH-1)5252-#define PAGE_IO 0x225353-#define PAGE_IO_SIZE 25454-5555-static volatile int page_in_window = -1; // Current page in window.5656-static void __iomem *iomapadr;5757-static DEFINE_SPINLOCK(elan_104nc_spin);5858-5959-/* partition_info gives details on the logical partitions that the split the 6060- * single flash device into. If the size if zero we use up to the end of the6161- * device. */6262-static struct mtd_partition partition_info[]={6363- { .name = "ELAN-104NC flash boot partition", 6464- .offset = 0, 6565- .size = 640*1024 },6666- { .name = "ELAN-104NC flash partition 1", 6767- .offset = 640*1024, 6868- .size = 896*1024 },6969- { .name = "ELAN-104NC flash partition 2", 7070- .offset = (640+896)*1024 }7171-};7272-#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))7373-7474-/*7575- * If no idea what is going on here. This is taken from the FlashFX stuff.7676- */7777-#define ROMCS 17878-7979-static inline void elan_104nc_setup(void)8080-{8181- u16 t;8282-8383- outw( 0x0023 + ROMCS*2, PAGE_IO );8484- t=inb( PAGE_IO+1 );8585-8686- t=(t & 0xf9) | 0x04;8787-8888- outw( ((0x0023 + ROMCS*2) | (t << 8)), PAGE_IO );8989-}9090-9191-static inline void elan_104nc_page(struct map_info *map, unsigned long ofs)9292-{9393- unsigned long page = ofs >> WINDOW_SHIFT;9494-9595- if( page!=page_in_window ) {9696- int cmd1;9797- int cmd2;9898-9999- cmd1=(page & 0x700) + 0x0833 + ROMCS*0x4000;100100- cmd2=((page & 0xff) << 8) + 0x0032;101101-102102- outw( cmd1, PAGE_IO );103103- outw( cmd2, PAGE_IO );104104-105105- page_in_window = page;106106- }107107-}108108-109109-110110-static map_word elan_104nc_read16(struct map_info *map, unsigned long ofs)111111-{112112- map_word ret;113113- spin_lock(&elan_104nc_spin);114114- elan_104nc_page(map, ofs);115115- ret.x[0] = readw(iomapadr + (ofs & WINDOW_MASK));116116- spin_unlock(&elan_104nc_spin);117117- return ret;118118-}119119-120120-static void elan_104nc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)121121-{122122- while (len) {123123- unsigned long thislen = len;124124- if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))125125- thislen = WINDOW_LENGTH-(from & WINDOW_MASK);126126-127127- spin_lock(&elan_104nc_spin);128128- elan_104nc_page(map, from);129129- memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen);130130- spin_unlock(&elan_104nc_spin);131131- to += thislen;132132- from += thislen;133133- len -= thislen;134134- }135135-}136136-137137-static void elan_104nc_write16(struct map_info *map, map_word d, unsigned long adr)138138-{139139- spin_lock(&elan_104nc_spin);140140- elan_104nc_page(map, adr);141141- writew(d.x[0], iomapadr + (adr & WINDOW_MASK));142142- spin_unlock(&elan_104nc_spin);143143-}144144-145145-static void elan_104nc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)146146-{ 147147- while(len) {148148- unsigned long thislen = len;149149- if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))150150- thislen = WINDOW_LENGTH-(to & WINDOW_MASK);151151-152152- spin_lock(&elan_104nc_spin);153153- elan_104nc_page(map, to);154154- memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen);155155- spin_unlock(&elan_104nc_spin);156156- to += thislen;157157- from += thislen;158158- len -= thislen;159159- }160160-}161161-162162-static struct map_info elan_104nc_map = {163163- .name = "ELAN-104NC flash",164164- .phys = NO_XIP,165165- .size = 8*1024*1024, /* this must be set to a maximum possible amount166166- of flash so the cfi probe routines find all167167- the chips */168168- .bankwidth = 2,169169- .read = elan_104nc_read16,170170- .copy_from = elan_104nc_copy_from,171171- .write = elan_104nc_write16,172172- .copy_to = elan_104nc_copy_to173173-};174174-175175-/* MTD device for all of the flash. */176176-static struct mtd_info *all_mtd;177177-178178-static void cleanup_elan_104nc(void)179179-{180180- if( all_mtd ) {181181- del_mtd_partitions( all_mtd );182182- map_destroy( all_mtd );183183- }184184-185185- iounmap(iomapadr);186186-}187187-188188-static int __init init_elan_104nc(void)189189-{190190- /* Urg! We use I/O port 0x22 without request_region()ing it,191191- because it's already allocated to the PIC. */192192-193193- iomapadr = ioremap(WINDOW_START, WINDOW_LENGTH);194194- if (!iomapadr) {195195- printk( KERN_ERR"%s: failed to ioremap memory region\n",196196- elan_104nc_map.name );197197- return -EIO;198198- }199199-200200- printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n",201201- elan_104nc_map.name,202202- PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1,203203- WINDOW_START, WINDOW_START+WINDOW_LENGTH-1 );204204-205205- elan_104nc_setup();206206-207207- /* Probe for chip. */208208- all_mtd = do_map_probe("cfi_probe", &elan_104nc_map );209209- if( !all_mtd ) {210210- cleanup_elan_104nc();211211- return -ENXIO;212212- }213213-214214- all_mtd->owner = THIS_MODULE;215215-216216- /* Create MTD devices for each partition. */217217- add_mtd_partitions( all_mtd, partition_info, NUM_PARTITIONS );218218-219219- return 0;220220-}221221-222222-module_init(init_elan_104nc);223223-module_exit(cleanup_elan_104nc);224224-225225-226226-MODULE_LICENSE("GPL");227227-MODULE_AUTHOR("Arcom Control Systems Ltd.");228228-MODULE_DESCRIPTION("MTD map driver for Arcom Control Systems ELAN-104NC");
···11+/*22+ * $Id: $33+ *44+ * Map driver for the Mainstone developer platform.55+ *66+ * Author: Nicolas Pitre77+ * Copyright: (C) 2001 MontaVista Software Inc.88+ * 99+ * This program is free software; you can redistribute it and/or modify1010+ * it under the terms of the GNU General Public License version 2 as1111+ * published by the Free Software Foundation.1212+ */1313+1414+#include <linux/module.h>1515+#include <linux/types.h>1616+#include <linux/kernel.h>1717+#include <linux/init.h>1818+#include <linux/dma-mapping.h>1919+#include <linux/mtd/mtd.h>2020+#include <linux/mtd/map.h>2121+#include <linux/mtd/partitions.h>2222+#include <asm/io.h>2323+#include <asm/hardware.h>2424+#include <asm/arch/pxa-regs.h>2525+#include <asm/arch/mainstone.h>2626+2727+2828+#define ROM_ADDR 0x000000002929+#define FLASH_ADDR 0x040000003030+3131+#define WINDOW_SIZE 0x040000003232+3333+static void mainstone_map_inval_cache(struct map_info *map, unsigned long from,3434+ ssize_t len)3535+{3636+ consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);3737+}3838+3939+static struct map_info mainstone_maps[2] = { {4040+ .size = WINDOW_SIZE,4141+ .phys = PXA_CS0_PHYS,4242+ .inval_cache = mainstone_map_inval_cache,4343+}, {4444+ .size = WINDOW_SIZE,4545+ .phys = PXA_CS1_PHYS,4646+ .inval_cache = mainstone_map_inval_cache,4747+} };4848+4949+static struct mtd_partition mainstone_partitions[] = {5050+ {5151+ .name = "Bootloader",5252+ .size = 0x00040000,5353+ .offset = 0,5454+ .mask_flags = MTD_WRITEABLE /* force read-only */5555+ },{5656+ .name = "Kernel",5757+ .size = 0x00400000,5858+ .offset = 0x00040000,5959+ },{6060+ .name = "Filesystem",6161+ .size = MTDPART_SIZ_FULL,6262+ .offset = 0x004400006363+ }6464+};6565+6666+static struct mtd_info *mymtds[2];6767+static struct mtd_partition *parsed_parts[2];6868+static int nr_parsed_parts[2];6969+7070+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };7171+7272+static int __init init_mainstone(void)7373+{7474+ int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */7575+ int ret = 0, i;7676+7777+ mainstone_maps[0].bankwidth = (BOOT_DEF & 1) ? 2 : 4;7878+ mainstone_maps[1].bankwidth = 4;7979+8080+ /* Compensate for SW7 which swaps the flash banks */8181+ mainstone_maps[SW7].name = "processor flash";8282+ mainstone_maps[SW7 ^ 1].name = "main board flash";8383+8484+ printk(KERN_NOTICE "Mainstone configured to boot from %s\n",8585+ mainstone_maps[0].name);8686+8787+ for (i = 0; i < 2; i++) {8888+ mainstone_maps[i].virt = ioremap(mainstone_maps[i].phys,8989+ WINDOW_SIZE);9090+ if (!mainstone_maps[i].virt) {9191+ printk(KERN_WARNING "Failed to ioremap %s\n", 9292+ mainstone_maps[i].name);9393+ if (!ret)9494+ ret = -ENOMEM;9595+ continue;9696+ }9797+ mainstone_maps[i].cached = 9898+ ioremap_cached(mainstone_maps[i].phys, WINDOW_SIZE);9999+ if (!mainstone_maps[i].cached)100100+ printk(KERN_WARNING "Failed to ioremap cached %s\n",101101+ mainstone_maps[i].name);102102+ simple_map_init(&mainstone_maps[i]);103103+104104+ printk(KERN_NOTICE 105105+ "Probing %s at physical address 0x%08lx"106106+ " (%d-bit bankwidth)\n",107107+ mainstone_maps[i].name, mainstone_maps[i].phys, 108108+ mainstone_maps[i].bankwidth * 8);109109+110110+ mymtds[i] = do_map_probe("cfi_probe", &mainstone_maps[i]);111111+112112+ if (!mymtds[i]) {113113+ iounmap((void *)mainstone_maps[i].virt);114114+ if (mainstone_maps[i].cached)115115+ iounmap(mainstone_maps[i].cached);116116+ if (!ret)117117+ ret = -EIO;118118+ continue;119119+ }120120+ mymtds[i]->owner = THIS_MODULE;121121+122122+ ret = parse_mtd_partitions(mymtds[i], probes,123123+ &parsed_parts[i], 0);124124+125125+ if (ret > 0)126126+ nr_parsed_parts[i] = ret;127127+ }128128+129129+ if (!mymtds[0] && !mymtds[1])130130+ return ret;131131+132132+ for (i = 0; i < 2; i++) {133133+ if (!mymtds[i]) {134134+ printk(KERN_WARNING "%s is absent. Skipping\n", 135135+ mainstone_maps[i].name);136136+ } else if (nr_parsed_parts[i]) {137137+ add_mtd_partitions(mymtds[i], parsed_parts[i], 138138+ nr_parsed_parts[i]);139139+ } else if (!i) {140140+ printk("Using static partitions on %s\n",141141+ mainstone_maps[i].name);142142+ add_mtd_partitions(mymtds[i], mainstone_partitions, 143143+ ARRAY_SIZE(mainstone_partitions));144144+ } else {145145+ printk("Registering %s as whole device\n", 146146+ mainstone_maps[i].name);147147+ add_mtd_device(mymtds[i]);148148+ }149149+ }150150+ return 0;151151+}152152+153153+static void __exit cleanup_mainstone(void)154154+{155155+ int i;156156+ for (i = 0; i < 2; i++) {157157+ if (!mymtds[i])158158+ continue;159159+160160+ if (nr_parsed_parts[i] || !i)161161+ del_mtd_partitions(mymtds[i]);162162+ else163163+ del_mtd_device(mymtds[i]);164164+165165+ map_destroy(mymtds[i]);166166+ iounmap((void *)mainstone_maps[i].virt);167167+ if (mainstone_maps[i].cached)168168+ iounmap(mainstone_maps[i].cached);169169+ kfree(parsed_parts[i]);170170+ }171171+}172172+173173+module_init(init_mainstone);174174+module_exit(cleanup_mainstone);175175+176176+MODULE_LICENSE("GPL");177177+MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");178178+MODULE_DESCRIPTION("MTD map driver for Intel Mainstone");
+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}
+179
drivers/mtd/maps/omap_nor.c
···11+/*22+ * Flash memory support for various TI OMAP boards33+ *44+ * Copyright (C) 2001-2002 MontaVista Software Inc.55+ * Copyright (C) 2003-2004 Texas Instruments66+ * Copyright (C) 2004 Nokia Corporation 77+ *88+ * Assembled using driver code copyright the companies above99+ * and written by David Brownell, Jian Zhang <jzhang@ti.com>,1010+ * Tony Lindgren <tony@atomide.com> and others.1111+ *1212+ * This program is free software; you can redistribute it and/or modify it1313+ * under the terms of the GNU General Public License as published by the1414+ * Free Software Foundation; either version 2 of the License, or (at your1515+ * option) any later version.1616+ *1717+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED1818+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF1919+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN2020+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,2121+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT2222+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF2323+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON2424+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT2525+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF2626+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2727+ *2828+ * You should have received a copy of the GNU General Public License along2929+ * with this program; if not, write to the Free Software Foundation, Inc.,3030+ * 675 Mass Ave, Cambridge, MA 02139, USA.3131+ */3232+3333+#include <linux/device.h>3434+#include <linux/module.h>3535+#include <linux/types.h>3636+#include <linux/kernel.h>3737+#include <linux/init.h>3838+#include <linux/ioport.h>3939+#include <linux/mtd/mtd.h>4040+#include <linux/mtd/map.h>4141+#include <linux/mtd/partitions.h>4242+4343+#include <asm/io.h>4444+#include <asm/hardware.h>4545+#include <asm/mach-types.h>4646+#include <asm/mach/flash.h>4747+#include <asm/arch/tc.h>4848+4949+#ifdef CONFIG_MTD_PARTITIONS5050+static const char *part_probes[] = { /* "RedBoot", */ "cmdlinepart", NULL };5151+#endif5252+5353+struct omapflash_info {5454+ struct mtd_partition *parts;5555+ struct mtd_info *mtd;5656+ struct map_info map;5757+};5858+5959+static void omap_set_vpp(struct map_info *map, int enable)6060+{6161+ static int count;6262+6363+ if (enable) {6464+ if (count++ == 0)6565+ OMAP_EMIFS_CONFIG_REG |= OMAP_EMIFS_CONFIG_WP;6666+ } else {6767+ if (count && (--count == 0))6868+ OMAP_EMIFS_CONFIG_REG &= ~OMAP_EMIFS_CONFIG_WP;6969+ }7070+}7171+7272+static int __devinit omapflash_probe(struct device *dev)7373+{7474+ int err;7575+ struct omapflash_info *info;7676+ struct platform_device *pdev = to_platform_device(dev);7777+ struct flash_platform_data *pdata = pdev->dev.platform_data;7878+ struct resource *res = pdev->resource;7979+ unsigned long size = res->end - res->start + 1;8080+8181+ info = kmalloc(sizeof(struct omapflash_info), GFP_KERNEL);8282+ if (!info)8383+ return -ENOMEM;8484+8585+ memset(info, 0, sizeof(struct omapflash_info));8686+8787+ if (!request_mem_region(res->start, size, "flash")) {8888+ err = -EBUSY;8989+ goto out_free_info;9090+ }9191+9292+ info->map.virt = ioremap(res->start, size);9393+ if (!info->map.virt) {9494+ err = -ENOMEM;9595+ goto out_release_mem_region;9696+ }9797+ info->map.name = pdev->dev.bus_id;9898+ info->map.phys = res->start;9999+ info->map.size = size;100100+ info->map.bankwidth = pdata->width;101101+ info->map.set_vpp = omap_set_vpp;102102+103103+ simple_map_init(&info->map);104104+ info->mtd = do_map_probe(pdata->map_name, &info->map);105105+ if (!info->mtd) {106106+ err = -EIO;107107+ goto out_iounmap;108108+ }109109+ info->mtd->owner = THIS_MODULE;110110+111111+#ifdef CONFIG_MTD_PARTITIONS112112+ err = parse_mtd_partitions(info->mtd, part_probes, &info->parts, 0);113113+ if (err > 0)114114+ add_mtd_partitions(info->mtd, info->parts, err);115115+ else if (err < 0 && pdata->parts)116116+ add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);117117+ else118118+#endif119119+ add_mtd_device(info->mtd);120120+121121+ dev_set_drvdata(&pdev->dev, info);122122+123123+ return 0;124124+125125+out_iounmap:126126+ iounmap(info->map.virt);127127+out_release_mem_region:128128+ release_mem_region(res->start, size);129129+out_free_info:130130+ kfree(info);131131+132132+ return err;133133+}134134+135135+static int __devexit omapflash_remove(struct device *dev)136136+{137137+ struct platform_device *pdev = to_platform_device(dev);138138+ struct omapflash_info *info = dev_get_drvdata(&pdev->dev);139139+140140+ dev_set_drvdata(&pdev->dev, NULL);141141+142142+ if (info) {143143+ if (info->parts) {144144+ del_mtd_partitions(info->mtd);145145+ kfree(info->parts);146146+ } else147147+ del_mtd_device(info->mtd);148148+ map_destroy(info->mtd);149149+ release_mem_region(info->map.phys, info->map.size);150150+ iounmap((void __iomem *) info->map.virt);151151+ kfree(info);152152+ }153153+154154+ return 0;155155+}156156+157157+static struct device_driver omapflash_driver = {158158+ .name = "omapflash",159159+ .bus = &platform_bus_type,160160+ .probe = omapflash_probe,161161+ .remove = __devexit_p(omapflash_remove),162162+};163163+164164+static int __init omapflash_init(void)165165+{166166+ return driver_register(&omapflash_driver);167167+}168168+169169+static void __exit omapflash_exit(void)170170+{171171+ driver_unregister(&omapflash_driver);172172+}173173+174174+module_init(omapflash_init);175175+module_exit(omapflash_exit);176176+177177+MODULE_LICENSE("GPL");178178+MODULE_DESCRIPTION("MTD NOR map driver for TI OMAP boards");179179+
-203
drivers/mtd/maps/pb1550-flash.c
···11-/*22- * Flash memory access on Alchemy Pb1550 board33- * 44- * $Id: pb1550-flash.c,v 1.6 2004/11/04 13:24:15 gleixner Exp $55- *66- * (C) 2004 Embedded Edge, LLC, based on pb1550-flash.c:77- * (C) 2003 Pete Popov <ppopov@pacbell.net>88- * 99- */1010-1111-#include <linux/config.h>1212-#include <linux/init.h>1313-#include <linux/module.h>1414-#include <linux/types.h>1515-#include <linux/kernel.h>1616-1717-#include <linux/mtd/mtd.h>1818-#include <linux/mtd/map.h>1919-#include <linux/mtd/partitions.h>2020-2121-#include <asm/io.h>2222-#include <asm/au1000.h>2323-#include <asm/pb1550.h>2424-2525-#ifdef DEBUG_RW2626-#define DBG(x...) printk(x)2727-#else2828-#define DBG(x...) 2929-#endif3030-3131-static unsigned long window_addr;3232-static unsigned long window_size;3333-3434-3535-static struct map_info pb1550_map = {3636- .name = "Pb1550 flash",3737-};3838-3939-static unsigned char flash_bankwidth = 4;4040-4141-/* 4242- * Support only 64MB NOR Flash parts4343- */4444-4545-#ifdef PB1550_BOTH_BANKS4646-/* both banks will be used. Combine the first bank and the first 4747- * part of the second bank together into a single jffs/jffs24848- * partition.4949- */5050-static struct mtd_partition pb1550_partitions[] = {5151- /* assume boot[2:0]:swap is '0000' or '1000', which translates to:5252- * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash5353- * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash5454- */5555- {5656- .name = "User FS",5757- .size = (0x1FC00000 - 0x18000000),5858- .offset = 0x00000005959- },{6060- .name = "yamon",6161- .size = 0x0100000,6262- .offset = MTDPART_OFS_APPEND,6363- .mask_flags = MTD_WRITEABLE6464- },{6565- .name = "raw kernel",6666- .size = (0x300000 - 0x40000), /* last 256KB is yamon env */6767- .offset = MTDPART_OFS_APPEND,6868- }6969-};7070-#elif defined(PB1550_BOOT_ONLY)7171-static struct mtd_partition pb1550_partitions[] = {7272- /* assume boot[2:0]:swap is '0000' or '1000', which translates to:7373- * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash7474- */7575- {7676- .name = "User FS",7777- .size = 0x03c00000,7878- .offset = 0x00000007979- },{8080- .name = "yamon",8181- .size = 0x0100000,8282- .offset = MTDPART_OFS_APPEND,8383- .mask_flags = MTD_WRITEABLE8484- },{8585- .name = "raw kernel",8686- .size = (0x300000-0x40000), /* last 256KB is yamon env */8787- .offset = MTDPART_OFS_APPEND,8888- }8989-};9090-#elif defined(PB1550_USER_ONLY)9191-static struct mtd_partition pb1550_partitions[] = {9292- /* assume boot[2:0]:swap is '0000' or '1000', which translates to:9393- * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash9494- */9595- {9696- .name = "User FS",9797- .size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */9898- .offset = 0x00000009999- },{100100- .name = "raw kernel",101101- .size = MTDPART_SIZ_FULL,102102- .offset = MTDPART_OFS_APPEND,103103- }104104-};105105-#else106106-#error MTD_PB1550 define combo error /* should never happen */107107-#endif108108-109109-#define NB_OF(x) (sizeof(x)/sizeof(x[0]))110110-111111-static struct mtd_info *mymtd;112112-113113-/*114114- * Probe the flash density and setup window address and size115115- * based on user CONFIG options. There are times when we don't116116- * want the MTD driver to be probing the boot or user flash,117117- * so having the option to enable only one bank is important.118118- */119119-int setup_flash_params(void)120120-{121121- u16 boot_swapboot;122122- boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) | 123123- ((bcsr->status >> 6) & 0x1);124124- printk("Pb1550 MTD: boot:swap %d\n", boot_swapboot);125125-126126- switch (boot_swapboot) {127127- case 0: /* 512Mbit devices, both enabled */128128- case 1: 129129- case 8:130130- case 9: 131131-#if defined(PB1550_BOTH_BANKS)132132- window_addr = 0x18000000;133133- window_size = 0x8000000; 134134-#elif defined(PB1550_BOOT_ONLY)135135- window_addr = 0x1C000000;136136- window_size = 0x4000000; 137137-#else /* USER ONLY */138138- window_addr = 0x1E000000;139139- window_size = 0x4000000; 140140-#endif141141- break;142142- case 0xC:143143- case 0xD:144144- case 0xE:145145- case 0xF: 146146- /* 64 MB Boot NOR Flash is disabled */147147- /* and the start address is moved to 0x0C00000 */148148- window_addr = 0x0C000000;149149- window_size = 0x4000000; 150150- default:151151- printk("Pb1550 MTD: unsupported boot:swap setting\n");152152- return 1;153153- }154154- return 0;155155-}156156-157157-int __init pb1550_mtd_init(void)158158-{159159- struct mtd_partition *parts;160160- int nb_parts = 0;161161-162162- /* Default flash bankwidth */163163- pb1550_map.bankwidth = flash_bankwidth;164164-165165- if (setup_flash_params()) 166166- return -ENXIO;167167-168168- /*169169- * Static partition definition selection170170- */171171- parts = pb1550_partitions;172172- nb_parts = NB_OF(pb1550_partitions);173173- pb1550_map.size = window_size;174174-175175- /*176176- * Now let's probe for the actual flash. Do it here since177177- * specific machine settings might have been set above.178178- */179179- printk(KERN_NOTICE "Pb1550 flash: probing %d-bit flash bus\n", 180180- pb1550_map.bankwidth*8);181181- pb1550_map.virt = ioremap(window_addr, window_size);182182- mymtd = do_map_probe("cfi_probe", &pb1550_map);183183- if (!mymtd) return -ENXIO;184184- mymtd->owner = THIS_MODULE;185185-186186- add_mtd_partitions(mymtd, parts, nb_parts);187187- return 0;188188-}189189-190190-static void __exit pb1550_mtd_cleanup(void)191191-{192192- if (mymtd) {193193- del_mtd_partitions(mymtd);194194- map_destroy(mymtd);195195- }196196-}197197-198198-module_init(pb1550_mtd_init);199199-module_exit(pb1550_mtd_cleanup);200200-201201-MODULE_AUTHOR("Embedded Edge, LLC");202202-MODULE_DESCRIPTION("Pb1550 mtd map driver");203203-MODULE_LICENSE("GPL");
···77 * it under the terms of the GNU General Public License version 2 as88 * published by the Free Software Foundation.99 *1010- * $Id: pci.c,v 1.9 2004/11/28 09:40:40 dwmw2 Exp $1010+ * $Id: pci.c,v 1.10 2005/03/18 14:04:35 gleixner Exp $1111 * 1212 * Generic PCI memory map driver. We support the following boards:1313 * - Intel IQ80310 ATU.···370370371371static int __init mtd_pci_maps_init(void)372372{373373- return pci_module_init(&mtd_pci_driver);373373+ return pci_register_driver(&mtd_pci_driver);374374}375375376376static void __exit mtd_pci_maps_exit(void)
+278
drivers/mtd/maps/plat-ram.c
···11+/* drivers/mtd/maps/plat-ram.c22+ *33+ * (c) 2004-2005 Simtec Electronics44+ * http://www.simtec.co.uk/products/SWLINUX/55+ * Ben Dooks <ben@simtec.co.uk>66+ *77+ * Generic platfrom device based RAM map88+ *99+ * $Id: plat-ram.c,v 1.3 2005/03/19 22:41:27 gleixner Exp $1010+ *1111+ * This program is free software; you can redistribute it and/or modify1212+ * it under the terms of the GNU General Public License as published by1313+ * the Free Software Foundation; either version 2 of the License, or1414+ * (at your option) any later version.1515+ *1616+ * This program is distributed in the hope that it will be useful,1717+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1818+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1919+ * GNU General Public License for more details.2020+ *2121+ * You should have received a copy of the GNU General Public License2222+ * along with this program; if not, write to the Free Software2323+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA2424+*/2525+2626+#include <linux/module.h>2727+#include <linux/types.h>2828+#include <linux/init.h>2929+#include <linux/kernel.h>3030+#include <linux/string.h>3131+#include <linux/ioport.h>3232+#include <linux/device.h>3333+3434+#include <linux/mtd/mtd.h>3535+#include <linux/mtd/map.h>3636+#include <linux/mtd/partitions.h>3737+#include <linux/mtd/plat-ram.h>3838+3939+#include <asm/io.h>4040+4141+/* private structure for each mtd platform ram device created */4242+4343+struct platram_info {4444+ struct device *dev;4545+ struct mtd_info *mtd;4646+ struct map_info map;4747+ struct mtd_partition *partitions;4848+ struct resource *area;4949+ struct platdata_mtd_ram *pdata;5050+};5151+5252+/* to_platram_info()5353+ *5454+ * device private data to struct platram_info conversion5555+*/5656+5757+static inline struct platram_info *to_platram_info(struct device *dev)5858+{5959+ return (struct platram_info *)dev_get_drvdata(dev);6060+}6161+6262+/* platram_setrw6363+ *6464+ * call the platform device's set rw/ro control6565+ *6666+ * to = 0 => read-only6767+ * = 1 => read-write6868+*/6969+7070+static inline void platram_setrw(struct platram_info *info, int to)7171+{7272+ if (info->pdata == NULL)7373+ return;7474+7575+ if (info->pdata->set_rw != NULL)7676+ (info->pdata->set_rw)(info->dev, to);7777+}7878+7979+/* platram_remove8080+ *8181+ * called to remove the device from the driver's control8282+*/8383+8484+static int platram_remove(struct device *dev)8585+{8686+ struct platram_info *info = to_platram_info(dev);8787+8888+ dev_set_drvdata(dev, NULL);8989+9090+ dev_dbg(dev, "removing device\n");9191+9292+ if (info == NULL) 9393+ return 0;9494+9595+ if (info->mtd) {9696+#ifdef CONFIG_MTD_PARTITIONS9797+ if (info->partitions) {9898+ del_mtd_partitions(info->mtd);9999+ kfree(info->partitions);100100+ }101101+#endif102102+ del_mtd_device(info->mtd);103103+ map_destroy(info->mtd);104104+ }105105+106106+ /* ensure ram is left read-only */107107+108108+ platram_setrw(info, PLATRAM_RO);109109+110110+ /* release resources */111111+112112+ if (info->area) {113113+ release_resource(info->area);114114+ kfree(info->area);115115+ }116116+117117+ if (info->map.virt != NULL)118118+ iounmap(info->map.virt);119119+120120+ kfree(info);121121+122122+ return 0;123123+}124124+125125+/* platram_probe126126+ *127127+ * called from device drive system when a device matching our128128+ * driver is found.129129+*/130130+131131+static int platram_probe(struct device *dev)132132+{133133+ struct platform_device *pd = to_platform_device(dev);134134+ struct platdata_mtd_ram *pdata;135135+ struct platram_info *info;136136+ struct resource *res;137137+ int err = 0;138138+139139+ dev_dbg(dev, "probe entered\n");140140+141141+ if (dev->platform_data == NULL) {142142+ dev_err(dev, "no platform data supplied\n");143143+ err = -ENOENT;144144+ goto exit_error;145145+ }146146+147147+ pdata = dev->platform_data;148148+149149+ info = kmalloc(sizeof(*info), GFP_KERNEL);150150+ if (info == NULL) {151151+ dev_err(dev, "no memory for flash info\n");152152+ err = -ENOMEM;153153+ goto exit_error;154154+ }155155+156156+ memset(info, 0, sizeof(*info));157157+ dev_set_drvdata(dev, info);158158+159159+ info->dev = dev;160160+ info->pdata = pdata;161161+162162+ /* get the resource for the memory mapping */163163+164164+ res = platform_get_resource(pd, IORESOURCE_MEM, 0);165165+166166+ if (res == NULL) {167167+ dev_err(dev, "no memory resource specified\n");168168+ err = -ENOENT;169169+ goto exit_free;170170+ }171171+172172+ dev_dbg(dev, "got platform resource %p (0x%lx)\n", res, res->start);173173+174174+ /* setup map parameters */175175+176176+ info->map.phys = res->start;177177+ info->map.size = (res->end - res->start) + 1;178178+ info->map.name = pdata->mapname != NULL ? pdata->mapname : pd->name;179179+ info->map.bankwidth = pdata->bankwidth;180180+181181+ /* register our usage of the memory area */182182+183183+ info->area = request_mem_region(res->start, info->map.size, pd->name);184184+ if (info->area == NULL) {185185+ dev_err(dev, "failed to request memory region\n");186186+ err = -EIO;187187+ goto exit_free;188188+ }189189+190190+ /* remap the memory area */191191+192192+ info->map.virt = ioremap(res->start, info->map.size);193193+ dev_dbg(dev, "virt %p, %lu bytes\n", info->map.virt, info->map.size);194194+195195+ if (info->map.virt == NULL) {196196+ dev_err(dev, "failed to ioremap() region\n");197197+ err = -EIO;198198+ goto exit_free;199199+ }200200+201201+ simple_map_init(&info->map);202202+203203+ dev_dbg(dev, "initialised map, probing for mtd\n");204204+205205+ /* probe for the right mtd map driver */206206+207207+ info->mtd = do_map_probe("map_ram" , &info->map);208208+ if (info->mtd == NULL) {209209+ dev_err(dev, "failed to probe for map_ram\n");210210+ err = -ENOMEM;211211+ goto exit_free;212212+ }213213+214214+ info->mtd->owner = THIS_MODULE;215215+216216+ platram_setrw(info, PLATRAM_RW);217217+218218+ /* check to see if there are any available partitions, or wether219219+ * to add this device whole */220220+221221+#ifdef CONFIG_MTD_PARTITIONS222222+ if (pdata->nr_partitions > 0) {223223+ const char **probes = { NULL };224224+225225+ if (pdata->probes)226226+ probes = (const char **)pdata->probes;227227+228228+ err = parse_mtd_partitions(info->mtd, probes,229229+ &info->partitions, 0);230230+ if (err > 0) {231231+ err = add_mtd_partitions(info->mtd, info->partitions,232232+ err);233233+ }234234+ }235235+#endif /* CONFIG_MTD_PARTITIONS */236236+237237+ if (add_mtd_device(info->mtd)) {238238+ dev_err(dev, "add_mtd_device() failed\n");239239+ err = -ENOMEM;240240+ }241241+242242+ dev_info(dev, "registered mtd device\n");243243+ return err;244244+245245+ exit_free:246246+ platram_remove(dev);247247+ exit_error:248248+ return err;249249+}250250+251251+/* device driver info */252252+253253+static struct device_driver platram_driver = {254254+ .name = "mtd-ram",255255+ .bus = &platform_bus_type,256256+ .probe = platram_probe,257257+ .remove = platram_remove,258258+};259259+260260+/* module init/exit */261261+262262+static int __init platram_init(void)263263+{264264+ printk("Generic platform RAM MTD, (c) 2004 Simtec Electronics\n");265265+ return driver_register(&platram_driver);266266+}267267+268268+static void __exit platram_exit(void)269269+{270270+ driver_unregister(&platram_driver);271271+}272272+273273+module_init(platram_init);274274+module_exit(platram_exit);275275+276276+MODULE_LICENSE("GPL");277277+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");278278+MODULE_DESCRIPTION("MTD platform RAM map driver");
+2-2
drivers/mtd/maps/scb2_flash.c
···11/*22 * MTD map driver for BIOS Flash on Intel SCB2 boards33- * $Id: scb2_flash.c,v 1.11 2004/11/28 09:40:40 dwmw2 Exp $33+ * $Id: scb2_flash.c,v 1.12 2005/03/18 14:04:35 gleixner Exp $44 * Copyright (C) 2002 Sun Microsystems, Inc.55 * Tim Hockin <thockin@sun.com>66 *···238238static int __init239239scb2_flash_init(void)240240{241241- return pci_module_init(&scb2_flash_driver);241241+ return pci_register_driver(&scb2_flash_driver);242242}243243244244static void __exit
+26-7
drivers/mtd/maps/sharpsl-flash.c
···44 * Copyright (C) 2001 Lineo Japan, Inc.55 * Copyright (C) 2002 SHARP66 *77- * $Id: sharpsl-flash.c,v 1.2 2004/11/24 20:38:06 rpurdie Exp $77+ * $Id: sharpsl-flash.c,v 1.5 2005/03/21 08:42:11 rpurdie Exp $88 *99 * based on rpxlite.c,v 1.15 2001/10/02 15:05:14 dwmw2 Exp1010 * Handle mapping of the flash on the RPX Lite and CLLF boards···2424#include <linux/module.h>2525#include <linux/types.h>2626#include <linux/kernel.h>2727-#include <asm/io.h>2827#include <linux/mtd/mtd.h>2928#include <linux/mtd/map.h>3029#include <linux/mtd/partitions.h>3030+#include <asm/io.h>3131+#include <asm/mach-types.h>31323233#define WINDOW_ADDR 0x000000003333-#define WINDOW_SIZE 0x010000003434+#define WINDOW_SIZE 0x008000003435#define BANK_WIDTH 235363637static struct mtd_info *mymtd;···45444645static struct mtd_partition sharpsl_partitions[1] = {4746 {4848- name: "Filesystem",4949- size: 0x006d0000,5050- offset: 0x001200004747+ name: "Boot PROM Filesystem",5148 }5249};5350···5758 int nb_parts = 0;5859 char *part_type = "static";59606060- printk(KERN_NOTICE "Sharp SL series flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);6161+ printk(KERN_NOTICE "Sharp SL series flash device: %x at %x\n", 6262+ WINDOW_SIZE, WINDOW_ADDR);6163 sharpsl_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);6264 if (!sharpsl_map.virt) {6365 printk("Failed to ioremap\n");6466 return -EIO;6567 }6868+6969+ simple_map_init(&sharpsl_map);7070+6671 mymtd = do_map_probe("map_rom", &sharpsl_map);6772 if (!mymtd) {6873 iounmap(sharpsl_map.virt);···75727673 mymtd->owner = THIS_MODULE;77747575+ if (machine_is_corgi() || machine_is_shepherd() || machine_is_husky() 7676+ || machine_is_poodle()) {7777+ sharpsl_partitions[0].size=0x006d0000;7878+ sharpsl_partitions[0].offset=0x00120000;7979+ } else if (machine_is_tosa()) {8080+ sharpsl_partitions[0].size=0x006a0000;8181+ sharpsl_partitions[0].offset=0x00160000;8282+ } else if (machine_is_spitz()) {8383+ sharpsl_partitions[0].size=0x006b0000;8484+ sharpsl_partitions[0].offset=0x00140000;8585+ } else {8686+ map_destroy(mymtd);8787+ iounmap(sharpsl_map.virt); 8888+ return -ENODEV;8989+ }9090+7891 parts = sharpsl_partitions;7992 nb_parts = NB_OF(sharpsl_partitions);8093
+143-33
drivers/mtd/mtdchar.c
···11/*22- * $Id: mtdchar.c,v 1.66 2005/01/05 18:05:11 dwmw2 Exp $22+ * $Id: mtdchar.c,v 1.73 2005/07/04 17:36:41 gleixner Exp $33 *44 * Character-device access to raw MTD devices.55 *···1515#include <linux/fs.h>1616#include <asm/uaccess.h>17171818-#ifdef CONFIG_DEVFS_FS1919-#include <linux/devfs_fs_kernel.h>1818+#include <linux/device.h>1919+2020+static struct class *mtd_class;20212122static void mtd_notify_add(struct mtd_info* mtd)2223{2324 if (!mtd)2425 return;25262626- devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2),2727- S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index);2828-2929- devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),3030- S_IFCHR | S_IRUGO, "mtd/%dro", mtd->index);2727+ class_device_create(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),2828+ NULL, "mtd%d", mtd->index);2929+3030+ class_device_create(mtd_class, 3131+ MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),3232+ NULL, "mtd%dro", mtd->index);3133}32343335static void mtd_notify_remove(struct mtd_info* mtd)3436{3537 if (!mtd)3638 return;3737- devfs_remove("mtd/%d", mtd->index);3838- devfs_remove("mtd/%dro", mtd->index);3939+4040+ class_device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2));4141+ class_device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1));3942}40434144static struct mtd_notifier notifier = {···4643 .remove = mtd_notify_remove,4744};48454949-static inline void mtdchar_devfs_init(void)5050-{5151- devfs_mk_dir("mtd");5252- register_mtd_user(¬ifier);5353-}4646+/*4747+ * We use file->private_data to store a pointer to the MTDdevice.4848+ * Since alighment is at least 32 bits, we have 2 bits free for OTP4949+ * modes as well.5050+ */54515555-static inline void mtdchar_devfs_exit(void)5656-{5757- unregister_mtd_user(¬ifier);5858- devfs_remove("mtd");5959-}6060-#else /* !DEVFS */6161-#define mtdchar_devfs_init() do { } while(0)6262-#define mtdchar_devfs_exit() do { } while(0)6363-#endif5252+#define TO_MTD(file) (struct mtd_info *)((long)((file)->private_data) & ~3L)5353+5454+#define MTD_MODE_OTP_FACT 15555+#define MTD_MODE_OTP_USER 25656+#define MTD_MODE(file) ((long)((file)->private_data) & 3)5757+5858+#define SET_MTD_MODE(file, mode) \5959+ do { long __p = (long)((file)->private_data); \6060+ (file)->private_data = (void *)((__p & ~3L) | mode); } while (0)64616562static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)6663{6767- struct mtd_info *mtd = file->private_data;6464+ struct mtd_info *mtd = TO_MTD(file);68656966 switch (orig) {7067 case 0:···137134138135 DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");139136140140- mtd = file->private_data;137137+ mtd = TO_MTD(file);141138142139 if (mtd->sync)143140 mtd->sync(mtd);···154151155152static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)156153{157157- struct mtd_info *mtd = file->private_data;154154+ struct mtd_info *mtd = TO_MTD(file);158155 size_t retlen=0;159156 size_t total_retlen=0;160157 int ret=0;···181178 if (!kbuf)182179 return -ENOMEM;183180184184- ret = MTD_READ(mtd, *ppos, len, &retlen, kbuf);181181+ switch (MTD_MODE(file)) {182182+ case MTD_MODE_OTP_FACT:183183+ ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf);184184+ break;185185+ case MTD_MODE_OTP_USER:186186+ ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);187187+ break;188188+ default:189189+ ret = MTD_READ(mtd, *ppos, len, &retlen, kbuf);190190+ }185191 /* Nand returns -EBADMSG on ecc errors, but it returns186192 * the data. For our userspace tools it is important187193 * to dump areas with ecc errors ! ···208196209197 count -= retlen;210198 buf += retlen;199199+ if (retlen == 0)200200+ count = 0;211201 }212202 else {213203 kfree(kbuf);···224210225211static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos)226212{227227- struct mtd_info *mtd = file->private_data;213213+ struct mtd_info *mtd = TO_MTD(file);228214 char *kbuf;229215 size_t retlen;230216 size_t total_retlen=0;···259245 return -EFAULT;260246 }261247262262- ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf);248248+ switch (MTD_MODE(file)) {249249+ case MTD_MODE_OTP_FACT:250250+ ret = -EROFS;251251+ break;252252+ case MTD_MODE_OTP_USER:253253+ if (!mtd->write_user_prot_reg) {254254+ ret = -EOPNOTSUPP;255255+ break;256256+ }257257+ ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);258258+ break;259259+ default:260260+ ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf);261261+ }263262 if (!ret) {264263 *ppos += retlen;265264 total_retlen += retlen;···303276static int mtd_ioctl(struct inode *inode, struct file *file,304277 u_int cmd, u_long arg)305278{306306- struct mtd_info *mtd = file->private_data;279279+ struct mtd_info *mtd = TO_MTD(file);307280 void __user *argp = (void __user *)arg;308281 int ret = 0;309282 u_long size;···545518 break;546519 }547520521521+#ifdef CONFIG_MTD_OTP522522+ case OTPSELECT:523523+ {524524+ int mode;525525+ if (copy_from_user(&mode, argp, sizeof(int)))526526+ return -EFAULT;527527+ SET_MTD_MODE(file, 0);528528+ switch (mode) {529529+ case MTD_OTP_FACTORY:530530+ if (!mtd->read_fact_prot_reg)531531+ ret = -EOPNOTSUPP;532532+ else533533+ SET_MTD_MODE(file, MTD_MODE_OTP_FACT);534534+ break;535535+ case MTD_OTP_USER:536536+ if (!mtd->read_fact_prot_reg)537537+ ret = -EOPNOTSUPP;538538+ else539539+ SET_MTD_MODE(file, MTD_MODE_OTP_USER);540540+ break;541541+ default:542542+ ret = -EINVAL;543543+ case MTD_OTP_OFF:544544+ break;545545+ }546546+ file->f_pos = 0;547547+ break;548548+ }549549+550550+ case OTPGETREGIONCOUNT:551551+ case OTPGETREGIONINFO:552552+ {553553+ struct otp_info *buf = kmalloc(4096, GFP_KERNEL);554554+ if (!buf)555555+ return -ENOMEM;556556+ ret = -EOPNOTSUPP;557557+ switch (MTD_MODE(file)) {558558+ case MTD_MODE_OTP_FACT:559559+ if (mtd->get_fact_prot_info)560560+ ret = mtd->get_fact_prot_info(mtd, buf, 4096);561561+ break;562562+ case MTD_MODE_OTP_USER:563563+ if (mtd->get_user_prot_info)564564+ ret = mtd->get_user_prot_info(mtd, buf, 4096);565565+ break;566566+ }567567+ if (ret >= 0) {568568+ if (cmd == OTPGETREGIONCOUNT) {569569+ int nbr = ret / sizeof(struct otp_info);570570+ ret = copy_to_user(argp, &nbr, sizeof(int));571571+ } else572572+ ret = copy_to_user(argp, buf, ret);573573+ if (ret)574574+ ret = -EFAULT;575575+ }576576+ kfree(buf);577577+ break;578578+ }579579+580580+ case OTPLOCK:581581+ {582582+ struct otp_info info;583583+584584+ if (MTD_MODE(file) != MTD_MODE_OTP_USER)585585+ return -EINVAL;586586+ if (copy_from_user(&info, argp, sizeof(info)))587587+ return -EFAULT;588588+ if (!mtd->lock_user_prot_reg)589589+ return -EOPNOTSUPP;590590+ ret = mtd->lock_user_prot_reg(mtd, info.start, info.length);591591+ break;592592+ }593593+#endif594594+548595 default:549596 ret = -ENOTTY;550597 }···644543 return -EAGAIN;645544 }646545647647- mtdchar_devfs_init();546546+ mtd_class = class_create(THIS_MODULE, "mtd");547547+548548+ if (IS_ERR(mtd_class)) {549549+ printk(KERN_ERR "Error creating mtd class.\n");550550+ unregister_chrdev(MTD_CHAR_MAJOR, "mtd");551551+ return PTR_ERR(mtd_class);552552+ }553553+554554+ register_mtd_user(¬ifier);648555 return 0;649556}650557651558static void __exit cleanup_mtdchar(void)652559{653653- mtdchar_devfs_exit();560560+ unregister_mtd_user(¬ifier);561561+ class_destroy(mtd_class);654562 unregister_chrdev(MTD_CHAR_MAJOR, "mtd");655563}656564
+3-3
drivers/mtd/mtdcore.c
···11/*22- * $Id: mtdcore.c,v 1.44 2004/11/16 18:28:59 dwmw2 Exp $22+ * $Id: mtdcore.c,v 1.45 2005/02/18 14:34:50 dedekind Exp $33 *44 * Core registration and callback routines for MTD55 * drivers and users.···149149}150150151151/**152152- * register_mtd_user - unregister a 'user' of MTD devices.153153- * @new: pointer to notifier info structure152152+ * unregister_mtd_user - unregister a 'user' of MTD devices.153153+ * @old: pointer to notifier info structure154154 *155155 * Removes a callback function pair from the list of 'users' to be156156 * notified upon addition or removal of MTD devices. Causes the
···11# drivers/mtd/nand/Kconfig22-# $Id: Kconfig,v 1.26 2005/01/05 12:42:24 dwmw2 Exp $22+# $Id: Kconfig,v 1.31 2005/06/20 12:03:21 bjd Exp $3344menu "NAND Flash Device Drivers"55 depends on MTD!=n···5858config MTD_NAND_IDS5959 tristate60606161-config MTD_NAND_TX4925NDFMC6262- tristate "SmartMedia Card on Toshiba RBTX4925 reference board"6363- depends on TOSHIBA_RBTX4925 && MTD_NAND && TOSHIBA_RBTX4925_MPLEX_NAND6464- help6565- This enables the driver for the NAND flash device found on the6666- Toshiba RBTX4925 reference board, which is a SmartMediaCard.6767-6868-config MTD_NAND_TX4938NDFMC6969- tristate "NAND Flash device on Toshiba RBTX4938 reference board"7070- depends on TOSHIBA_RBTX4938 && MTD_NAND && TOSHIBA_RBTX4938_MPLEX_NAND 7171- help7272- This enables the driver for the NAND flash device found on the7373- Toshiba RBTX4938 reference board.7474-7561config MTD_NAND_AU15507662 tristate "Au1550 NAND support"7763 depends on SOC_AU1550 && MTD_NAND···8195 This enables the NAND flash driver on the PPChameleon EVB Board.82968397config MTD_NAND_S3C24108484- tristate "NAND Flash support for S3C2410 SoC"9898+ tristate "NAND Flash support for S3C2410/S3C2440 SoC"8599 depends on ARCH_S3C2410 && MTD_NAND86100 help8787- This enables the NAND flash controller on the S3C2410.101101+ This enables the NAND flash controller on the S3C2410 and S3C2440102102+ SoCs8810389104 No board specfic support is done by this driver, each board90105 must advertise a platform_device for the driver to attach.
···1616 * 1717 * Interface to generic NAND code for M-Systems DiskOnChip devices1818 *1919- * $Id: diskonchip.c,v 1.45 2005/01/05 18:05:14 dwmw2 Exp $1919+ * $Id: diskonchip.c,v 1.54 2005/04/07 14:22:55 dbrown Exp $2020 */21212222#include <linux/kernel.h>···3535#include <linux/mtd/inftl.h>36363737/* Where to look for the devices? */3838-#ifndef CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS3939-#define CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 03838+#ifndef CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS3939+#define CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS 04040#endif41414242static unsigned long __initdata doc_locations[] = {4343#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)4444-#ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH4444+#ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH4545 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, 4646 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,4747 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, ···8181 struct mtd_info *nextdoc;8282};83838484-/* Max number of eraseblocks to scan (from start of device) for the (I)NFTL8585- MediaHeader. The spec says to just keep going, I think, but that's just8686- silly. */8787-#define MAX_MEDIAHEADER_SCAN 88888-8984/* This is the syndrome computed by the HW ecc generator upon reading an empty9085 page, one with all 0xff for data and stored ecc code. */9186static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a };···106111static int no_ecc_failures=0;107112module_param(no_ecc_failures, int, 0);108113109109-#ifdef CONFIG_MTD_PARTITIONS110114static int no_autopart=0;111115module_param(no_autopart, int, 0);112112-#endif116116+117117+static int show_firmware_partition=0;118118+module_param(show_firmware_partition, int, 0);113119114120#ifdef MTD_NAND_DISKONCHIP_BBTWRITE115121static int inftl_bbt_write=1;···119123#endif120124module_param(inftl_bbt_write, int, 0);121125122122-static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS;126126+static unsigned long doc_config_location = CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS;123127module_param(doc_config_location, ulong, 0);124128MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");125129···406410 doc200x_hwcontrol(mtd, NAND_CTL_SETALE);407411 this->write_byte(mtd, 0);408412 doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);409409-413413+414414+ /* We cant' use dev_ready here, but at least we wait for the415415+ * command to complete 416416+ */417417+ udelay(50);418418+410419 ret = this->read_byte(mtd) << 8;411420 ret |= this->read_byte(mtd);412421···429428 doc200x_hwcontrol(mtd, NAND_CTL_SETALE);430429 doc2000_write_byte(mtd, 0);431430 doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);431431+432432+ udelay(50);432433433434 ident.dword = readl(docptr + DoC_2k_CDSN_IO);434435 if (((ident.byte[0] << 8) | ident.byte[1]) == ret) {···1049104610501047//u_char mydatabuf[528];1051104810491049+/* The strange out-of-order .oobfree list below is a (possibly unneeded)10501050+ * attempt to retain compatibility. It used to read:10511051+ * .oobfree = { {8, 8} }10521052+ * Since that leaves two bytes unusable, it was changed. But the following10531053+ * scheme might affect existing jffs2 installs by moving the cleanmarker:10541054+ * .oobfree = { {6, 10} }10551055+ * jffs2 seems to handle the above gracefully, but the current scheme seems10561056+ * safer. The only problem with it is that any code that parses oobfree must10571057+ * be able to handle out-of-order segments.10581058+ */10521059static struct nand_oobinfo doc200x_oobinfo = {10531060 .useecc = MTD_NANDECC_AUTOPLACE,10541061 .eccbytes = 6,10551062 .eccpos = {0, 1, 2, 3, 4, 5},10561056- .oobfree = { {8, 8} }10631063+ .oobfree = { {8, 8}, {6, 2} }10571064};1058106510591066/* Find the (I)NFTL Media Header, and optionally also the mirror media header.···10771064{10781065 struct nand_chip *this = mtd->priv;10791066 struct doc_priv *doc = this->priv;10801080- unsigned offs, end = (MAX_MEDIAHEADER_SCAN << this->phys_erase_shift);10671067+ unsigned offs;10811068 int ret;10821069 size_t retlen;1083107010841084- end = min(end, mtd->size); // paranoia10851085- for (offs = 0; offs < end; offs += mtd->erasesize) {10711071+ for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {10861072 ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);10871073 if (retlen != mtd->oobblock) continue;10881074 if (ret) {···11231111 u_char *buf;11241112 struct NFTLMediaHeader *mh;11251113 const unsigned psize = 1 << this->page_shift;11141114+ int numparts = 0;11261115 unsigned blocks, maxblocks;11271116 int offs, numheaders;11281117···11351122 if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out;11361123 mh = (struct NFTLMediaHeader *) buf;1137112411381138-//#ifdef CONFIG_MTD_DEBUG_VERBOSE11391139-// if (CONFIG_MTD_DEBUG_VERBOSE >= 2)11251125+ mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits);11261126+ mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN);11271127+ mh->FormattedSize = le32_to_cpu(mh->FormattedSize);11281128+11401129 printk(KERN_INFO " DataOrgID = %s\n"11411130 " NumEraseUnits = %d\n"11421131 " FirstPhysicalEUN = %d\n"···11471132 mh->DataOrgID, mh->NumEraseUnits,11481133 mh->FirstPhysicalEUN, mh->FormattedSize,11491134 mh->UnitSizeFactor);11501150-//#endif1151113511521136 blocks = mtd->size >> this->phys_erase_shift;11531137 maxblocks = min(32768U, mtd->erasesize - psize);···11891175 offs <<= this->page_shift;11901176 offs += mtd->erasesize;1191117711921192- //parts[0].name = " DiskOnChip Boot / Media Header partition";11931193- //parts[0].offset = 0;11941194- //parts[0].size = offs;11951195-11961196- parts[0].name = " DiskOnChip BDTL partition";11971197- parts[0].offset = offs;11981198- parts[0].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift;11991199-12001200- offs += parts[0].size;12011201- if (offs < mtd->size) {12021202- parts[1].name = " DiskOnChip Remainder partition";12031203- parts[1].offset = offs;12041204- parts[1].size = mtd->size - offs;12051205- ret = 2;12061206- goto out;11781178+ if (show_firmware_partition == 1) {11791179+ parts[0].name = " DiskOnChip Firmware / Media Header partition";11801180+ parts[0].offset = 0;11811181+ parts[0].size = offs;11821182+ numparts = 1;12071183 }12081208- ret = 1;11841184+11851185+ parts[numparts].name = " DiskOnChip BDTL partition";11861186+ parts[numparts].offset = offs;11871187+ parts[numparts].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift;11881188+11891189+ offs += parts[numparts].size;11901190+ numparts++;11911191+11921192+ if (offs < mtd->size) {11931193+ parts[numparts].name = " DiskOnChip Remainder partition";11941194+ parts[numparts].offset = offs;11951195+ parts[numparts].size = mtd->size - offs;11961196+ numparts++;11971197+ }11981198+11991199+ ret = numparts;12091200out:12101201 kfree(buf);12111202 return ret;···12521233 mh->FormatFlags = le32_to_cpu(mh->FormatFlags);12531234 mh->PercentUsed = le32_to_cpu(mh->PercentUsed);1254123512551255-//#ifdef CONFIG_MTD_DEBUG_VERBOSE12561256-// if (CONFIG_MTD_DEBUG_VERBOSE >= 2)12571236 printk(KERN_INFO " bootRecordID = %s\n"12581237 " NoOfBootImageBlocks = %d\n"12591238 " NoOfBinaryPartitions = %d\n"···12691252 ((unsigned char *) &mh->OsakVersion)[2] & 0xf,12701253 ((unsigned char *) &mh->OsakVersion)[3] & 0xf,12711254 mh->PercentUsed);12721272-//#endif1273125512741256 vshift = this->phys_erase_shift + mh->BlockMultiplierBits;12751257···12941278 ip->spareUnits = le32_to_cpu(ip->spareUnits);12951279 ip->Reserved0 = le32_to_cpu(ip->Reserved0);1296128012971297-//#ifdef CONFIG_MTD_DEBUG_VERBOSE12981298-// if (CONFIG_MTD_DEBUG_VERBOSE >= 2)12991281 printk(KERN_INFO " PARTITION[%d] ->\n"13001282 " virtualUnits = %d\n"13011283 " firstUnit = %d\n"···13031289 i, ip->virtualUnits, ip->firstUnit,13041290 ip->lastUnit, ip->flags,13051291 ip->spareUnits);13061306-//#endif1307129213081308-/*13091309- if ((i == 0) && (ip->firstUnit > 0)) {12931293+ if ((show_firmware_partition == 1) &&12941294+ (i == 0) && (ip->firstUnit > 0)) {13101295 parts[0].name = " DiskOnChip IPL / Media Header partition";13111296 parts[0].offset = 0;13121297 parts[0].size = mtd->erasesize * ip->firstUnit;13131298 numparts = 1;13141299 }13151315-*/1316130013171301 if (ip->flags & INFTL_BINARY)13181302 parts[numparts].name = " DiskOnChip BDK partition";
+215-84
drivers/mtd/nand/nand_base.c
···2828 * among multiple independend devices. Suggestions and initial patch2929 * from Ben Dooks <ben-mtd@fluff.org>3030 *3131+ * 12-05-2004 dmarlin: add workaround for Renesas AG-AND chips "disturb" issue.3232+ * Basically, any block not rewritten may lose data when surrounding blocks3333+ * are rewritten many times. JFFS2 ensures this doesn't happen for blocks 3434+ * it uses, but the Bad Block Table(s) may not be rewritten. To ensure they3535+ * do not lose data, force them to be rewritten when some of the surrounding3636+ * blocks are erased. Rather than tracking a specific nearby block (which 3737+ * could itself go bad), use a page address 'mask' to select several blocks 3838+ * in the same area, and rewrite the BBT when any of them are erased.3939+ *4040+ * 01-03-2005 dmarlin: added support for the device recovery command sequence for Renesas 4141+ * AG-AND chips. If there was a sudden loss of power during an erase operation,4242+ * a "device recovery" operation must be performed when power is restored4343+ * to ensure correct operation.4444+ *4545+ * 01-20-2005 dmarlin: added support for optional hardware specific callback routine to 4646+ * perform extra error status checks on erase and write failures. This required4747+ * adding a wrapper function for nand_read_ecc.4848+ *3149 * Credits:3250 * David Woodhouse for adding multichip support 3351 * ···5941 * The AG-AND chips have nice features for speed improvement,6042 * which are not supported yet. Read / program 4 pages in one go.6143 *6262- * $Id: nand_base.c,v 1.126 2004/12/13 11:22:25 lavinen Exp $4444+ * $Id: nand_base.c,v 1.146 2005/06/17 15:02:06 gleixner Exp $6345 *6446 * This program is free software; you can redistribute it and/or modify6547 * it under the terms of the GNU General Public License version 2 as···167149168150 /* De-select the NAND device */169151 this->select_chip(mtd, -1);170170- /* Do we have a hardware controller ? */152152+171153 if (this->controller) {154154+ /* Release the controller and the chip */172155 spin_lock(&this->controller->lock);173156 this->controller->active = NULL;157157+ this->state = FL_READY;158158+ wake_up(&this->controller->wq);174159 spin_unlock(&this->controller->lock);160160+ } else {161161+ /* Release the chip */162162+ spin_lock(&this->chip_lock);163163+ this->state = FL_READY;164164+ wake_up(&this->wq);165165+ spin_unlock(&this->chip_lock);175166 }176176- /* Release the chip */177177- spin_lock (&this->chip_lock);178178- this->state = FL_READY;179179- wake_up (&this->wq);180180- spin_unlock (&this->chip_lock);181167}182168183169/**···465443466444 /* Get block number */467445 block = ((int) ofs) >> this->bbt_erase_shift;468468- this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);446446+ if (this->bbt)447447+ this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);469448470449 /* Do we have a flash based bad block table ? */471450 if (this->options & NAND_USE_FLASH_BBT)···489466 struct nand_chip *this = mtd->priv;490467 /* Check the WP bit */491468 this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);492492- return (this->read_byte(mtd) & 0x80) ? 0 : 1; 469469+ return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; 493470}494471495472/**···511488512489 /* Return info from the table */513490 return nand_isbad_bbt (mtd, ofs, allowbbt);491491+}492492+493493+/* 494494+ * Wait for the ready pin, after a command495495+ * The timeout is catched later.496496+ */497497+static void nand_wait_ready(struct mtd_info *mtd)498498+{499499+ struct nand_chip *this = mtd->priv;500500+ unsigned long timeo = jiffies + 2;501501+502502+ /* wait until command is processed or timeout occures */503503+ do {504504+ if (this->dev_ready(mtd))505505+ return;506506+ } while (time_before(jiffies, timeo)); 514507}515508516509/**···610571 this->hwcontrol(mtd, NAND_CTL_SETCLE);611572 this->write_byte(mtd, NAND_CMD_STATUS);612573 this->hwcontrol(mtd, NAND_CTL_CLRCLE);613613- while ( !(this->read_byte(mtd) & 0x40));574574+ while ( !(this->read_byte(mtd) & NAND_STATUS_READY));614575 return;615576616577 /* This applies to read commands */ ···624585 return;625586 } 626587 }627627-628588 /* Apply this short delay always to ensure that we do wait tWB in629589 * any case on any machine. */630590 ndelay (100);631631- /* wait until command is processed */632632- while (!this->dev_ready(mtd));591591+592592+ nand_wait_ready(mtd);633593}634594635595/**···657619 /* Begin command latch cycle */658620 this->hwcontrol(mtd, NAND_CTL_SETCLE);659621 /* Write out the command to the device. */660660- this->write_byte(mtd, command);622622+ this->write_byte(mtd, (command & 0xff));661623 /* End command latch cycle */662624 this->hwcontrol(mtd, NAND_CTL_CLRCLE);663625···685647686648 /* 687649 * program and erase have their own busy handlers 688688- * status and sequential in needs no delay689689- */650650+ * status, sequential in, and deplete1 need no delay651651+ */690652 switch (command) {691653692654 case NAND_CMD_CACHEDPROG:···695657 case NAND_CMD_ERASE2:696658 case NAND_CMD_SEQIN:697659 case NAND_CMD_STATUS:660660+ case NAND_CMD_DEPLETE1:698661 return;699662663663+ /* 664664+ * read error status commands require only a short delay665665+ */666666+ case NAND_CMD_STATUS_ERROR:667667+ case NAND_CMD_STATUS_ERROR0:668668+ case NAND_CMD_STATUS_ERROR1:669669+ case NAND_CMD_STATUS_ERROR2:670670+ case NAND_CMD_STATUS_ERROR3:671671+ udelay(this->chip_delay);672672+ return;700673701674 case NAND_CMD_RESET:702675 if (this->dev_ready) ···716667 this->hwcontrol(mtd, NAND_CTL_SETCLE);717668 this->write_byte(mtd, NAND_CMD_STATUS);718669 this->hwcontrol(mtd, NAND_CTL_CLRCLE);719719- while ( !(this->read_byte(mtd) & 0x40));670670+ while ( !(this->read_byte(mtd) & NAND_STATUS_READY));720671 return;721672722673 case NAND_CMD_READ0:···739690 return;740691 } 741692 }742742-693693+743694 /* Apply this short delay always to ensure that we do wait tWB in744695 * any case on any machine. */745696 ndelay (100);746746- /* wait until command is processed */747747- while (!this->dev_ready(mtd));697697+698698+ nand_wait_ready(mtd);748699}749700750701/**···757708 */758709static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state)759710{760760- struct nand_chip *active = this;761761-711711+ struct nand_chip *active;712712+ spinlock_t *lock;713713+ wait_queue_head_t *wq;762714 DECLARE_WAITQUEUE (wait, current);763715764764- /* 765765- * Grab the lock and see if the device is available 766766- */716716+ lock = (this->controller) ? &this->controller->lock : &this->chip_lock;717717+ wq = (this->controller) ? &this->controller->wq : &this->wq;767718retry:719719+ active = this;720720+ spin_lock(lock);721721+768722 /* Hardware controller shared among independend devices */769723 if (this->controller) {770770- spin_lock (&this->controller->lock);771724 if (this->controller->active)772725 active = this->controller->active;773726 else774727 this->controller->active = this;775775- spin_unlock (&this->controller->lock);776728 }777777-778778- if (active == this) {779779- spin_lock (&this->chip_lock);780780- if (this->state == FL_READY) {781781- this->state = new_state;782782- spin_unlock (&this->chip_lock);783783- return;784784- }785785- } 786786- set_current_state (TASK_UNINTERRUPTIBLE);787787- add_wait_queue (&active->wq, &wait);788788- spin_unlock (&active->chip_lock);789789- schedule ();790790- remove_wait_queue (&active->wq, &wait);729729+ if (active == this && this->state == FL_READY) {730730+ this->state = new_state;731731+ spin_unlock(lock);732732+ return;733733+ }734734+ set_current_state(TASK_UNINTERRUPTIBLE);735735+ add_wait_queue(wq, &wait);736736+ spin_unlock(lock);737737+ schedule();738738+ remove_wait_queue(wq, &wait);791739 goto retry;792740}793741···831785 if (this->read_byte(mtd) & NAND_STATUS_READY)832786 break;833787 }834834- yield ();788788+ cond_resched();835789 }836790 status = (int) this->read_byte(mtd);837791 return status;···917871 if (!cached) {918872 /* call wait ready function */919873 status = this->waitfunc (mtd, this, FL_WRITING);874874+875875+ /* See if operation failed and additional status checks are available */876876+ if ((status & NAND_STATUS_FAIL) && (this->errstat)) {877877+ status = this->errstat(mtd, this, FL_WRITING, status, page);878878+ }879879+920880 /* See if device thinks it succeeded */921921- if (status & 0x01) {881881+ if (status & NAND_STATUS_FAIL) {922882 DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);923883 return -EIO;924884 }···1027975 if (!this->dev_ready) 1028976 udelay (this->chip_delay);1029977 else10301030- while (!this->dev_ready(mtd)); 978978+ nand_wait_ready(mtd);10319791032980 /* All done, return happy */1033981 if (!numpages)···1049997#endif10509981051999/**10521052- * nand_read - [MTD Interface] MTD compability function for nand_read_ecc10001000+ * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc10531001 * @mtd: MTD device structure10541002 * @from: offset to read from10551003 * @len: number of bytes to read10561004 * @retlen: pointer to variable to store the number of read bytes10571005 * @buf: the databuffer to put data10581006 *10591059- * This function simply calls nand_read_ecc with oob buffer and oobsel = NULL10601060-*/10071007+ * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL10081008+ * and flags = 0xff10091009+ */10611010static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)10621011{10631063- return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL);10641064-} 10121012+ return nand_do_read_ecc (mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff);10131013+}106510141066101510671016/**10681068- * nand_read_ecc - [MTD Interface] Read data with ECC10171017+ * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc10691018 * @mtd: MTD device structure10701019 * @from: offset to read from10711020 * @len: number of bytes to read···10751022 * @oob_buf: filesystem supplied oob data buffer10761023 * @oobsel: oob selection structure10771024 *10781078- * NAND read with ECC10251025+ * This function simply calls nand_do_read_ecc with flags = 0xff10791026 */10801027static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,10811028 size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel)10821029{10301030+ /* use userspace supplied oobinfo, if zero */10311031+ if (oobsel == NULL)10321032+ oobsel = &mtd->oobinfo;10331033+ return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff);10341034+}10351035+10361036+10371037+/**10381038+ * nand_do_read_ecc - [MTD Interface] Read data with ECC10391039+ * @mtd: MTD device structure10401040+ * @from: offset to read from10411041+ * @len: number of bytes to read10421042+ * @retlen: pointer to variable to store the number of read bytes10431043+ * @buf: the databuffer to put data10441044+ * @oob_buf: filesystem supplied oob data buffer (can be NULL)10451045+ * @oobsel: oob selection structure10461046+ * @flags: flag to indicate if nand_get_device/nand_release_device should be preformed10471047+ * and how many corrected error bits are acceptable:10481048+ * bits 0..7 - number of tolerable errors10491049+ * bit 8 - 0 == do not get/release chip, 1 == get/release chip10501050+ *10511051+ * NAND read with ECC10521052+ */10531053+int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,10541054+ size_t * retlen, u_char * buf, u_char * oob_buf, 10551055+ struct nand_oobinfo *oobsel, int flags)10561056+{10571057+10831058 int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;10841059 int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;10851060 struct nand_chip *this = mtd->priv;···11321051 }1133105211341053 /* Grab the lock and see if the device is available */11351135- nand_get_device (this, mtd ,FL_READING);10541054+ if (flags & NAND_GET_DEVICE)10551055+ nand_get_device (this, mtd, FL_READING);1136105611371137- /* use userspace supplied oobinfo, if zero */11381138- if (oobsel == NULL)11391139- oobsel = &mtd->oobinfo;11401140-11411057 /* Autoplace of oob data ? Use the default placement scheme */11421058 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)11431059 oobsel = this->autooob;···11961118 } 1197111911981120 /* get oob area, if we have no oob buffer from fs-driver */11991199- if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE)11211121+ if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE ||11221122+ oobsel->useecc == MTD_NANDECC_AUTOPL_USR)12001123 oob_data = &this->data_buf[end];1201112412021125 eccsteps = this->eccsteps;···12341155 /* We calc error correction directly, it checks the hw12351156 * generator for an error, reads back the syndrome and12361157 * does the error correction on the fly */12371237- if (this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]) == -1) {11581158+ ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);11591159+ if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {12381160 DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " 12391161 "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);12401162 ecc_failed++;···12741194 p[i] = ecc_status;12751195 }1276119612771277- if (ecc_status == -1) { 11971197+ if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { 12781198 DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);12791199 ecc_failed++;12801200 }···12861206 /* without autoplace. Legacy mode used by YAFFS1 */12871207 switch(oobsel->useecc) {12881208 case MTD_NANDECC_AUTOPLACE:12091209+ case MTD_NANDECC_AUTOPL_USR:12891210 /* Walk through the autoplace chunks */12901290- for (i = 0, j = 0; j < mtd->oobavail; i++) {12111211+ for (i = 0; oobsel->oobfree[i][1]; i++) {12911212 int from = oobsel->oobfree[i][0];12921213 int num = oobsel->oobfree[i][1];12931214 memcpy(&oob_buf[oob], &oob_data[from], num);12941294- j+= num;12151215+ oob += num;12951216 }12961296- oob += mtd->oobavail;12971217 break;12981218 case MTD_NANDECC_PLACE:12991219 /* YAFFS1 legacy mode */···13191239 if (!this->dev_ready) 13201240 udelay (this->chip_delay);13211241 else13221322- while (!this->dev_ready(mtd)); 12421242+ nand_wait_ready(mtd);1323124313241244 if (read == len)13251245 break; ···13441264 }1345126513461266 /* Deselect and wake up anyone waiting on the device */13471347- nand_release_device(mtd);12671267+ if (flags & NAND_GET_DEVICE)12681268+ nand_release_device(mtd);1348126913491270 /*13501271 * Return success, if no ECC failures, else -EBADMSG···14181337 if (!this->dev_ready) 14191338 udelay (this->chip_delay);14201339 else14211421- while (!this->dev_ready(mtd)); 13401340+ nand_wait_ready(mtd);1422134114231342 /* Read more ? */14241343 if (i < len) {···14981417 if (!this->dev_ready) 14991418 udelay (this->chip_delay);15001419 else15011501- while (!this->dev_ready(mtd)); 14201420+ nand_wait_ready(mtd);1502142115031422 /* Check, if the chip supports auto page increment */ 15041423 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))···16481567 oobsel = this->autooob;16491568 autoplace = 1;16501569 } 15701570+ if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)15711571+ autoplace = 1;1651157216521573 /* Setup variables and oob buffer */16531574 totalpages = len >> this->page_shift;···18161733 status = this->waitfunc (mtd, this, FL_WRITING);1817173418181735 /* See if device thinks it succeeded */18191819- if (status & 0x01) {17361736+ if (status & NAND_STATUS_FAIL) {18201737 DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);18211738 ret = -EIO;18221739 goto out;···19241841 oobsel = this->autooob;19251842 autoplace = 1;19261843 } 18441844+ if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)18451845+ autoplace = 1;1927184619281847 /* Setup start page */19291848 page = (int) (to >> this->page_shift);···20721987 return nand_erase_nand (mtd, instr, 0);20731988}2074198919901990+#define BBT_PAGE_MASK 0xffffff3f20751991/**20761992 * nand_erase_intern - [NAND Interface] erase block(s)20771993 * @mtd: MTD device structure···20851999{20862000 int page, len, status, pages_per_block, ret, chipnr;20872001 struct nand_chip *this = mtd->priv;20022002+ int rewrite_bbt[NAND_MAX_CHIPS]={0}; /* flags to indicate the page, if bbt needs to be rewritten. */20032003+ unsigned int bbt_masked_page; /* bbt mask to compare to page being erased. */20042004+ /* It is used to see if the current page is in the same */20052005+ /* 256 block group and the same bank as the bbt. */2088200620892007 DEBUG (MTD_DEBUG_LEVEL3,20902008 "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len);···21342044 goto erase_exit;21352045 }2136204620472047+ /* if BBT requires refresh, set the BBT page mask to see if the BBT should be rewritten */20482048+ if (this->options & BBT_AUTO_REFRESH) {20492049+ bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;20502050+ } else {20512051+ bbt_masked_page = 0xffffffff; /* should not match anything */20522052+ }20532053+21372054 /* Loop through the pages */21382055 len = instr->len;21392056···2163206621642067 status = this->waitfunc (mtd, this, FL_ERASING);2165206820692069+ /* See if operation failed and additional status checks are available */20702070+ if ((status & NAND_STATUS_FAIL) && (this->errstat)) {20712071+ status = this->errstat(mtd, this, FL_ERASING, status, page);20722072+ }20732073+21662074 /* See if block erase succeeded */21672167- if (status & 0x01) {20752075+ if (status & NAND_STATUS_FAIL) {21682076 DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);21692077 instr->state = MTD_ERASE_FAILED;21702078 instr->fail_addr = (page << this->page_shift);21712079 goto erase_exit;20802080+ }20812081+20822082+ /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */20832083+ if (this->options & BBT_AUTO_REFRESH) {20842084+ if (((page & BBT_PAGE_MASK) == bbt_masked_page) && 20852085+ (page != this->bbt_td->pages[chipnr])) {20862086+ rewrite_bbt[chipnr] = (page << this->page_shift);20872087+ }21722088 }2173208921742090 /* Increment page address and decrement length */···21932083 chipnr++;21942084 this->select_chip(mtd, -1);21952085 this->select_chip(mtd, chipnr);20862086+20872087+ /* if BBT requires refresh and BBT-PERCHIP, 20882088+ * set the BBT page mask to see if this BBT should be rewritten */20892089+ if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) {20902090+ bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;20912091+ }20922092+21962093 }21972094 }21982095 instr->state = MTD_ERASE_DONE;···2213209622142097 /* Deselect and wake up anyone waiting on the device */22152098 nand_release_device(mtd);20992099+21002100+ /* if BBT requires refresh and erase was successful, rewrite any selected bad block tables */21012101+ if ((this->options & BBT_AUTO_REFRESH) && (!ret)) {21022102+ for (chipnr = 0; chipnr < this->numchips; chipnr++) {21032103+ if (rewrite_bbt[chipnr]) {21042104+ /* update the BBT for chip */21052105+ DEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n", 21062106+ chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]);21072107+ nand_update_bbt (mtd, rewrite_bbt[chipnr]);21082108+ }21092109+ }21102110+ }2216211122172112 /* Return more or less happy */22182113 return ret;···22972168 */22982169int nand_scan (struct mtd_info *mtd, int maxchips)22992170{23002300- int i, j, nand_maf_id, nand_dev_id, busw;21712171+ int i, nand_maf_id, nand_dev_id, busw, maf_id;23012172 struct nand_chip *this = mtd->priv;2302217323032174 /* Get buswidth to select the correct functions*/···23852256 busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;23862257 }2387225822592259+ /* Try to identify manufacturer */22602260+ for (maf_id = 0; nand_manuf_ids[maf_id].id != 0x0; maf_id++) {22612261+ if (nand_manuf_ids[maf_id].id == nand_maf_id)22622262+ break;22632263+ }22642264+23882265 /* Check, if buswidth is correct. Hardware drivers should set23892266 * this correct ! */23902267 if (busw != (this->options & NAND_BUSWIDTH_16)) {23912268 printk (KERN_INFO "NAND device: Manufacturer ID:"23922269 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, 23932393- nand_manuf_ids[i].name , mtd->name);22702270+ nand_manuf_ids[maf_id].name , mtd->name);23942271 printk (KERN_WARNING 23952272 "NAND bus width %d instead %d bit\n", 23962273 (this->options & NAND_BUSWIDTH_16) ? 16 : 8,···24352300 if (mtd->oobblock > 512 && this->cmdfunc == nand_command)24362301 this->cmdfunc = nand_command_lp;2437230224382438- /* Try to identify manufacturer */24392439- for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {24402440- if (nand_manuf_ids[j].id == nand_maf_id)24412441- break;24422442- }24432303 printk (KERN_INFO "NAND device: Manufacturer ID:"24442304 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, 24452445- nand_manuf_ids[j].name , nand_flash_ids[i].name);23052305+ nand_manuf_ids[maf_id].name , nand_flash_ids[i].name);24462306 break;24472307 }24482308···2518238825192389 /* The number of bytes available for the filesystem to place fs dependend25202390 * oob data */25212521- if (this->options & NAND_BUSWIDTH_16) {25222522- mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 2);25232523- if (this->autooob->eccbytes & 0x01)25242524- mtd->oobavail--;25252525- } else25262526- mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1);23912391+ mtd->oobavail = 0;23922392+ for (i = 0; this->autooob->oobfree[i][1]; i++)23932393+ mtd->oobavail += this->autooob->oobfree[i][1];2527239425282395 /* 25292396 * check ECC mode, default to software···26512524 memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));2652252526532526 mtd->owner = THIS_MODULE;25272527+25282528+ /* Check, if we should skip the bad block table scan */25292529+ if (this->options & NAND_SKIP_BBTSCAN)25302530+ return 0;2654253126552532 /* Build bad block table */26562533 return this->scan_bbt (mtd);···26862555 kfree (this->data_buf);26872556}2688255726892689-EXPORT_SYMBOL (nand_scan);26902690-EXPORT_SYMBOL (nand_release);25582558+EXPORT_SYMBOL_GPL (nand_scan);25592559+EXPORT_SYMBOL_GPL (nand_release);2691256026922561MODULE_LICENSE ("GPL");26932562MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
+86-28
drivers/mtd/nand/nand_bbt.c
···66 * 77 * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)88 *99- * $Id: nand_bbt.c,v 1.28 2004/11/13 10:19:09 gleixner Exp $99+ * $Id: nand_bbt.c,v 1.33 2005/06/14 15:47:56 gleixner Exp $1010 *1111 * This program is free software; you can redistribute it and/or modify1212 * it under the terms of the GNU General Public License version 2 as···7777*/7878static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)7979{8080- int i, end;8080+ int i, end = 0;8181 uint8_t *p = buf;82828383 end = paglen + td->offs;···9595 return -1;9696 }97979898- p += td->len;9999- end += td->len;10098 if (td->options & NAND_BBT_SCANEMPTY) {9999+ p += td->len;100100+ end += td->len;101101 for (i = end; i < len; i++) {102102 if (*p++ != 0xff)103103 return -1;104104 }105105+ }106106+ return 0;107107+}108108+109109+/** 110110+ * check_short_pattern - [GENERIC] check if a pattern is in the buffer111111+ * @buf: the buffer to search112112+ * @len: the length of buffer to search113113+ * @paglen: the pagelength114114+ * @td: search pattern descriptor115115+ *116116+ * Check for a pattern at the given place. Used to search bad block117117+ * tables and good / bad block identifiers. Same as check_pattern, but 118118+ * no optional empty check and the pattern is expected to start119119+ * at offset 0.120120+ *121121+*/122122+static int check_short_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)123123+{124124+ int i;125125+ uint8_t *p = buf;126126+127127+ /* Compare the pattern */128128+ for (i = 0; i < td->len; i++) {129129+ if (p[i] != td->pattern[i])130130+ return -1;105131 }106132 return 0;107133}···278252 * Create a bad block table by scanning the device279253 * for the given good/bad block identify pattern280254 */281281-static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)255255+static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)282256{283257 struct nand_chip *this = mtd->priv;284258 int i, j, numblocks, len, scanlen;···296270 else 297271 len = 1;298272 }299299- scanlen = mtd->oobblock + mtd->oobsize;300300- readlen = len * mtd->oobblock;301301- ooblen = len * mtd->oobsize;273273+274274+ if (!(bd->options & NAND_BBT_SCANEMPTY)) {275275+ /* We need only read few bytes from the OOB area */276276+ scanlen = ooblen = 0;277277+ readlen = bd->len;278278+ } else {279279+ /* Full page content should be read */280280+ scanlen = mtd->oobblock + mtd->oobsize;281281+ readlen = len * mtd->oobblock;282282+ ooblen = len * mtd->oobsize;283283+ }302284303285 if (chip == -1) {304286 /* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it···318284 if (chip >= this->numchips) {319285 printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",320286 chip + 1, this->numchips);321321- return; 287287+ return -EINVAL;322288 }323289 numblocks = this->chipsize >> (this->bbt_erase_shift - 1);324290 startblock = chip * numblocks;···327293 }328294329295 for (i = startblock; i < numblocks;) {330330- nand_read_raw (mtd, buf, from, readlen, ooblen);296296+ int ret;297297+298298+ if (bd->options & NAND_BBT_SCANEMPTY)299299+ if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen)))300300+ return ret;301301+331302 for (j = 0; j < len; j++) {332332- if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {333333- this->bbt[i >> 3] |= 0x03 << (i & 0x6);334334- printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 335335- i >> 1, (unsigned int) from);336336- break;303303+ if (!(bd->options & NAND_BBT_SCANEMPTY)) {304304+ size_t retlen;305305+306306+ /* No need to read pages fully, just read required OOB bytes */307307+ ret = mtd->read_oob(mtd, from + j * mtd->oobblock + bd->offs,308308+ readlen, &retlen, &buf[0]);309309+ if (ret)310310+ return ret;311311+312312+ if (check_short_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {313313+ this->bbt[i >> 3] |= 0x03 << (i & 0x6);314314+ printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 315315+ i >> 1, (unsigned int) from);316316+ break;317317+ }318318+ } else {319319+ if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {320320+ this->bbt[i >> 3] |= 0x03 << (i & 0x6);321321+ printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 322322+ i >> 1, (unsigned int) from);323323+ break;324324+ }337325 }338326 }339327 i += 2;340328 from += (1 << this->bbt_erase_shift);341329 }330330+ return 0;342331}343332344333/**···646589 * The function creates a memory based bbt by scanning the device 647590 * for manufacturer / software marked good / bad blocks648591*/649649-static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)592592+static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)650593{651594 struct nand_chip *this = mtd->priv;652595653653- /* Ensure that we only scan for the pattern and nothing else */654654- bd->options = 0;655655- create_bbt (mtd, this->data_buf, bd, -1);656656- return 0;596596+ bd->options &= ~NAND_BBT_SCANEMPTY;597597+ return create_bbt (mtd, this->data_buf, bd, -1);657598}658599659600/**···863808 /* If no primary table decriptor is given, scan the device864809 * to build a memory based bad block table865810 */866866- if (!td)867867- return nand_memory_bbt(mtd, bd);811811+ if (!td) {812812+ if ((res = nand_memory_bbt(mtd, bd))) {813813+ printk (KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");814814+ kfree (this->bbt);815815+ this->bbt = NULL;816816+ }817817+ return res;818818+ }868819869820 /* Allocate a temporary buffer for one eraseblock incl. oob */870821 len = (1 << this->bbt_erase_shift);···965904}966905967906/* Define some generic bad / good block scan pattern which are used 968968- * while scanning a device for factory marked good / bad blocks969969- * 970970- * The memory based patterns just 971971- */907907+ * while scanning a device for factory marked good / bad blocks. */972908static uint8_t scan_ff_pattern[] = { 0xff, 0xff };973909974910static struct nand_bbt_descr smallpage_memorybased = {975975- .options = 0,911911+ .options = NAND_BBT_SCAN2NDPAGE,976912 .offs = 5,977913 .len = 1,978914 .pattern = scan_ff_pattern···11001042 res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;1101104311021044 DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", 11031103- (unsigned int)offs, res, block >> 1);10451045+ (unsigned int)offs, block >> 1, res);1104104611051047 switch ((int)res) {11061048 case 0x00: return 0;
+13-5
drivers/mtd/nand/nand_ids.c
···22 * drivers/mtd/nandids.c33 *44 * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)55- *66- * $Id: nand_ids.c,v 1.10 2004/05/26 13:40:12 gleixner Exp $55+ *66+ * $Id: nand_ids.c,v 1.14 2005/06/23 09:38:50 gleixner Exp $77 *88 * This program is free software; you can redistribute it and/or modify99 * it under the terms of the GNU General Public License version 2 as···5656 {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},57575858 {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0},5959+ {"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0},5960 {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0},6061 {"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},6262+ {"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},6163 {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},6464+ {"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},62656366 {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0},64676565- {"NAND 512MiB 3,3V 8-bit", 0xDC, 512, 512, 0x4000, 0},6666-6768 /* These are the new chips with large page size. The pagesize6869 * and the erasesize is determined from the extended id bytes6970 */7171+ /*512 Megabit */7272+ {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},7373+ {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},7474+ {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},7575+ {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},7676+7077 /* 1 Gigabit */7178 {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},7279 {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},···110103 * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go111104 * There are more speed improvements for reads and writes possible, but not implemented now 112105 */113113- {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},106106+ {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH},114107115108 {NULL,}116109};···125118 {NAND_MFR_NATIONAL, "National"},126119 {NAND_MFR_RENESAS, "Renesas"},127120 {NAND_MFR_STMICRO, "ST Micro"},121121+ {NAND_MFR_HYNIX, "Hynix"},128122 {0x0, "Unknown"}129123};130124
+12-29
drivers/mtd/nand/nandsim.c
···2222 * along with this program; if not, write to the Free Software2323 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA2424 *2525- * $Id: nandsim.c,v 1.7 2004/12/06 11:53:06 dedekind Exp $2525+ * $Id: nandsim.c,v 1.8 2005/03/19 15:33:56 dedekind Exp $2626 */27272828#include <linux/config.h>···14841484}1485148514861486/*14871487- * Having only NAND chip IDs we call nand_scan which detects NAND flash14881488- * parameters and then calls scan_bbt in order to scan/find/build the14891489- * NAND flash bad block table. But since at that moment the NAND flash14901490- * image isn't allocated in the simulator, errors arise. To avoid this14911491- * we redefine the scan_bbt callback and initialize the nandsim structure14921492- * before the flash media scanning.14931493- */14941494-int ns_scan_bbt(struct mtd_info *mtd)14951495-{ 14961496- struct nand_chip *chip = (struct nand_chip *)mtd->priv;14971497- struct nandsim *ns = (struct nandsim *)(chip->priv);14981498- int retval;14991499-15001500- if (!NS_IS_INITIALIZED(ns))15011501- if ((retval = init_nandsim(mtd)) != 0) {15021502- NS_ERR("scan_bbt: can't initialize the nandsim structure\n");15031503- return retval;15041504- }15051505- if ((retval = nand_default_bbt(mtd)) != 0) {15061506- free_nandsim(ns);15071507- return retval;15081508- }15091509-15101510- return 0;15111511-}15121512-15131513-/*15141487 * Module initialization function15151488 */15161489int __init ns_init_module(void)···15171544 chip->hwcontrol = ns_hwcontrol;15181545 chip->read_byte = ns_nand_read_byte;15191546 chip->dev_ready = ns_device_ready;15201520- chip->scan_bbt = ns_scan_bbt;15211547 chip->write_byte = ns_nand_write_byte;15221548 chip->write_buf = ns_nand_write_buf;15231549 chip->read_buf = ns_nand_read_buf;···15241552 chip->write_word = ns_nand_write_word;15251553 chip->read_word = ns_nand_read_word;15261554 chip->eccmode = NAND_ECC_SOFT;15551555+ chip->options |= NAND_SKIP_BBTSCAN;1527155615281557 /* 15291558 * Perform minimum nandsim structure initialization to handle···15501577 NS_ERR("can't register NAND Simulator\n");15511578 if (retval > 0)15521579 retval = -ENXIO;15801580+ goto error;15811581+ }15821582+15831583+ if ((retval = init_nandsim(nsmtd)) != 0) {15841584+ NS_ERR("scan_bbt: can't initialize the nandsim structure\n");15851585+ goto error;15861586+ }15871587+15881588+ if ((retval = nand_default_bbt(nsmtd)) != 0) {15891589+ free_nandsim(nand);15531590 goto error;15541591 }15551592
+132-8
drivers/mtd/nand/rtc_from4.c
···66 * Derived from drivers/mtd/nand/spia.c77 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)88 *99- * $Id: rtc_from4.c,v 1.7 2004/11/04 12:53:10 gleixner Exp $99+ * $Id: rtc_from4.c,v 1.9 2005/01/24 20:40:11 dmarlin Exp $1010 *1111 * This program is free software; you can redistribute it and/or modify1212 * it under the terms of the GNU General Public License version 2 as···8383#define RTC_FROM4_RS_ECC_CHK (RTC_FROM4_NAND_ADDR_FPGA | 0x00000070)8484#define RTC_FROM4_RS_ECC_CHK_ERROR (1 << 7)85858686+#define ERR_STAT_ECC_AVAILABLE 0x208787+8688/* Undefine for software ECC */8789#define RTC_FROM4_HWECC 19090+9191+/* Define as 1 for no virtual erase blocks (in JFFS2) */9292+#define RTC_FROM4_NO_VIRTBLOCKS 088938994/*9095 * Module stuff9196 */9292-static void __iomem *rtc_from4_fio_base = P2SEGADDR(RTC_FROM4_FIO_BASE);9797+static void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE);93989499const static struct mtd_partition partition_info[] = {95100 {···272267}273268274269275275-276270/*277271 * rtc_from4_nand_device_ready - hardware specific ready/busy check278272 * @mtd: MTD device structure···289285 return (status & RTC_FROM4_DEVICE_READY);290286291287}288288+289289+290290+/*291291+ * deplete - code to perform device recovery in case there was a power loss292292+ * @mtd: MTD device structure293293+ * @chip: Chip to select (0 == slot 3, 1 == slot 4)294294+ *295295+ * If there was a sudden loss of power during an erase operation, a 296296+ * "device recovery" operation must be performed when power is restored297297+ * to ensure correct operation. This routine performs the required steps298298+ * for the requested chip.299299+ *300300+ * See page 86 of the data sheet for details.301301+ *302302+ */303303+static void deplete(struct mtd_info *mtd, int chip)304304+{305305+ struct nand_chip *this = mtd->priv;306306+307307+ /* wait until device is ready */308308+ while (!this->dev_ready(mtd));309309+310310+ this->select_chip(mtd, chip);311311+312312+ /* Send the commands for device recovery, phase 1 */313313+ this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000);314314+ this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1);315315+316316+ /* Send the commands for device recovery, phase 2 */317317+ this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004);318318+ this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1);319319+320320+}321321+292322293323#ifdef RTC_FROM4_HWECC294324/*···367329368330}369331332332+370333/*371334 * rtc_from4_calculate_ecc - hardware specific code to read ECC code372335 * @mtd: MTD device structure···395356 ecc_code[7] |= 0x0f; /* set the last four bits (not used) */396357}397358359359+398360/*399361 * rtc_from4_correct_data - hardware specific code to correct data using ECC code400362 * @mtd: MTD device structure···405365 *406366 * The FPGA tells us fast, if there's an error or not. If no, we go back happy407367 * else we read the ecc results from the fpga and call the rs library to decode408408- * and hopefully correct the error368368+ * and hopefully correct the error.409369 *410410- * For now I use the code, which we read from the FLASH to use the RS lib,411411- * as the syndrom conversion has a unresolved issue.412370 */413371static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2)414372{415373 int i, j, res;416374 unsigned short status; 417417- uint16_t par[6], syn[6], tmp;375375+ uint16_t par[6], syn[6];418376 uint8_t ecc[8];419377 volatile unsigned short *rs_ecc;420378···454416 }455417456418 /* Let the library code do its magic.*/457457- res = decode_rs8(rs_decoder, buf, par, 512, syn, 0, NULL, 0xff, NULL);419419+ res = decode_rs8(rs_decoder, (uint8_t *)buf, par, 512, syn, 0, NULL, 0xff, NULL);458420 if (res > 0) {459421 DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " 460422 "ECC corrected %d errors on read\n", res);461423 }462424 return res;463425}426426+427427+428428+/**429429+ * rtc_from4_errstat - perform additional error status checks430430+ * @mtd: MTD device structure431431+ * @this: NAND chip structure432432+ * @state: state or the operation433433+ * @status: status code returned from read status434434+ * @page: startpage inside the chip, must be called with (page & this->pagemask)435435+ * 436436+ * Perform additional error status checks on erase and write failures 437437+ * to determine if errors are correctable. For this device, correctable 438438+ * 1-bit errors on erase and write are considered acceptable.439439+ *440440+ * note: see pages 34..37 of data sheet for details.441441+ *442442+ */443443+static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page)444444+{445445+ int er_stat=0;446446+ int rtn, retlen;447447+ size_t len;448448+ uint8_t *buf;449449+ int i;450450+451451+ this->cmdfunc (mtd, NAND_CMD_STATUS_CLEAR, -1, -1);452452+453453+ if (state == FL_ERASING) {454454+ for (i=0; i<4; i++) {455455+ if (status & 1<<(i+1)) {456456+ this->cmdfunc (mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1);457457+ rtn = this->read_byte(mtd);458458+ this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);459459+ if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {460460+ er_stat |= 1<<(i+1); /* err_ecc_not_avail */461461+ }462462+ }463463+ }464464+ } else if (state == FL_WRITING) {465465+ /* single bank write logic */466466+ this->cmdfunc (mtd, NAND_CMD_STATUS_ERROR, -1, -1);467467+ rtn = this->read_byte(mtd);468468+ this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);469469+ if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {470470+ er_stat |= 1<<1; /* err_ecc_not_avail */471471+ } else {472472+ len = mtd->oobblock;473473+ buf = kmalloc (len, GFP_KERNEL);474474+ if (!buf) {475475+ printk (KERN_ERR "rtc_from4_errstat: Out of memory!\n");476476+ er_stat = 1; /* if we can't check, assume failed */477477+ } else {478478+ /* recovery read */479479+ /* page read */480480+ rtn = nand_do_read_ecc (mtd, page, len, &retlen, buf, NULL, this->autooob, 1);481481+ if (rtn) { /* if read failed or > 1-bit error corrected */482482+ er_stat |= 1<<1; /* ECC read failed */483483+ }484484+ kfree(buf);485485+ }486486+ }487487+ }488488+489489+ rtn = status;490490+ if (er_stat == 0) { /* if ECC is available */491491+ rtn = (status & ~NAND_STATUS_FAIL); /* clear the error bit */492492+ }493493+494494+ return rtn;495495+}464496#endif497497+465498466499/*467500 * Main initialization routine···541432{542433 struct nand_chip *this;543434 unsigned short bcr1, bcr2, wcr2;435435+ int i;544436545437 /* Allocate memory for MTD device structure and private data */546438 rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip),···593483594484 this->eccmode = NAND_ECC_HW8_512;595485 this->options |= NAND_HWECC_SYNDROME;486486+ /* return the status of extra status and ECC checks */487487+ this->errstat = rtc_from4_errstat;596488 /* set the nand_oobinfo to support FPGA H/W error detection */597489 this->autooob = &rtc_from4_nand_oobinfo;598490 this->enable_hwecc = rtc_from4_enable_hwecc;···615503 kfree(rtc_from4_mtd);616504 return -ENXIO;617505 }506506+507507+ /* Perform 'device recovery' for each chip in case there was a power loss. */508508+ for (i=0; i < this->numchips; i++) {509509+ deplete(rtc_from4_mtd, i);510510+ }511511+512512+#if RTC_FROM4_NO_VIRTBLOCKS513513+ /* use a smaller erase block to minimize wasted space when a block is bad */514514+ /* note: this uses eight times as much RAM as using the default and makes */515515+ /* mounts take four times as long. */516516+ rtc_from4_mtd->flags |= MTD_NO_VIRTBLOCKS;517517+#endif618518619519 /* Register the partitions */620520 add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
+161-136
drivers/mtd/nand/s3c2410.c
···11/* linux/drivers/mtd/nand/s3c2410.c22 *33- * Copyright (c) 2004 Simtec Electronics44- * Ben Dooks <ben@simtec.co.uk>33+ * Copyright (c) 2004,2005 Simtec Electronics44+ * http://www.simtec.co.uk/products/SWLINUX/55+ * Ben Dooks <ben@simtec.co.uk>56 *66- * Samsung S3C2410 NAND driver77+ * Samsung S3C2410/S3C240 NAND driver78 *89 * Changelog:910 * 21-Sep-2004 BJD Initial version1011 * 23-Sep-2004 BJD Mulitple device support1112 * 28-Sep-2004 BJD Fixed ECC placement for Hardware mode1213 * 12-Oct-2004 BJD Fixed errors in use of platform data1414+ * 18-Feb-2005 BJD Fix sparse errors1515+ * 14-Mar-2005 BJD Applied tglx's code reduction patch1616+ * 02-May-2005 BJD Fixed s3c2440 support1717+ * 02-May-2005 BJD Reduced hwcontrol decode1818+ * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug1919+ * 08-Jul-2005 BJD Fix OOPS when no platform data supplied1320 *1414- * $Id: s3c2410.c,v 1.7 2005/01/05 18:05:14 dwmw2 Exp $2121+ * $Id: s3c2410.c,v 1.14 2005/07/06 20:05:06 bjd Exp $1522 *1623 * This program is free software; you can redistribute it and/or modify1724 * it under the terms of the GNU General Public License as published by···7669 */77707871static struct nand_oobinfo nand_hw_eccoob = {7979- .useecc = MTD_NANDECC_AUTOPLACE,8080- .eccbytes = 3,8181- .eccpos = {0, 1, 2 },8282- .oobfree = { {8, 8} }7272+ .useecc = MTD_NANDECC_AUTOPLACE,7373+ .eccbytes = 3,7474+ .eccpos = {0, 1, 2 },7575+ .oobfree = { {8, 8} }8376};84778578/* controller and mtd information */···10699 struct device *device;107100 struct resource *area;108101 struct clk *clk;109109- void *regs;102102+ void __iomem *regs;110103 int mtd_count;104104+105105+ unsigned char is_s3c2440;111106};112107113108/* conversion functions */···174165 /* calculate the timing information for the controller */175166176167 if (plat != NULL) {177177- tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 8);168168+ tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4);178169 twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8);179170 twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8);180171 } else {181172 /* default timings */182182- tacls = 8;173173+ tacls = 4;183174 twrph0 = 8;184175 twrph1 = 8;185176 }···194185 to_ns(twrph0, clkrate),195186 to_ns(twrph1, clkrate));196187197197- cfg = S3C2410_NFCONF_EN;198198- cfg |= S3C2410_NFCONF_TACLS(tacls-1);199199- cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1);200200- cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1);188188+ if (!info->is_s3c2440) {189189+ cfg = S3C2410_NFCONF_EN;190190+ cfg |= S3C2410_NFCONF_TACLS(tacls-1);191191+ cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1);192192+ cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1);193193+ } else {194194+ cfg = S3C2440_NFCONF_TACLS(tacls-1);195195+ cfg |= S3C2440_NFCONF_TWRPH0(twrph0-1);196196+ cfg |= S3C2440_NFCONF_TWRPH1(twrph1-1);197197+ }201198202199 pr_debug(PFX "NF_CONF is 0x%lx\n", cfg);203200···218203 struct s3c2410_nand_info *info;219204 struct s3c2410_nand_mtd *nmtd; 220205 struct nand_chip *this = mtd->priv;206206+ void __iomem *reg;221207 unsigned long cur;208208+ unsigned long bit;222209223210 nmtd = this->priv;224211 info = nmtd->info;225212226226- cur = readl(info->regs + S3C2410_NFCONF);213213+ bit = (info->is_s3c2440) ? S3C2440_NFCONT_nFCE : S3C2410_NFCONF_nFCE;214214+ reg = info->regs+((info->is_s3c2440) ? S3C2440_NFCONT:S3C2410_NFCONF);215215+216216+ cur = readl(reg);227217228218 if (chip == -1) {229229- cur |= S3C2410_NFCONF_nFCE;219219+ cur |= bit;230220 } else {231231- if (chip > nmtd->set->nr_chips) {221221+ if (nmtd->set != NULL && chip > nmtd->set->nr_chips) {232222 printk(KERN_ERR PFX "chip %d out of range\n", chip);233223 return;234224 }···243223 (info->platform->select_chip)(nmtd->set, chip);244224 }245225246246- cur &= ~S3C2410_NFCONF_nFCE;226226+ cur &= ~bit;247227 }248228249249- writel(cur, info->regs + S3C2410_NFCONF);229229+ writel(cur, reg);250230}251231252252-/* command and control functions */232232+/* command and control functions 233233+ *234234+ * Note, these all use tglx's method of changing the IO_ADDR_W field235235+ * to make the code simpler, and use the nand layer's code to issue the236236+ * command and address sequences via the proper IO ports.237237+ *238238+*/253239254240static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)255241{256242 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);257257- unsigned long cur;243243+ struct nand_chip *chip = mtd->priv;258244259245 switch (cmd) {260246 case NAND_CTL_SETNCE:261261- cur = readl(info->regs + S3C2410_NFCONF);262262- cur &= ~S3C2410_NFCONF_nFCE;263263- writel(cur, info->regs + S3C2410_NFCONF);264264- break;265265-266247 case NAND_CTL_CLRNCE:267267- cur = readl(info->regs + S3C2410_NFCONF);268268- cur |= S3C2410_NFCONF_nFCE;269269- writel(cur, info->regs + S3C2410_NFCONF);248248+ printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__);270249 break;271250272272- /* we don't need to implement these */273251 case NAND_CTL_SETCLE:274274- case NAND_CTL_CLRCLE:252252+ chip->IO_ADDR_W = info->regs + S3C2410_NFCMD;253253+ break;254254+275255 case NAND_CTL_SETALE:276276- case NAND_CTL_CLRALE:277277- pr_debug(PFX "s3c2410_nand_hwcontrol(%d) unusedn", cmd);256256+ chip->IO_ADDR_W = info->regs + S3C2410_NFADDR;257257+ break;258258+259259+ /* NAND_CTL_CLRCLE: */260260+ /* NAND_CTL_CLRALE: */261261+ default:262262+ chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;278263 break;279264 }280265}281266282282-/* s3c2410_nand_command283283- *284284- * This function implements sending commands and the relevant address285285- * information to the chip, via the hardware controller. Since the286286- * S3C2410 generates the correct ALE/CLE signaling automatically, we287287- * do not need to use hwcontrol.288288-*/267267+/* command and control functions */289268290290-static void s3c2410_nand_command (struct mtd_info *mtd, unsigned command,291291- int column, int page_addr)269269+static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)292270{293293- register struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);294294- register struct nand_chip *this = mtd->priv;271271+ struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);272272+ struct nand_chip *chip = mtd->priv;295273296296- /*297297- * Write out the command to the device.298298- */299299- if (command == NAND_CMD_SEQIN) {300300- int readcmd;274274+ switch (cmd) {275275+ case NAND_CTL_SETNCE:276276+ case NAND_CTL_CLRNCE:277277+ printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__);278278+ break;301279302302- if (column >= mtd->oobblock) {303303- /* OOB area */304304- column -= mtd->oobblock;305305- readcmd = NAND_CMD_READOOB;306306- } else if (column < 256) {307307- /* First 256 bytes --> READ0 */308308- readcmd = NAND_CMD_READ0;309309- } else {310310- column -= 256;311311- readcmd = NAND_CMD_READ1;312312- }313313-314314- writeb(readcmd, info->regs + S3C2410_NFCMD);315315- }316316- writeb(command, info->regs + S3C2410_NFCMD);280280+ case NAND_CTL_SETCLE:281281+ chip->IO_ADDR_W = info->regs + S3C2440_NFCMD;282282+ break;317283318318- /* Set ALE and clear CLE to start address cycle */284284+ case NAND_CTL_SETALE:285285+ chip->IO_ADDR_W = info->regs + S3C2440_NFADDR;286286+ break;319287320320- if (column != -1 || page_addr != -1) {321321-322322- /* Serially input address */323323- if (column != -1) {324324- /* Adjust columns for 16 bit buswidth */325325- if (this->options & NAND_BUSWIDTH_16)326326- column >>= 1;327327- writeb(column, info->regs + S3C2410_NFADDR);328328- }329329- if (page_addr != -1) {330330- writeb((unsigned char) (page_addr), info->regs + S3C2410_NFADDR);331331- writeb((unsigned char) (page_addr >> 8), info->regs + S3C2410_NFADDR);332332- /* One more address cycle for higher density devices */333333- if (this->chipsize & 0x0c000000) 334334- writeb((unsigned char) ((page_addr >> 16) & 0x0f),335335- info->regs + S3C2410_NFADDR);336336- }337337- /* Latch in address */338338- }339339-340340- /* 341341- * program and erase have their own busy handlers 342342- * status and sequential in needs no delay343343- */344344- switch (command) {345345-346346- case NAND_CMD_PAGEPROG:347347- case NAND_CMD_ERASE1:348348- case NAND_CMD_ERASE2:349349- case NAND_CMD_SEQIN:350350- case NAND_CMD_STATUS:351351- return;352352-353353- case NAND_CMD_RESET:354354- if (this->dev_ready) 355355- break;356356-357357- udelay(this->chip_delay);358358- writeb(NAND_CMD_STATUS, info->regs + S3C2410_NFCMD);359359-360360- while ( !(this->read_byte(mtd) & 0x40));361361- return;362362-363363- /* This applies to read commands */ 288288+ /* NAND_CTL_CLRCLE: */289289+ /* NAND_CTL_CLRALE: */364290 default:365365- /* 366366- * If we don't have access to the busy pin, we apply the given367367- * command delay368368- */369369- if (!this->dev_ready) {370370- udelay (this->chip_delay);371371- return;372372- } 291291+ chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;292292+ break;373293 }374374-375375- /* Apply this short delay always to ensure that we do wait tWB in376376- * any case on any machine. */377377- ndelay (100);378378- /* wait until command is processed */379379- while (!this->dev_ready(mtd));380294}381381-382295383296/* s3c2410_nand_devready()384297 *···322369{323370 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);324371372372+ if (info->is_s3c2440)373373+ return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY;325374 return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;326375}376376+327377328378/* ECC handling functions */329379···350394 return -1;351395}352396397397+/* ECC functions398398+ *399399+ * These allow the s3c2410 and s3c2440 to use the controller's ECC400400+ * generator block to ECC the data as it passes through]401401+*/402402+353403static void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)354404{355405 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);···364402 ctrl = readl(info->regs + S3C2410_NFCONF);365403 ctrl |= S3C2410_NFCONF_INITECC;366404 writel(ctrl, info->regs + S3C2410_NFCONF);405405+}406406+407407+static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)408408+{409409+ struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);410410+ unsigned long ctrl;411411+412412+ ctrl = readl(info->regs + S3C2440_NFCONT);413413+ writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT);367414}368415369416static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd,···391420}392421393422394394-/* over-ride the standard functions for a little more speed? */423423+static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd,424424+ const u_char *dat, u_char *ecc_code)425425+{426426+ struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);427427+ unsigned long ecc = readl(info->regs + S3C2440_NFMECC0);428428+429429+ ecc_code[0] = ecc;430430+ ecc_code[1] = ecc >> 8;431431+ ecc_code[2] = ecc >> 16;432432+433433+ pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n",434434+ ecc_code[0], ecc_code[1], ecc_code[2]);435435+436436+ return 0;437437+}438438+439439+440440+/* over-ride the standard functions for a little more speed. We can441441+ * use read/write block to move the data buffers to/from the controller442442+*/395443396444static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)397445{···513523{514524 struct nand_chip *chip = &nmtd->chip;515525516516- chip->IO_ADDR_R = (char *)info->regs + S3C2410_NFDATA;517517- chip->IO_ADDR_W = (char *)info->regs + S3C2410_NFDATA;526526+ chip->IO_ADDR_R = info->regs + S3C2410_NFDATA;527527+ chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;518528 chip->hwcontrol = s3c2410_nand_hwcontrol;519529 chip->dev_ready = s3c2410_nand_devready;520520- chip->cmdfunc = s3c2410_nand_command;521530 chip->write_buf = s3c2410_nand_write_buf;522531 chip->read_buf = s3c2410_nand_read_buf;523532 chip->select_chip = s3c2410_nand_select_chip;···524535 chip->priv = nmtd;525536 chip->options = 0;526537 chip->controller = &info->controller;538538+539539+ if (info->is_s3c2440) {540540+ chip->IO_ADDR_R = info->regs + S3C2440_NFDATA;541541+ chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;542542+ chip->hwcontrol = s3c2440_nand_hwcontrol;543543+ }527544528545 nmtd->info = info;529546 nmtd->mtd.priv = chip;···541546 chip->calculate_ecc = s3c2410_nand_calculate_ecc;542547 chip->eccmode = NAND_ECC_HW3_512;543548 chip->autooob = &nand_hw_eccoob;549549+550550+ if (info->is_s3c2440) {551551+ chip->enable_hwecc = s3c2440_nand_enable_hwecc;552552+ chip->calculate_ecc = s3c2440_nand_calculate_ecc;553553+ }544554 } else {545555 chip->eccmode = NAND_ECC_SOFT;546556 }···559559 * nand layer to look for devices560560*/561561562562-static int s3c2410_nand_probe(struct device *dev)562562+static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440)563563{564564 struct platform_device *pdev = to_platform_device(dev);565565 struct s3c2410_platform_nand *plat = to_nand_plat(dev);···585585 dev_set_drvdata(dev, info);586586587587 spin_lock_init(&info->controller.lock);588588+ init_waitqueue_head(&info->controller.wq);588589589590 /* get the clock source and enable it */590591···601600602601 /* allocate and map the resource */603602604604- res = pdev->resource; /* assume that the flash has one resource */603603+ /* currently we assume we have the one resource */604604+ res = pdev->resource;605605 size = res->end - res->start + 1;606606607607 info->area = request_mem_region(res->start, size, pdev->name);···613611 goto exit_error;614612 }615613616616- info->device = dev;617617- info->platform = plat;618618- info->regs = ioremap(res->start, size);614614+ info->device = dev;615615+ info->platform = plat;616616+ info->regs = ioremap(res->start, size);617617+ info->is_s3c2440 = is_s3c2440;619618620619 if (info->regs == NULL) {621620 printk(KERN_ERR PFX "cannot reserve register region\n");···681678 return err;682679}683680681681+/* driver device registration */682682+683683+static int s3c2410_nand_probe(struct device *dev)684684+{685685+ return s3c24xx_nand_probe(dev, 0);686686+}687687+688688+static int s3c2440_nand_probe(struct device *dev)689689+{690690+ return s3c24xx_nand_probe(dev, 1);691691+}692692+684693static struct device_driver s3c2410_nand_driver = {685694 .name = "s3c2410-nand",686695 .bus = &platform_bus_type,···700685 .remove = s3c2410_nand_remove,701686};702687688688+static struct device_driver s3c2440_nand_driver = {689689+ .name = "s3c2440-nand",690690+ .bus = &platform_bus_type,691691+ .probe = s3c2440_nand_probe,692692+ .remove = s3c2410_nand_remove,693693+};694694+703695static int __init s3c2410_nand_init(void)704696{705705- printk("S3C2410 NAND Driver, (c) 2004 Simtec Electronics\n");697697+ printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n");698698+699699+ driver_register(&s3c2440_nand_driver);706700 return driver_register(&s3c2410_nand_driver);707701}708702709703static void __exit s3c2410_nand_exit(void)710704{705705+ driver_unregister(&s3c2440_nand_driver);711706 driver_unregister(&s3c2410_nand_driver);712707}713708···726701727702MODULE_LICENSE("GPL");728703MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");729729-MODULE_DESCRIPTION("S3C2410 MTD NAND driver");704704+MODULE_DESCRIPTION("S3C24XX MTD NAND driver");
···11-/*22- * drivers/mtd/tx4925ndfmc.c33- *44- * Overview:55- * This is a device driver for the NAND flash device found on the66- * Toshiba RBTX4925 reference board, which is a SmartMediaCard. It supports 77- * 16MiB, 32MiB and 64MiB cards.88- *99- * Author: MontaVista Software, Inc. source@mvista.com1010- *1111- * Derived from drivers/mtd/autcpu12.c1212- * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)1313- *1414- * $Id: tx4925ndfmc.c,v 1.5 2004/10/05 13:50:20 gleixner Exp $1515- *1616- * Copyright (C) 2001 Toshiba Corporation 1717- * 1818- * 2003 (c) MontaVista Software, Inc. This file is licensed under1919- * the terms of the GNU General Public License version 2. This program2020- * is licensed "as is" without any warranty of any kind, whether express2121- * or implied.2222- *2323- */2424-2525-#include <linux/slab.h>2626-#include <linux/init.h>2727-#include <linux/module.h>2828-#include <linux/mtd/mtd.h>2929-#include <linux/mtd/nand.h>3030-#include <linux/mtd/partitions.h>3131-#include <linux/delay.h>3232-#include <asm/io.h>3333-#include <asm/tx4925/tx4925_nand.h>3434-3535-extern struct nand_oobinfo jffs2_oobinfo;3636-3737-/*3838- * MTD structure for RBTX4925 board3939- */4040-static struct mtd_info *tx4925ndfmc_mtd = NULL;4141-4242-/*4343- * Define partitions for flash devices4444- */4545-4646-static struct mtd_partition partition_info16k[] = {4747- { .name = "RBTX4925 flash partition 1",4848- .offset = 0,4949- .size = 8 * 0x00100000 },5050- { .name = "RBTX4925 flash partition 2",5151- .offset = 8 * 0x00100000,5252- .size = 8 * 0x00100000 },5353-};5454-5555-static struct mtd_partition partition_info32k[] = {5656- { .name = "RBTX4925 flash partition 1",5757- .offset = 0,5858- .size = 8 * 0x00100000 },5959- { .name = "RBTX4925 flash partition 2",6060- .offset = 8 * 0x00100000,6161- .size = 24 * 0x00100000 },6262-};6363-6464-static struct mtd_partition partition_info64k[] = {6565- { .name = "User FS",6666- .offset = 0,6767- .size = 16 * 0x00100000 },6868- { .name = "RBTX4925 flash partition 2",6969- .offset = 16 * 0x00100000,7070- .size = 48 * 0x00100000},7171-};7272-7373-static struct mtd_partition partition_info128k[] = {7474- { .name = "Skip bad section",7575- .offset = 0,7676- .size = 16 * 0x00100000 },7777- { .name = "User FS",7878- .offset = 16 * 0x00100000,7979- .size = 112 * 0x00100000 },8080-};8181-#define NUM_PARTITIONS16K 28282-#define NUM_PARTITIONS32K 28383-#define NUM_PARTITIONS64K 28484-#define NUM_PARTITIONS128K 28585-8686-/* 8787- * hardware specific access to control-lines8888-*/8989-static void tx4925ndfmc_hwcontrol(struct mtd_info *mtd, int cmd)9090-{9191-9292- switch(cmd){9393-9494- case NAND_CTL_SETCLE: 9595- tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CLE;9696- break;9797- case NAND_CTL_CLRCLE:9898- tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CLE;9999- break;100100- case NAND_CTL_SETALE:101101- tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ALE;102102- break;103103- case NAND_CTL_CLRALE: 104104- tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ALE;105105- break;106106- case NAND_CTL_SETNCE:107107- tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CE;108108- break;109109- case NAND_CTL_CLRNCE:110110- tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CE;111111- break;112112- case NAND_CTL_SETWP:113113- tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_WE;114114- break;115115- case NAND_CTL_CLRWP:116116- tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_WE;117117- break;118118- }119119-}120120-121121-/*122122-* read device ready pin123123-*/124124-static int tx4925ndfmc_device_ready(struct mtd_info *mtd)125125-{126126- int ready;127127- ready = (tx4925_ndfmcptr->sr & TX4925_NDSFR_BUSY) ? 0 : 1;128128- return ready;129129-}130130-void tx4925ndfmc_enable_hwecc(struct mtd_info *mtd, int mode)131131-{132132- /* reset first */133133- tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_MASK;134134- tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK;135135- tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_ENAB;136136-}137137-static void tx4925ndfmc_disable_ecc(void)138138-{139139- tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK;140140-}141141-static void tx4925ndfmc_enable_read_ecc(void)142142-{143143- tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK;144144- tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_READ;145145-}146146-void tx4925ndfmc_readecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code){147147- int i;148148- u_char *ecc = ecc_code;149149- tx4925ndfmc_enable_read_ecc();150150- for (i = 0;i < 6;i++,ecc++)151151- *ecc = tx4925_read_nfmc(&(tx4925_ndfmcptr->dtr));152152- tx4925ndfmc_disable_ecc();153153-}154154-void tx4925ndfmc_device_setup(void)155155-{156156-157157- *(unsigned char *)0xbb005000 &= ~0x08;158158-159159- /* reset NDFMC */160160- tx4925_ndfmcptr->rstr |= TX4925_NDFRSTR_RST;161161- while (tx4925_ndfmcptr->rstr & TX4925_NDFRSTR_RST); 162162-163163- /* setup BusSeparete, Hold Time, Strobe Pulse Width */164164- tx4925_ndfmcptr->mcr = TX4925_BSPRT ? TX4925_NDFMCR_BSPRT : 0;165165- tx4925_ndfmcptr->spr = TX4925_HOLD << 4 | TX4925_SPW; 166166-}167167-static u_char tx4925ndfmc_nand_read_byte(struct mtd_info *mtd)168168-{169169- struct nand_chip *this = mtd->priv;170170- return tx4925_read_nfmc(this->IO_ADDR_R);171171-}172172-173173-static void tx4925ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte)174174-{175175- struct nand_chip *this = mtd->priv;176176- tx4925_write_nfmc(byte, this->IO_ADDR_W);177177-}178178-179179-static void tx4925ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)180180-{181181- int i;182182- struct nand_chip *this = mtd->priv;183183-184184- for (i=0; i<len; i++)185185- tx4925_write_nfmc(buf[i], this->IO_ADDR_W);186186-}187187-188188-static void tx4925ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)189189-{190190- int i;191191- struct nand_chip *this = mtd->priv;192192-193193- for (i=0; i<len; i++)194194- buf[i] = tx4925_read_nfmc(this->IO_ADDR_R);195195-}196196-197197-static int tx4925ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)198198-{199199- int i;200200- struct nand_chip *this = mtd->priv;201201-202202- for (i=0; i<len; i++)203203- if (buf[i] != tx4925_read_nfmc(this->IO_ADDR_R))204204- return -EFAULT;205205-206206- return 0;207207-}208208-209209-/*210210- * Send command to NAND device211211- */212212-static void tx4925ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)213213-{214214- register struct nand_chip *this = mtd->priv;215215-216216- /* Begin command latch cycle */217217- this->hwcontrol(mtd, NAND_CTL_SETCLE);218218- /*219219- * Write out the command to the device.220220- */221221- if (command == NAND_CMD_SEQIN) {222222- int readcmd;223223-224224- if (column >= mtd->oobblock) {225225- /* OOB area */226226- column -= mtd->oobblock;227227- readcmd = NAND_CMD_READOOB;228228- } else if (column < 256) {229229- /* First 256 bytes --> READ0 */230230- readcmd = NAND_CMD_READ0;231231- } else {232232- column -= 256;233233- readcmd = NAND_CMD_READ1;234234- }235235- this->write_byte(mtd, readcmd);236236- }237237- this->write_byte(mtd, command);238238-239239- /* Set ALE and clear CLE to start address cycle */240240- this->hwcontrol(mtd, NAND_CTL_CLRCLE);241241-242242- if (column != -1 || page_addr != -1) {243243- this->hwcontrol(mtd, NAND_CTL_SETALE);244244-245245- /* Serially input address */246246- if (column != -1)247247- this->write_byte(mtd, column);248248- if (page_addr != -1) {249249- this->write_byte(mtd, (unsigned char) (page_addr & 0xff));250250- this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));251251- /* One more address cycle for higher density devices */252252- if (mtd->size & 0x0c000000) 253253- this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));254254- }255255- /* Latch in address */256256- this->hwcontrol(mtd, NAND_CTL_CLRALE);257257- }258258-259259- /* 260260- * program and erase have their own busy handlers 261261- * status and sequential in needs no delay262262- */263263- switch (command) {264264-265265- case NAND_CMD_PAGEPROG:266266- /* Turn off WE */267267- this->hwcontrol (mtd, NAND_CTL_CLRWP);268268- return;269269-270270- case NAND_CMD_SEQIN:271271- /* Turn on WE */272272- this->hwcontrol (mtd, NAND_CTL_SETWP);273273- return;274274-275275- case NAND_CMD_ERASE1:276276- case NAND_CMD_ERASE2:277277- case NAND_CMD_STATUS:278278- return;279279-280280- case NAND_CMD_RESET:281281- if (this->dev_ready) 282282- break;283283- this->hwcontrol(mtd, NAND_CTL_SETCLE);284284- this->write_byte(mtd, NAND_CMD_STATUS);285285- this->hwcontrol(mtd, NAND_CTL_CLRCLE);286286- while ( !(this->read_byte(mtd) & 0x40));287287- return;288288-289289- /* This applies to read commands */ 290290- default:291291- /* 292292- * If we don't have access to the busy pin, we apply the given293293- * command delay294294- */295295- if (!this->dev_ready) {296296- udelay (this->chip_delay);297297- return;298298- } 299299- }300300-301301- /* wait until command is processed */302302- while (!this->dev_ready(mtd));303303-}304304-305305-#ifdef CONFIG_MTD_CMDLINE_PARTS306306-extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partitio307307-n **pparts, char *);308308-#endif309309-310310-/*311311- * Main initialization routine312312- */313313-extern int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);314314-int __init tx4925ndfmc_init (void)315315-{316316- struct nand_chip *this;317317- int err = 0;318318-319319- /* Allocate memory for MTD device structure and private data */320320- tx4925ndfmc_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),321321- GFP_KERNEL);322322- if (!tx4925ndfmc_mtd) {323323- printk ("Unable to allocate RBTX4925 NAND MTD device structure.\n");324324- err = -ENOMEM;325325- goto out;326326- }327327-328328- tx4925ndfmc_device_setup();329329-330330- /* io is indirect via a register so don't need to ioremap address */331331-332332- /* Get pointer to private data */333333- this = (struct nand_chip *) (&tx4925ndfmc_mtd[1]);334334-335335- /* Initialize structures */336336- memset((char *) tx4925ndfmc_mtd, 0, sizeof(struct mtd_info));337337- memset((char *) this, 0, sizeof(struct nand_chip));338338-339339- /* Link the private data with the MTD structure */340340- tx4925ndfmc_mtd->priv = this;341341-342342- /* Set address of NAND IO lines */343343- this->IO_ADDR_R = (void __iomem *)&(tx4925_ndfmcptr->dtr);344344- this->IO_ADDR_W = (void __iomem *)&(tx4925_ndfmcptr->dtr);345345- this->hwcontrol = tx4925ndfmc_hwcontrol;346346- this->enable_hwecc = tx4925ndfmc_enable_hwecc;347347- this->calculate_ecc = tx4925ndfmc_readecc;348348- this->correct_data = nand_correct_data;349349- this->eccmode = NAND_ECC_HW6_512; 350350- this->dev_ready = tx4925ndfmc_device_ready;351351- /* 20 us command delay time */352352- this->chip_delay = 20; 353353- this->read_byte = tx4925ndfmc_nand_read_byte;354354- this->write_byte = tx4925ndfmc_nand_write_byte;355355- this->cmdfunc = tx4925ndfmc_nand_command;356356- this->write_buf = tx4925ndfmc_nand_write_buf;357357- this->read_buf = tx4925ndfmc_nand_read_buf;358358- this->verify_buf = tx4925ndfmc_nand_verify_buf;359359-360360- /* Scan to find existance of the device */361361- if (nand_scan (tx4925ndfmc_mtd, 1)) {362362- err = -ENXIO;363363- goto out_ior;364364- }365365-366366- /* Register the partitions */367367-#ifdef CONFIG_MTD_CMDLINE_PARTS368368- {369369- int mtd_parts_nb = 0;370370- struct mtd_partition *mtd_parts = 0;371371- mtd_parts_nb = parse_cmdline_partitions(tx4925ndfmc_mtd, &mtd_parts, "tx4925ndfmc");372372- if (mtd_parts_nb > 0)373373- add_mtd_partitions(tx4925ndfmc_mtd, mtd_parts, mtd_parts_nb);374374- else375375- add_mtd_device(tx4925ndfmc_mtd);376376- }377377-#else /* ifdef CONFIG_MTD_CMDLINE_PARTS */378378- switch(tx4925ndfmc_mtd->size){379379- case 0x01000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info16k, NUM_PARTITIONS16K); break;380380- case 0x02000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info32k, NUM_PARTITIONS32K); break;381381- case 0x04000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info64k, NUM_PARTITIONS64K); break; 382382- case 0x08000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info128k, NUM_PARTITIONS128K); break; 383383- default: {384384- printk ("Unsupported SmartMedia device\n"); 385385- err = -ENXIO;386386- goto out_ior;387387- }388388- }389389-#endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */390390- goto out;391391-392392-out_ior:393393-out:394394- return err;395395-}396396-397397-module_init(tx4925ndfmc_init);398398-399399-/*400400- * Clean up routine401401- */402402-#ifdef MODULE403403-static void __exit tx4925ndfmc_cleanup (void)404404-{405405- /* Release resources, unregister device */406406- nand_release (tx4925ndfmc_mtd);407407-408408- /* Free the MTD device structure */409409- kfree (tx4925ndfmc_mtd);410410-}411411-module_exit(tx4925ndfmc_cleanup);412412-#endif413413-414414-MODULE_LICENSE("GPL");415415-MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");416416-MODULE_DESCRIPTION("Glue layer for SmartMediaCard on Toshiba RBTX4925");
-406
drivers/mtd/nand/tx4938ndfmc.c
···11-/*22- * drivers/mtd/nand/tx4938ndfmc.c33- *44- * Overview:55- * This is a device driver for the NAND flash device connected to66- * TX4938 internal NAND Memory Controller.77- * TX4938 NDFMC is almost same as TX4925 NDFMC, but register size are 64 bit.88- *99- * Author: source@mvista.com1010- *1111- * Based on spia.c by Steven J. Hill1212- *1313- * $Id: tx4938ndfmc.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $1414- *1515- * Copyright (C) 2000-2001 Toshiba Corporation 1616- *1717- * 2003 (c) MontaVista Software, Inc. This file is licensed under the1818- * terms of the GNU General Public License version 2. This program is1919- * licensed "as is" without any warranty of any kind, whether express2020- * or implied.2121- */2222-#include <linux/config.h>2323-#include <linux/slab.h>2424-#include <linux/init.h>2525-#include <linux/module.h>2626-#include <linux/mtd/mtd.h>2727-#include <linux/mtd/nand.h>2828-#include <linux/mtd/nand_ecc.h>2929-#include <linux/mtd/partitions.h>3030-#include <asm/io.h>3131-#include <asm/bootinfo.h>3232-#include <linux/delay.h>3333-#include <asm/tx4938/rbtx4938.h>3434-3535-extern struct nand_oobinfo jffs2_oobinfo;3636-3737-/*3838- * MTD structure for TX4938 NDFMC3939- */4040-static struct mtd_info *tx4938ndfmc_mtd;4141-4242-/*4343- * Define partitions for flash device4444- */4545-#define flush_wb() (void)tx4938_ndfmcptr->mcr;4646-4747-#define NUM_PARTITIONS 34848-#define NUMBER_OF_CIS_BLOCKS 244949-#define SIZE_OF_BLOCK 0x000040005050-#define NUMBER_OF_BLOCK_PER_ZONE 10245151-#define SIZE_OF_ZONE (NUMBER_OF_BLOCK_PER_ZONE * SIZE_OF_BLOCK)5252-#ifndef CONFIG_MTD_CMDLINE_PARTS5353-/*5454- * You can use the following sample of MTD partitions 5555- * on the NAND Flash Memory 32MB or more.5656- *5757- * The following figure shows the image of the sample partition on5858- * the 32MB NAND Flash Memory. 5959- *6060- * Block No.6161- * 0 +-----------------------------+ ------6262- * | CIS | ^6363- * 24 +-----------------------------+ |6464- * | kernel image | | Zone 06565- * | | |6666- * +-----------------------------+ |6767- * 1023 | unused area | v6868- * +-----------------------------+ ------6969- * 1024 | JFFS2 | ^7070- * | | |7171- * | | | Zone 17272- * | | |7373- * | | |7474- * | | v7575- * 2047 +-----------------------------+ ------7676- *7777- */7878-static struct mtd_partition partition_info[NUM_PARTITIONS] = {7979- {8080- .name = "RBTX4938 CIS Area",8181- .offset = 0,8282- .size = (NUMBER_OF_CIS_BLOCKS * SIZE_OF_BLOCK),8383- .mask_flags = MTD_WRITEABLE /* This partition is NOT writable */8484- },8585- {8686- .name = "RBTX4938 kernel image",8787- .offset = MTDPART_OFS_APPEND,8888- .size = 8 * 0x00100000, /* 8MB (Depends on size of kernel image) */8989- .mask_flags = MTD_WRITEABLE /* This partition is NOT writable */9090- },9191- {9292- .name = "Root FS (JFFS2)",9393- .offset = (0 + SIZE_OF_ZONE), /* start address of next zone */9494- .size = MTDPART_SIZ_FULL9595- },9696-};9797-#endif9898-9999-static void tx4938ndfmc_hwcontrol(struct mtd_info *mtd, int cmd)100100-{101101- switch (cmd) {102102- case NAND_CTL_SETCLE:103103- tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CLE;104104- break;105105- case NAND_CTL_CLRCLE:106106- tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CLE;107107- break;108108- case NAND_CTL_SETALE:109109- tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_ALE;110110- break;111111- case NAND_CTL_CLRALE:112112- tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_ALE;113113- break;114114- /* TX4938_NDFMCR_CE bit is 0:high 1:low */115115- case NAND_CTL_SETNCE:116116- tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CE;117117- break;118118- case NAND_CTL_CLRNCE:119119- tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CE;120120- break;121121- case NAND_CTL_SETWP:122122- tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_WE;123123- break;124124- case NAND_CTL_CLRWP:125125- tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_WE;126126- break;127127- }128128-}129129-static int tx4938ndfmc_dev_ready(struct mtd_info *mtd)130130-{131131- flush_wb();132132- return !(tx4938_ndfmcptr->sr & TX4938_NDFSR_BUSY);133133-}134134-static void tx4938ndfmc_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)135135-{136136- u32 mcr = tx4938_ndfmcptr->mcr;137137- mcr &= ~TX4938_NDFMCR_ECC_ALL;138138- tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF;139139- tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_READ;140140- ecc_code[1] = tx4938_ndfmcptr->dtr;141141- ecc_code[0] = tx4938_ndfmcptr->dtr;142142- ecc_code[2] = tx4938_ndfmcptr->dtr;143143- tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF;144144-}145145-static void tx4938ndfmc_enable_hwecc(struct mtd_info *mtd, int mode)146146-{147147- u32 mcr = tx4938_ndfmcptr->mcr;148148- mcr &= ~TX4938_NDFMCR_ECC_ALL;149149- tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_RESET;150150- tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF;151151- tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_ON;152152-}153153-154154-static u_char tx4938ndfmc_nand_read_byte(struct mtd_info *mtd)155155-{156156- struct nand_chip *this = mtd->priv;157157- return tx4938_read_nfmc(this->IO_ADDR_R);158158-}159159-160160-static void tx4938ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte)161161-{162162- struct nand_chip *this = mtd->priv;163163- tx4938_write_nfmc(byte, this->IO_ADDR_W);164164-}165165-166166-static void tx4938ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)167167-{168168- int i;169169- struct nand_chip *this = mtd->priv;170170-171171- for (i=0; i<len; i++)172172- tx4938_write_nfmc(buf[i], this->IO_ADDR_W);173173-}174174-175175-static void tx4938ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)176176-{177177- int i;178178- struct nand_chip *this = mtd->priv;179179-180180- for (i=0; i<len; i++)181181- buf[i] = tx4938_read_nfmc(this->IO_ADDR_R);182182-}183183-184184-static int tx4938ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)185185-{186186- int i;187187- struct nand_chip *this = mtd->priv;188188-189189- for (i=0; i<len; i++)190190- if (buf[i] != tx4938_read_nfmc(this->IO_ADDR_R))191191- return -EFAULT;192192-193193- return 0;194194-}195195-196196-/*197197- * Send command to NAND device198198- */199199-static void tx4938ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)200200-{201201- register struct nand_chip *this = mtd->priv;202202-203203- /* Begin command latch cycle */204204- this->hwcontrol(mtd, NAND_CTL_SETCLE);205205- /*206206- * Write out the command to the device.207207- */208208- if (command == NAND_CMD_SEQIN) {209209- int readcmd;210210-211211- if (column >= mtd->oobblock) {212212- /* OOB area */213213- column -= mtd->oobblock;214214- readcmd = NAND_CMD_READOOB;215215- } else if (column < 256) {216216- /* First 256 bytes --> READ0 */217217- readcmd = NAND_CMD_READ0;218218- } else {219219- column -= 256;220220- readcmd = NAND_CMD_READ1;221221- }222222- this->write_byte(mtd, readcmd);223223- }224224- this->write_byte(mtd, command);225225-226226- /* Set ALE and clear CLE to start address cycle */227227- this->hwcontrol(mtd, NAND_CTL_CLRCLE);228228-229229- if (column != -1 || page_addr != -1) {230230- this->hwcontrol(mtd, NAND_CTL_SETALE);231231-232232- /* Serially input address */233233- if (column != -1)234234- this->write_byte(mtd, column);235235- if (page_addr != -1) {236236- this->write_byte(mtd, (unsigned char) (page_addr & 0xff));237237- this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));238238- /* One more address cycle for higher density devices */239239- if (mtd->size & 0x0c000000) 240240- this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));241241- }242242- /* Latch in address */243243- this->hwcontrol(mtd, NAND_CTL_CLRALE);244244- }245245-246246- /* 247247- * program and erase have their own busy handlers 248248- * status and sequential in needs no delay249249- */250250- switch (command) {251251-252252- case NAND_CMD_PAGEPROG:253253- /* Turn off WE */254254- this->hwcontrol (mtd, NAND_CTL_CLRWP);255255- return;256256-257257- case NAND_CMD_SEQIN:258258- /* Turn on WE */259259- this->hwcontrol (mtd, NAND_CTL_SETWP);260260- return;261261-262262- case NAND_CMD_ERASE1:263263- case NAND_CMD_ERASE2:264264- case NAND_CMD_STATUS:265265- return;266266-267267- case NAND_CMD_RESET:268268- if (this->dev_ready) 269269- break;270270- this->hwcontrol(mtd, NAND_CTL_SETCLE);271271- this->write_byte(mtd, NAND_CMD_STATUS);272272- this->hwcontrol(mtd, NAND_CTL_CLRCLE);273273- while ( !(this->read_byte(mtd) & 0x40));274274- return;275275-276276- /* This applies to read commands */ 277277- default:278278- /* 279279- * If we don't have access to the busy pin, we apply the given280280- * command delay281281- */282282- if (!this->dev_ready) {283283- udelay (this->chip_delay);284284- return;285285- } 286286- }287287-288288- /* wait until command is processed */289289- while (!this->dev_ready(mtd));290290-}291291-292292-#ifdef CONFIG_MTD_CMDLINE_PARTS293293-extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *);294294-#endif295295-/*296296- * Main initialization routine297297- */298298-int __init tx4938ndfmc_init (void)299299-{300300- struct nand_chip *this;301301- int bsprt = 0, hold = 0xf, spw = 0xf;302302- int protected = 0;303303-304304- if ((*rbtx4938_piosel_ptr & 0x0c) != 0x08) {305305- printk("TX4938 NDFMC: disabled by IOC PIOSEL\n");306306- return -ENODEV;307307- }308308- bsprt = 1;309309- hold = 2;310310- spw = 9 - 1; /* 8 GBUSCLK = 80ns (@ GBUSCLK 100MHz) */311311-312312- if ((tx4938_ccfgptr->pcfg &313313- (TX4938_PCFG_ATA_SEL|TX4938_PCFG_ISA_SEL|TX4938_PCFG_NDF_SEL))314314- != TX4938_PCFG_NDF_SEL) {315315- printk("TX4938 NDFMC: disabled by PCFG.\n");316316- return -ENODEV;317317- }318318-319319- /* reset NDFMC */320320- tx4938_ndfmcptr->rstr |= TX4938_NDFRSTR_RST;321321- while (tx4938_ndfmcptr->rstr & TX4938_NDFRSTR_RST)322322- ;323323- /* setup BusSeparete, Hold Time, Strobe Pulse Width */324324- tx4938_ndfmcptr->mcr = bsprt ? TX4938_NDFMCR_BSPRT : 0;325325- tx4938_ndfmcptr->spr = hold << 4 | spw;326326-327327- /* Allocate memory for MTD device structure and private data */328328- tx4938ndfmc_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),329329- GFP_KERNEL);330330- if (!tx4938ndfmc_mtd) {331331- printk ("Unable to allocate TX4938 NDFMC MTD device structure.\n");332332- return -ENOMEM;333333- }334334-335335- /* Get pointer to private data */336336- this = (struct nand_chip *) (&tx4938ndfmc_mtd[1]);337337-338338- /* Initialize structures */339339- memset((char *) tx4938ndfmc_mtd, 0, sizeof(struct mtd_info));340340- memset((char *) this, 0, sizeof(struct nand_chip));341341-342342- /* Link the private data with the MTD structure */343343- tx4938ndfmc_mtd->priv = this;344344-345345- /* Set address of NAND IO lines */346346- this->IO_ADDR_R = (unsigned long)&tx4938_ndfmcptr->dtr;347347- this->IO_ADDR_W = (unsigned long)&tx4938_ndfmcptr->dtr;348348- this->hwcontrol = tx4938ndfmc_hwcontrol;349349- this->dev_ready = tx4938ndfmc_dev_ready;350350- this->calculate_ecc = tx4938ndfmc_calculate_ecc;351351- this->correct_data = nand_correct_data;352352- this->enable_hwecc = tx4938ndfmc_enable_hwecc;353353- this->eccmode = NAND_ECC_HW3_256;354354- this->chip_delay = 100;355355- this->read_byte = tx4938ndfmc_nand_read_byte;356356- this->write_byte = tx4938ndfmc_nand_write_byte;357357- this->cmdfunc = tx4938ndfmc_nand_command;358358- this->write_buf = tx4938ndfmc_nand_write_buf;359359- this->read_buf = tx4938ndfmc_nand_read_buf;360360- this->verify_buf = tx4938ndfmc_nand_verify_buf;361361-362362- /* Scan to find existance of the device */363363- if (nand_scan (tx4938ndfmc_mtd, 1)) {364364- kfree (tx4938ndfmc_mtd);365365- return -ENXIO;366366- }367367-368368- if (protected) {369369- printk(KERN_INFO "TX4938 NDFMC: write protected.\n");370370- tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE);371371- }372372-373373-#ifdef CONFIG_MTD_CMDLINE_PARTS374374- {375375- int mtd_parts_nb = 0;376376- struct mtd_partition *mtd_parts = 0;377377- mtd_parts_nb = parse_cmdline_partitions(tx4938ndfmc_mtd, &mtd_parts, "tx4938ndfmc");378378- if (mtd_parts_nb > 0)379379- add_mtd_partitions(tx4938ndfmc_mtd, mtd_parts, mtd_parts_nb);380380- else381381- add_mtd_device(tx4938ndfmc_mtd);382382- }383383-#else384384- add_mtd_partitions(tx4938ndfmc_mtd, partition_info, NUM_PARTITIONS );385385-#endif386386-387387- return 0;388388-}389389-module_init(tx4938ndfmc_init);390390-391391-/*392392- * Clean up routine393393- */394394-static void __exit tx4938ndfmc_cleanup (void)395395-{396396- /* Release resources, unregister device */397397- nand_release (tx4938ndfmc_mtd);398398-399399- /* Free the MTD device structure */400400- kfree (tx4938ndfmc_mtd);401401-}402402-module_exit(tx4938ndfmc_cleanup);403403-404404-MODULE_LICENSE("GPL");405405-MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");406406-MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on TX4938 NDFMC");
+9-17
fs/Kconfig
···10391039 If reporting bugs, please try to have available a full dump of the10401040 messages at debug level 1 while the misbehaviour was occurring.1041104110421042-config JFFS2_FS_NAND10431043- bool "JFFS2 support for NAND flash"10421042+config JFFS2_FS_WRITEBUFFER10431043+ bool "JFFS2 write-buffering support"10441044 depends on JFFS2_FS10451045- default n10451045+ default y10461046 help10471047- This enables the support for NAND flash in JFFS2. NAND is a newer10481048- type of flash chip design than the traditional NOR flash, with10491049- higher density but a handful of characteristics which make it more10501050- interesting for the file system to use.10471047+ This enables the write-buffering support in JFFS2.1051104810521052- Say 'N' unless you have NAND flash.10531053-10541054-config JFFS2_FS_NOR_ECC10551055- bool "JFFS2 support for ECC'd NOR flash (EXPERIMENTAL)"10561056- depends on JFFS2_FS && EXPERIMENTAL10571057- default n10581058- help10591059- This enables the experimental support for NOR flash with transparent10601060- ECC for JFFS2. This type of flash chip is not common, however it is10611061- available from ST Microelectronics.10491049+ This functionality is required to support JFFS2 on the following10501050+ types of flash devices:10511051+ - NAND flash10521052+ - NOR flash with transparent ECC10531053+ - DataFlash1062105410631055config JFFS2_COMPRESSION_OPTIONS10641056 bool "Advanced compression options for JFFS2"
···11- $Id: README.Locking,v 1.9 2004/11/20 10:35:40 dwmw2 Exp $11+ $Id: README.Locking,v 1.12 2005/04/13 13:22:35 dwmw2 Exp $2233 JFFS2 LOCKING DOCUMENTATION44 ---------------------------···107107in-core jffs2_inode_cache objects (each inode in JFFS2 has the108108correspondent jffs2_inode_cache object). So, the inocache_lock109109has to be locked while walking the c->inocache_list hash buckets.110110+111111+This spinlock also covers allocation of new inode numbers, which is112112+currently just '++->highest_ino++', but might one day get more complicated113113+if we need to deal with wrapping after 4 milliard inode numbers are used.110114111115Note, the f->sem guarantees that the correspondent jffs2_inode_cache112116will not be removed. So, it is allowed to access it without locking
+8-5
fs/jffs2/background.c
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: background.c,v 1.50 2004/11/16 20:36:10 dwmw2 Exp $1010+ * $Id: background.c,v 1.54 2005/05/20 21:37:12 gleixner Exp $1111 *1212 */1313···3737 if (c->gc_task)3838 BUG();39394040- init_MUTEX_LOCKED(&c->gc_thread_start);4040+ init_completion(&c->gc_thread_start);4141 init_completion(&c->gc_thread_exit);42424343 pid = kernel_thread(jffs2_garbage_collect_thread, c, CLONE_FS|CLONE_FILES);···4848 } else {4949 /* Wait for it... */5050 D1(printk(KERN_DEBUG "JFFS2: Garbage collect thread is pid %d\n", pid));5151- down(&c->gc_thread_start);5151+ wait_for_completion(&c->gc_thread_start);5252 }53535454 return ret;···56565757void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)5858{5959+ int wait = 0;5960 spin_lock(&c->erase_completion_lock);6061 if (c->gc_task) {6162 D1(printk(KERN_DEBUG "jffs2: Killing GC task %d\n", c->gc_task->pid));6263 send_sig(SIGKILL, c->gc_task, 1);6464+ wait = 1;6365 }6466 spin_unlock(&c->erase_completion_lock);6565- wait_for_completion(&c->gc_thread_exit);6767+ if (wait)6868+ wait_for_completion(&c->gc_thread_exit);6669}67706871static int jffs2_garbage_collect_thread(void *_c)···7875 allow_signal(SIGCONT);79768077 c->gc_task = current;8181- up(&c->gc_thread_start);7878+ complete(&c->gc_thread_start);82798380 set_user_nice(current, 10);8481
+6-3
fs/jffs2/build.c
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: build.c,v 1.69 2004/12/16 20:22:18 dmarlin Exp $1010+ * $Id: build.c,v 1.70 2005/02/28 08:21:05 dedekind Exp $1111 *1212 */1313···9797 /* First, scan the medium and build all the inode caches with9898 lists of physical nodes */9999100100- c->flags |= JFFS2_SB_FLAG_MOUNTING;100100+ c->flags |= JFFS2_SB_FLAG_SCANNING;101101 ret = jffs2_scan_medium(c);102102+ c->flags &= ~JFFS2_SB_FLAG_SCANNING;102103 if (ret)103104 goto exit;104105105106 D1(printk(KERN_DEBUG "Scanned flash completely\n"));106107 D2(jffs2_dump_block_lists(c));107108109109+ c->flags |= JFFS2_SB_FLAG_BUILDING;108110 /* Now scan the directory tree, increasing nlink according to every dirent found. */109111 for_each_inode(i, c, ic) {110112 D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino));···118116 cond_resched();119117 }120118 }121121- c->flags &= ~JFFS2_SB_FLAG_MOUNTING;122119123120 D1(printk(KERN_DEBUG "Pass 1 complete\n"));124121···165164 ic->scan_dents = NULL;166165 cond_resched();167166 }167167+ c->flags &= ~JFFS2_SB_FLAG_BUILDING;168168+168169 D1(printk(KERN_DEBUG "Pass 3 complete\n"));169170 D2(jffs2_dump_block_lists(c));170171
+2-2
fs/jffs2/compr_zlib.c
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: compr_zlib.c,v 1.29 2004/11/16 20:36:11 dwmw2 Exp $1010+ * $Id: compr_zlib.c,v 1.31 2005/05/20 19:30:06 gleixner Exp $1111 *1212 */1313···17171818#include <linux/config.h>1919#include <linux/kernel.h>2020+#include <linux/sched.h>2021#include <linux/slab.h>2122#include <linux/zlib.h>2223#include <linux/zutil.h>2323-#include <asm/semaphore.h>2424#include "nodelist.h"2525#include "compr.h"2626
+25-21
fs/jffs2/dir.c
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: dir.c,v 1.84 2004/11/16 20:36:11 dwmw2 Exp $1010+ * $Id: dir.c,v 1.86 2005/07/06 12:13:09 dwmw2 Exp $1111 *1212 */1313···2222#include <linux/time.h>2323#include "nodelist.h"24242525-/* Urgh. Please tell me there's a nicer way of doing these. */2626-#include <linux/version.h>2727-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)2828-typedef int mknod_arg_t;2929-#define NAMEI_COMPAT(x) ((void *)x)3030-#else3131-typedef dev_t mknod_arg_t;3232-#define NAMEI_COMPAT(x) (x)3333-#endif3434-3525static int jffs2_readdir (struct file *, void *, filldir_t);36263727static int jffs2_create (struct inode *,struct dentry *,int,···3343static int jffs2_symlink (struct inode *,struct dentry *,const char *);3444static int jffs2_mkdir (struct inode *,struct dentry *,int);3545static int jffs2_rmdir (struct inode *,struct dentry *);3636-static int jffs2_mknod (struct inode *,struct dentry *,int,mknod_arg_t);4646+static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);3747static int jffs2_rename (struct inode *, struct dentry *,3848 struct inode *, struct dentry *);3949···48584959struct inode_operations jffs2_dir_inode_operations =5060{5151- .create = NAMEI_COMPAT(jffs2_create),5252- .lookup = NAMEI_COMPAT(jffs2_lookup),6161+ .create = jffs2_create,6262+ .lookup = jffs2_lookup,5363 .link = jffs2_link,5464 .unlink = jffs2_unlink,5565 .symlink = jffs2_symlink,···286296 struct jffs2_full_dirent *fd;287297 int namelen;288298 uint32_t alloclen, phys_ofs;289289- int ret;299299+ int ret, targetlen = strlen(target);290300291301 /* FIXME: If you care. We'd need to use frags for the target292302 if it grows much more than this */293293- if (strlen(target) > 254)303303+ if (targetlen > 254)294304 return -EINVAL;295305296306 ri = jffs2_alloc_raw_inode();···304314 * Just the node will do for now, though 305315 */306316 namelen = dentry->d_name.len;307307- ret = jffs2_reserve_space(c, sizeof(*ri) + strlen(target), &phys_ofs, &alloclen, ALLOC_NORMAL);317317+ ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, ALLOC_NORMAL);308318309319 if (ret) {310320 jffs2_free_raw_inode(ri);···323333324334 f = JFFS2_INODE_INFO(inode);325335326326- inode->i_size = strlen(target);336336+ inode->i_size = targetlen;327337 ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size);328338 ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size);329339 ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));330340331341 ri->compr = JFFS2_COMPR_NONE;332332- ri->data_crc = cpu_to_je32(crc32(0, target, strlen(target)));342342+ ri->data_crc = cpu_to_je32(crc32(0, target, targetlen));333343 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));334344335335- fn = jffs2_write_dnode(c, f, ri, target, strlen(target), phys_ofs, ALLOC_NORMAL);345345+ fn = jffs2_write_dnode(c, f, ri, target, targetlen, phys_ofs, ALLOC_NORMAL);336346337347 jffs2_free_raw_inode(ri);338348···343353 jffs2_clear_inode(inode);344354 return PTR_ERR(fn);345355 }356356+357357+ /* We use f->dents field to store the target path. */358358+ f->dents = kmalloc(targetlen + 1, GFP_KERNEL);359359+ if (!f->dents) {360360+ printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);361361+ up(&f->sem);362362+ jffs2_complete_reservation(c);363363+ jffs2_clear_inode(inode);364364+ return -ENOMEM;365365+ }366366+367367+ memcpy(f->dents, target, targetlen + 1);368368+ D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->dents));369369+346370 /* No data here. Only a metadata node, which will be 347371 obsoleted by the first data write348372 */···568564 return ret;569565}570566571571-static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, mknod_arg_t rdev)567567+static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, dev_t rdev)572568{573569 struct jffs2_inode_info *f, *dir_f;574570 struct jffs2_sb_info *c;
+15-9
fs/jffs2/erase.c
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: erase.c,v 1.66 2004/11/16 20:36:11 dwmw2 Exp $1010+ * $Id: erase.c,v 1.76 2005/05/03 15:11:40 dedekind Exp $1111 *1212 */1313···4848#else /* Linux */4949 struct erase_info *instr;50505151+ D1(printk(KERN_DEBUG "jffs2_erase_block(): erase block %#x (range %#x-%#x)\n", jeb->offset, jeb->offset, jeb->offset + c->sector_size));5152 instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);5253 if (!instr) {5354 printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");···234233 continue;235234 } 236235237237- if (((*prev)->flash_offset & ~(c->sector_size -1)) == jeb->offset) {236236+ if (SECTOR_ADDR((*prev)->flash_offset) == jeb->offset) {238237 /* It's in the block we're erasing */239238 struct jffs2_raw_node_ref *this;240239···278277 printk("\n");279278 });280279281281- if (ic->nodes == (void *)ic) {282282- D1(printk(KERN_DEBUG "inocache for ino #%u is all gone now. Freeing\n", ic->ino));280280+ if (ic->nodes == (void *)ic && ic->nlink == 0)283281 jffs2_del_ino_cache(c, ic);284284- jffs2_free_inode_cache(ic);285285- }286282}287283288284static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)···308310 int ret;309311 uint32_t bad_offset;310312311311- if (!jffs2_cleanmarker_oob(c)) {313313+ if ((!jffs2_cleanmarker_oob(c)) && (c->cleanmarker_size > 0)) {312314 marker_ref = jffs2_alloc_raw_node_ref();313315 if (!marker_ref) {314316 printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n");···333335334336 bad_offset = ofs;335337336336- ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf);338338+ ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf);339339+337340 if (ret) {338341 printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret);339342 goto bad;···350351 bad_offset += i;351352 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", datum, bad_offset);352353 bad: 353353- if (!jffs2_cleanmarker_oob(c))354354+ if ((!jffs2_cleanmarker_oob(c)) && (c->cleanmarker_size > 0))354355 jffs2_free_raw_node_ref(marker_ref);355356 kfree(ebuf);356357 bad2:···380381 if (jffs2_write_nand_cleanmarker(c, jeb))381382 goto bad2;382383384384+ jeb->first_node = jeb->last_node = NULL;385385+386386+ jeb->free_size = c->sector_size;387387+ jeb->used_size = 0;388388+ jeb->dirty_size = 0;389389+ jeb->wasted_size = 0;390390+ } else if (c->cleanmarker_size == 0) {383391 jeb->first_node = jeb->last_node = NULL;384392385393 jeb->free_size = c->sector_size;
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: nodemgmt.c,v 1.115 2004/11/22 11:07:21 dwmw2 Exp $1010+ * $Id: nodemgmt.c,v 1.122 2005/05/06 09:30:27 dedekind Exp $1111 *1212 */1313···7575 dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size + c->unchecked_size;7676 if (dirty < c->nospc_dirty_size) {7777 if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) {7878- printk(KERN_NOTICE "jffs2_reserve_space(): Low on dirty space to GC, but it's a deletion. Allowing...\n");7878+ D1(printk(KERN_NOTICE "jffs2_reserve_space(): Low on dirty space to GC, but it's a deletion. Allowing...\n"));7979 break;8080 }8181 D1(printk(KERN_DEBUG "dirty size 0x%08x + unchecked_size 0x%08x < nospc_dirty_size 0x%08x, returning -ENOSPC\n",···9898 avail = c->free_size + c->dirty_size + c->erasing_size + c->unchecked_size;9999 if ( (avail / c->sector_size) <= blocksneeded) {100100 if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) {101101- printk(KERN_NOTICE "jffs2_reserve_space(): Low on possibly available space, but it's a deletion. Allowing...\n");101101+ D1(printk(KERN_NOTICE "jffs2_reserve_space(): Low on possibly available space, but it's a deletion. Allowing...\n"));102102 break;103103 }104104···308308309309 D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len));310310#if 1311311- if (jeb != c->nextblock || (ref_offset(new)) != jeb->offset + (c->sector_size - jeb->free_size)) {311311+ /* we could get some obsolete nodes after nextblock was refiled312312+ in wbuf.c */313313+ if ((c->nextblock || !ref_obsolete(new))314314+ &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) {312315 printk(KERN_WARNING "argh. node added in wrong place\n");313316 jffs2_free_raw_node_ref(new);314317 return -EINVAL;···335332 c->used_size += len;336333 }337334338338- if (!jeb->free_size && !jeb->dirty_size) {335335+ if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {339336 /* If it lives on the dirty_list, jffs2_reserve_space will put it there */340337 D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",341338 jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size));···403400 jeb = &c->blocks[blocknr];404401405402 if (jffs2_can_mark_obsolete(c) && !jffs2_is_readonly(c) &&406406- !(c->flags & JFFS2_SB_FLAG_MOUNTING)) {403403+ !(c->flags & (JFFS2_SB_FLAG_SCANNING | JFFS2_SB_FLAG_BUILDING))) {407404 /* Hm. This may confuse static lock analysis. If any of the above 408405 three conditions is false, we're going to return from this 409406 function without actually obliterating any nodes or freeing···437434438435 // Take care, that wasted size is taken into concern439436 if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref_totlen(c, jeb, ref))) && jeb != c->nextblock) {440440- D1(printk("Dirtying\n"));437437+ D1(printk(KERN_DEBUG "Dirtying\n"));441438 addedsize = ref_totlen(c, jeb, ref);442439 jeb->dirty_size += ref_totlen(c, jeb, ref);443440 c->dirty_size += ref_totlen(c, jeb, ref);···459456 }460457 }461458 } else {462462- D1(printk("Wasting\n"));459459+ D1(printk(KERN_DEBUG "Wasting\n"));463460 addedsize = 0;464461 jeb->wasted_size += ref_totlen(c, jeb, ref);465462 c->wasted_size += ref_totlen(c, jeb, ref); ···470467471468 D1(ACCT_PARANOIA_CHECK(jeb));472469473473- if (c->flags & JFFS2_SB_FLAG_MOUNTING) {474474- /* Mount in progress. Don't muck about with the block470470+ if (c->flags & JFFS2_SB_FLAG_SCANNING) {471471+ /* Flash scanning is in progress. Don't muck about with the block475472 lists because they're not ready yet, and don't actually476473 obliterate nodes that look obsolete. If they weren't 477474 marked obsolete on the flash at the time they _became_···530527531528 spin_unlock(&c->erase_completion_lock);532529533533- if (!jffs2_can_mark_obsolete(c) || jffs2_is_readonly(c)) {530530+ if (!jffs2_can_mark_obsolete(c) || jffs2_is_readonly(c) ||531531+ (c->flags & JFFS2_SB_FLAG_BUILDING)) {534532 /* We didn't lock the erase_free_sem */535533 return;536534 }···594590 *p = ref->next_in_ino;595591 ref->next_in_ino = NULL;596592597597- if (ic->nodes == (void *)ic) {598598- D1(printk(KERN_DEBUG "inocache for ino #%u is all gone now. Freeing\n", ic->ino));593593+ if (ic->nodes == (void *)ic && ic->nlink == 0)599594 jffs2_del_ino_cache(c, ic);600600- jffs2_free_inode_cache(ic);601601- }602595603596 spin_unlock(&c->erase_completion_lock);604597 }
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: read.c,v 1.38 2004/11/16 20:36:12 dwmw2 Exp $1010+ * $Id: read.c,v 1.39 2005/03/01 10:34:03 dedekind Exp $1111 *1212 */1313···214214 return 0;215215}216216217217-/* Core function to read symlink target. */218218-char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f)219219-{220220- char *buf;221221- int ret;222222-223223- down(&f->sem);224224-225225- if (!f->metadata) {226226- printk(KERN_NOTICE "No metadata for symlink inode #%u\n", f->inocache->ino);227227- up(&f->sem);228228- return ERR_PTR(-EINVAL);229229- }230230- buf = kmalloc(f->metadata->size+1, GFP_USER);231231- if (!buf) {232232- up(&f->sem);233233- return ERR_PTR(-ENOMEM);234234- }235235- buf[f->metadata->size]=0;236236-237237- ret = jffs2_read_dnode(c, f, f->metadata, buf, 0, f->metadata->size);238238-239239- up(&f->sem);240240-241241- if (ret) {242242- kfree(buf);243243- return ERR_PTR(ret);244244- }245245- return buf;246246-}
+85-11
fs/jffs2/readinode.c
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: readinode.c,v 1.117 2004/11/20 18:06:54 dwmw2 Exp $1010+ * $Id: readinode.c,v 1.120 2005/07/05 21:03:07 dwmw2 Exp $1111 *1212 */1313···500500 struct jffs2_inode_info *f,501501 struct jffs2_raw_inode *latest_node)502502{503503- struct jffs2_tmp_dnode_info *tn_list, *tn;503503+ struct jffs2_tmp_dnode_info *tn = NULL;504504+ struct rb_root tn_list;505505+ struct rb_node *rb, *repl_rb;504506 struct jffs2_full_dirent *fd_list;505507 struct jffs2_full_dnode *fn = NULL;506508 uint32_t crc;···524522 }525523 f->dents = fd_list;526524527527- while (tn_list) {528528- tn = tn_list;525525+ rb = rb_first(&tn_list);529526527527+ while (rb) {528528+ tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb);530529 fn = tn->fn;531530532531 if (f->metadata) {···559556 mdata_ver = tn->version;560557 }561558 next_tn:562562- tn_list = tn->next;559559+ BUG_ON(rb->rb_left);560560+ repl_rb = NULL;561561+ if (rb->rb_parent && rb->rb_parent->rb_left == rb) {562562+ /* We were then left-hand child of our parent. We need563563+ to move our own right-hand child into our place. */564564+ repl_rb = rb->rb_right;565565+ if (repl_rb)566566+ repl_rb->rb_parent = rb->rb_parent;567567+ } else568568+ repl_rb = NULL;569569+570570+ rb = rb_next(rb);571571+572572+ /* Remove the spent tn from the tree; don't bother rebalancing573573+ but put our right-hand child in our own place. */574574+ if (tn->rb.rb_parent) {575575+ if (tn->rb.rb_parent->rb_left == &tn->rb)576576+ tn->rb.rb_parent->rb_left = repl_rb;577577+ else if (tn->rb.rb_parent->rb_right == &tn->rb)578578+ tn->rb.rb_parent->rb_right = repl_rb;579579+ else BUG();580580+ } else if (tn->rb.rb_right)581581+ tn->rb.rb_right->rb_parent = NULL;582582+563583 jffs2_free_tmp_dnode_info(tn);564584 }565585 D1(jffs2_sanitycheck_fragtree(f));···649623 case. */650624 if (!je32_to_cpu(latest_node->isize))651625 latest_node->isize = latest_node->dsize;626626+627627+ if (f->inocache->state != INO_STATE_CHECKING) {628628+ /* Symlink's inode data is the target path. Read it and629629+ * keep in RAM to facilitate quick follow symlink operation.630630+ * We use f->dents field to store the target path, which631631+ * is somewhat ugly. */632632+ f->dents = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);633633+ if (!f->dents) {634634+ printk(KERN_WARNING "Can't allocate %d bytes of memory "635635+ "for the symlink target path cache\n",636636+ je32_to_cpu(latest_node->csize));637637+ up(&f->sem);638638+ jffs2_do_clear_inode(c, f);639639+ return -ENOMEM;640640+ }641641+642642+ ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node),643643+ je32_to_cpu(latest_node->csize), &retlen, (char *)f->dents);644644+645645+ if (ret || retlen != je32_to_cpu(latest_node->csize)) {646646+ if (retlen != je32_to_cpu(latest_node->csize))647647+ ret = -EIO;648648+ kfree(f->dents);649649+ f->dents = NULL;650650+ up(&f->sem);651651+ jffs2_do_clear_inode(c, f);652652+ return -ret;653653+ }654654+655655+ ((char *)f->dents)[je32_to_cpu(latest_node->csize)] = '\0';656656+ D1(printk(KERN_DEBUG "jffs2_do_read_inode(): symlink's target '%s' cached\n",657657+ (char *)f->dents));658658+ }659659+652660 /* fall through... */653661654662 case S_IFBLK:···732672 down(&f->sem);733673 deleted = f->inocache && !f->inocache->nlink;734674675675+ if (f->inocache && f->inocache->state != INO_STATE_CHECKING)676676+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);677677+735678 if (f->metadata) {736679 if (deleted)737680 jffs2_mark_node_obsolete(c, f->metadata->raw);···743680744681 jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);745682746746- fds = f->dents;683683+ /* For symlink inodes we us f->dents to store the target path name */684684+ if (S_ISLNK(OFNI_EDONI_2SFFJ(f)->i_mode)) {685685+ if (f->dents) {686686+ kfree(f->dents);687687+ f->dents = NULL;688688+ }689689+ } else {690690+ fds = f->dents;747691748748- while(fds) {749749- fd = fds;750750- fds = fd->next;751751- jffs2_free_full_dirent(fd);692692+ while(fds) {693693+ fd = fds;694694+ fds = fd->next;695695+ jffs2_free_full_dirent(fd);696696+ }752697 }753698754754- if (f->inocache && f->inocache->state != INO_STATE_CHECKING)699699+ if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {755700 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);701701+ if (f->inocache->nodes == (void *)f->inocache)702702+ jffs2_del_ino_cache(c, f->inocache);703703+ }756704757705 up(&f->sem);758706}
+25-14
fs/jffs2/scan.c
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: scan.c,v 1.115 2004/11/17 12:59:08 dedekind Exp $1010+ * $Id: scan.c,v 1.119 2005/02/17 17:51:13 dedekind Exp $1111 *1212 */1313#include <linux/kernel.h>···1919#include <linux/compiler.h>2020#include "nodelist.h"21212222-#define EMPTY_SCAN_SIZE 10242222+#define DEFAULT_EMPTY_SCAN_SIZE 102423232424#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \2525 c->free_size -= _x; c->dirty_size += _x; \···6868static inline int min_free(struct jffs2_sb_info *c)6969{7070 uint32_t min = 2 * sizeof(struct jffs2_raw_inode);7171-#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC7171+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER7272 if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize)7373 return c->wbuf_pagesize;7474#endif7575 return min;76767777}7878+7979+static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size) {8080+ if (sector_size < DEFAULT_EMPTY_SCAN_SIZE)8181+ return sector_size;8282+ else8383+ return DEFAULT_EMPTY_SCAN_SIZE;8484+}8585+7886int jffs2_scan_medium(struct jffs2_sb_info *c)7987{8088 int i, ret;···228220 c->dirty_size -= c->nextblock->dirty_size;229221 c->nextblock->dirty_size = 0;230222 }231231-#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC223223+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER232224 if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) {233225 /* If we're going to start writing into a block which already 234226 contains data, and the end of the data isn't page-aligned,···294286 uint32_t hdr_crc, buf_ofs, buf_len;295287 int err;296288 int noise = 0;297297-#ifdef CONFIG_JFFS2_FS_NAND289289+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER298290 int cleanmarkerfound = 0;299291#endif300292···303295304296 D1(printk(KERN_DEBUG "jffs2_scan_eraseblock(): Scanning block at 0x%x\n", ofs));305297306306-#ifdef CONFIG_JFFS2_FS_NAND298298+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER307299 if (jffs2_cleanmarker_oob(c)) {308300 int ret = jffs2_check_nand_cleanmarker(c, jeb);309301 D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d\n",ret));···324316 if (!buf_size) {325317 buf_len = c->sector_size;326318 } else {327327- buf_len = EMPTY_SCAN_SIZE;319319+ buf_len = EMPTY_SCAN_SIZE(c->sector_size);328320 err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);329321 if (err)330322 return err;···334326 ofs = 0;335327336328 /* Scan only 4KiB of 0xFF before declaring it's empty */337337- while(ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)329329+ while(ofs < EMPTY_SCAN_SIZE(c->sector_size) && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)338330 ofs += 4;339331340340- if (ofs == EMPTY_SCAN_SIZE) {341341-#ifdef CONFIG_JFFS2_FS_NAND332332+ if (ofs == EMPTY_SCAN_SIZE(c->sector_size)) {333333+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER342334 if (jffs2_cleanmarker_oob(c)) {343335 /* scan oob, take care of cleanmarker */344336 int ret = jffs2_check_oob_empty(c, jeb, cleanmarkerfound);···351343 }352344#endif353345 D1(printk(KERN_DEBUG "Block at 0x%08x is empty (erased)\n", jeb->offset));354354- return BLK_STATE_ALLFF; /* OK to erase if all blocks are like this */346346+ if (c->cleanmarker_size == 0)347347+ return BLK_STATE_CLEANMARKER; /* don't bother with re-erase */348348+ else349349+ return BLK_STATE_ALLFF; /* OK to erase if all blocks are like this */355350 }356351 if (ofs) {357352 D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset,···433422 /* If we're only checking the beginning of a block with a cleanmarker,434423 bail now */435424 if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && 436436- c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_in_ino) {437437- D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE));425425+ c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) {426426+ D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size)));438427 return BLK_STATE_CLEANMARKER;439428 }440429···629618 }630619631620 if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size 632632- && (!jeb->first_node || !jeb->first_node->next_in_ino) )621621+ && (!jeb->first_node || !jeb->first_node->next_phys) )633622 return BLK_STATE_CLEANMARKER;634623635624 /* move blocks with max 4 byte dirty space to cleanlist */
+4-4
fs/jffs2/super.c
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: super.c,v 1.104 2004/11/23 15:37:31 gleixner Exp $1010+ * $Id: super.c,v 1.106 2005/05/18 11:37:25 dedekind Exp $1111 *1212 */1313···270270271271 D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));272272273273- if (!(sb->s_flags & MS_RDONLY))274274- jffs2_stop_garbage_collect_thread(c);275273 down(&c->alloc_sem);276274 jffs2_flush_wbuf_pad(c);277275 up(&c->alloc_sem);···290292static void jffs2_kill_sb(struct super_block *sb)291293{292294 struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);295295+ if (!(sb->s_flags & MS_RDONLY))296296+ jffs2_stop_garbage_collect_thread(c);293297 generic_shutdown_super(sb);294298 put_mtd_device(c->mtd);295299 kfree(c);···309309 int ret;310310311311 printk(KERN_INFO "JFFS2 version 2.2."312312-#ifdef CONFIG_JFFS2_FS_NAND312312+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER313313 " (NAND)"314314#endif315315 " (C) 2001-2003 Red Hat, Inc.\n");
+30-12
fs/jffs2/symlink.c
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: symlink.c,v 1.14 2004/11/16 20:36:12 dwmw2 Exp $1010+ * $Id: symlink.c,v 1.16 2005/03/01 10:50:48 dedekind Exp $1111 *1212 */1313···1919#include "nodelist.h"20202121static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd);2222-static void jffs2_put_link(struct dentry *dentry, struct nameidata *nd);23222423struct inode_operations jffs2_symlink_inode_operations =2524{ 2625 .readlink = generic_readlink,2726 .follow_link = jffs2_follow_link,2828- .put_link = jffs2_put_link,2927 .setattr = jffs2_setattr3028};31293230static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)3331{3434- unsigned char *buf;3535- buf = jffs2_getlink(JFFS2_SB_INFO(dentry->d_inode->i_sb), JFFS2_INODE_INFO(dentry->d_inode));3636- nd_set_link(nd, buf);3232+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);3333+3434+ /*3535+ * We don't acquire the f->sem mutex here since the only data we3636+ * use is f->dents which in case of the symlink inode points to the3737+ * symlink's target path.3838+ *3939+ * 1. If we are here the inode has already built and f->dents has4040+ * to point to the target path.4141+ * 2. Nobody uses f->dents (if the inode is symlink's inode). The4242+ * exception is inode freeing function which frees f->dents. But4343+ * it can't be called while we are here and before VFS has4444+ * stopped using our f->dents string which we provide by means of4545+ * nd_set_link() call.4646+ */4747+4848+ if (!f->dents) {4949+ printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n");5050+ return -EIO;5151+ }5252+ D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents));5353+5454+ nd_set_link(nd, (char *)f->dents);5555+5656+ /*5757+ * We unlock the f->sem mutex but VFS will use the f->dents string. This is safe5858+ * since the only way that may cause f->dents to be changed is iput() operation.5959+ * But VFS will not use f->dents after iput() has been called.6060+ */3761 return 0;3862}39634040-static void jffs2_put_link(struct dentry *dentry, struct nameidata *nd)4141-{4242- char *s = nd_get_link(nd);4343- if (!IS_ERR(s))4444- kfree(s);4545-}
+108-56
fs/jffs2/wbuf.c
···99 *1010 * For licensing information, see the file 'LICENCE' in this directory.1111 *1212- * $Id: wbuf.c,v 1.82 2004/11/20 22:08:31 dwmw2 Exp $1212+ * $Id: wbuf.c,v 1.92 2005/04/05 12:51:54 dedekind Exp $1313 *1414 */1515···8383 struct jffs2_inodirty *new;84848585 /* Mark the superblock dirty so that kupdated will flush... */8686- OFNI_BS_2SFFJ(c)->s_dirt = 1;8686+ jffs2_erase_pending_trigger(c);87878888 if (jffs2_wbuf_pending_for_ino(c, ino))8989 return;···130130 }131131}132132133133-static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)133133+#define REFILE_NOTEMPTY 0134134+#define REFILE_ANYWAY 1135135+136136+static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int allow_empty)134137{135138 D1(printk("About to refile bad block at %08x\n", jeb->offset));136139···147144 D1(printk("Refiling block at %08x to bad_used_list\n", jeb->offset));148145 list_add(&jeb->list, &c->bad_used_list);149146 } else {150150- BUG();147147+ BUG_ON(allow_empty == REFILE_NOTEMPTY);151148 /* It has to have had some nodes or we couldn't be here */152149 D1(printk("Refiling block at %08x to erase_pending_list\n", jeb->offset));153150 list_add(&jeb->list, &c->erase_pending_list);···182179183180 jeb = &c->blocks[c->wbuf_ofs / c->sector_size];184181185185- jffs2_block_refile(c, jeb);182182+ jffs2_block_refile(c, jeb, REFILE_NOTEMPTY);186183187184 /* Find the first node to be recovered, by skipping over every188185 node which ends before the wbuf starts, or which is obsolete. */···267264 ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len);268265 if (ret) {269266 printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n");270270- if (buf)271271- kfree(buf);267267+ kfree(buf);272268 return;273269 }274270 if (end-start >= c->wbuf_pagesize) {275275- /* Need to do another write immediately. This, btw,276276- means that we'll be writing from 'buf' and not from277277- the wbuf. Since if we're writing from the wbuf there278278- won't be more than a wbuf full of data, now will279279- there? :) */280280-271271+ /* Need to do another write immediately, but it's possible272272+ that this is just because the wbuf itself is completely273273+ full, and there's nothing earlier read back from the 274274+ flash. Hence 'buf' isn't necessarily what we're writing 275275+ from. */276276+ unsigned char *rewrite_buf = buf?:c->wbuf;281277 uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize);282278283279 D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n",···294292#endif295293 if (jffs2_cleanmarker_oob(c))296294 ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen,297297- buf, NULL, c->oobinfo);295295+ rewrite_buf, NULL, c->oobinfo);298296 else299299- ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, buf);297297+ ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, rewrite_buf);300298301299 if (ret || retlen != towrite) {302300 /* Argh. We tried. Really we did. */···323321324322 c->wbuf_len = (end - start) - towrite;325323 c->wbuf_ofs = ofs + towrite;326326- memcpy(c->wbuf, buf + towrite, c->wbuf_len);324324+ memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len);327325 /* Don't muck about with c->wbuf_inodes. False positives are harmless. */328328-329329- kfree(buf);326326+ if (buf)327327+ kfree(buf);330328 } else {331329 /* OK, now we're left with the dregs in whichever buffer we're using */332330 if (buf) {···415413 int ret;416414 size_t retlen;417415418418- /* Nothing to do if not NAND flash. In particular, we shouldn't416416+ /* Nothing to do if not write-buffering the flash. In particular, we shouldn't419417 del_timer() the timer we never initialised. */420420- if (jffs2_can_mark_obsolete(c))418418+ if (!jffs2_is_writebuffered(c))421419 return 0;422420423421 if (!down_trylock(&c->alloc_sem)) {···426424 BUG();427425 }428426429429- if(!c->wbuf || !c->wbuf_len)427427+ if (!c->wbuf_len) /* already checked c->wbuf above */430428 return 0;431429432430 /* claim remaining space on the page···435433 if we have a switch to next page, we will not have436434 enough remaining space for this. 437435 */438438- if (pad) {436436+ if (pad && !jffs2_dataflash(c)) {439437 c->wbuf_len = PAD(c->wbuf_len);440438441439 /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR···486484 spin_lock(&c->erase_completion_lock);487485488486 /* Adjust free size of the block if we padded. */489489- if (pad) {487487+ if (pad && !jffs2_dataflash(c)) {490488 struct jffs2_eraseblock *jeb;491489492490 jeb = &c->blocks[c->wbuf_ofs / c->sector_size];···534532535533 D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() called for ino #%u...\n", ino));536534535535+ if (!c->wbuf)536536+ return 0;537537+537538 down(&c->alloc_sem);538539 if (!jffs2_wbuf_pending_for_ino(c, ino)) {539540 D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino));···552547 D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() padding. Not finished checking\n"));553548 down_write(&c->wbuf_sem);554549 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);550550+ /* retry flushing wbuf in case jffs2_wbuf_recover551551+ left some data in the wbuf */552552+ if (ret)553553+ ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);555554 up_write(&c->wbuf_sem);556555 } else while (old_wbuf_len &&557556 old_wbuf_ofs == c->wbuf_ofs) {···570561 down(&c->alloc_sem);571562 down_write(&c->wbuf_sem);572563 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);564564+ /* retry flushing wbuf in case jffs2_wbuf_recover565565+ left some data in the wbuf */566566+ if (ret)567567+ ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);573568 up_write(&c->wbuf_sem);574569 break;575570 }···591578{592579 int ret;593580581581+ if (!c->wbuf)582582+ return 0;583583+594584 down_write(&c->wbuf_sem);595585 ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);586586+ /* retry - maybe wbuf recover left some data in wbuf. */587587+ if (ret)588588+ ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);596589 up_write(&c->wbuf_sem);597590598591 return ret;599592}600593594594+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER595595+#define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) )596596+#define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) )597597+#else601598#define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) )602599#define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) )600600+#endif601601+603602int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino)604603{605604 struct kvec outvecs[3];···626601 uint32_t outvec_to = to;627602628603 /* If not NAND flash, don't bother */629629- if (!c->wbuf)604604+ if (!jffs2_is_writebuffered(c))630605 return jffs2_flash_direct_writev(c, invecs, count, to, retlen);631606632607 down_write(&c->wbuf_sem);···655630 erase block. Anything else, and you die.656631 New block starts at xxx000c (0-b = block header)657632 */658658- if ( (to & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) {633633+ if (SECTOR_ADDR(to) != SECTOR_ADDR(c->wbuf_ofs)) {659634 /* It's a write to a new block */660635 if (c->wbuf_len) {661636 D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs));···787762788763 if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) {789764 /* At this point we have no problem,790790- c->wbuf is empty. 765765+ c->wbuf is empty. However refile nextblock to avoid766766+ writing again to same address.791767 */792792- *retlen = donelen;768768+ struct jffs2_eraseblock *jeb;769769+770770+ spin_lock(&c->erase_completion_lock);771771+772772+ jeb = &c->blocks[outvec_to / c->sector_size];773773+ jffs2_block_refile(c, jeb, REFILE_ANYWAY);774774+775775+ *retlen = 0;776776+ spin_unlock(&c->erase_completion_lock);793777 goto exit;794778 }795779···853819{854820 struct kvec vecs[1];855821856856- if (jffs2_can_mark_obsolete(c))822822+ if (!jffs2_is_writebuffered(c))857823 return c->mtd->write(c->mtd, ofs, len, retlen, buf);858824859825 vecs[0].iov_base = (unsigned char *) buf;···869835 loff_t orbf = 0, owbf = 0, lwbf = 0;870836 int ret;871837872872- /* Read flash */873873- if (!jffs2_can_mark_obsolete(c)) {874874- down_read(&c->wbuf_sem);875875-876876- if (jffs2_cleanmarker_oob(c))877877- ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo);878878- else879879- ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);880880-881881- if ( (ret == -EBADMSG) && (*retlen == len) ) {882882- printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",883883- len, ofs);884884- /* 885885- * We have the raw data without ECC correction in the buffer, maybe 886886- * we are lucky and all data or parts are correct. We check the node.887887- * If data are corrupted node check will sort it out.888888- * We keep this block, it will fail on write or erase and the we889889- * mark it bad. Or should we do that now? But we should give him a chance.890890- * Maybe we had a system crash or power loss before the ecc write or 891891- * a erase was completed.892892- * So we return success. :)893893- */894894- ret = 0;895895- } 896896- } else838838+ if (!jffs2_is_writebuffered(c))897839 return c->mtd->read(c->mtd, ofs, len, retlen, buf);840840+841841+ /* Read flash */842842+ down_read(&c->wbuf_sem);843843+ if (jffs2_cleanmarker_oob(c))844844+ ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo);845845+ else846846+ ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);847847+848848+ if ( (ret == -EBADMSG) && (*retlen == len) ) {849849+ printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",850850+ len, ofs);851851+ /* 852852+ * We have the raw data without ECC correction in the buffer, maybe 853853+ * we are lucky and all data or parts are correct. We check the node.854854+ * If data are corrupted node check will sort it out.855855+ * We keep this block, it will fail on write or erase and the we856856+ * mark it bad. Or should we do that now? But we should give him a chance.857857+ * Maybe we had a system crash or power loss before the ecc write or 858858+ * a erase was completed.859859+ * So we return success. :)860860+ */861861+ ret = 0;862862+ } 898863899864 /* if no writebuffer available or write buffer empty, return */900865 if (!c->wbuf_pagesize || !c->wbuf_len)901866 goto exit;902867903868 /* if we read in a different block, return */904904- if ( (ofs & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) 869869+ if (SECTOR_ADDR(ofs) != SECTOR_ADDR(c->wbuf_ofs))905870 goto exit;906871907872 if (ofs >= c->wbuf_ofs) {···11941161 kfree(c->wbuf);11951162}1196116311971197-#ifdef CONFIG_JFFS2_FS_NOR_ECC11641164+int jffs2_dataflash_setup(struct jffs2_sb_info *c) {11651165+ c->cleanmarker_size = 0; /* No cleanmarkers needed */11661166+11671167+ /* Initialize write buffer */11681168+ init_rwsem(&c->wbuf_sem);11691169+ c->wbuf_pagesize = c->sector_size;11701170+ c->wbuf_ofs = 0xFFFFFFFF;11711171+11721172+ c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);11731173+ if (!c->wbuf)11741174+ return -ENOMEM;11751175+11761176+ printk(KERN_INFO "JFFS2 write-buffering enabled (%i)\n", c->wbuf_pagesize);11771177+11781178+ return 0;11791179+}11801180+11811181+void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) {11821182+ kfree(c->wbuf);11831183+}11841184+11981185int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) {11991186 /* Cleanmarker is actually larger on the flashes */12001187 c->cleanmarker_size = 16;···12341181void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) {12351182 kfree(c->wbuf);12361183}12371237-#endif
+38-17
fs/jffs2/write.c
···77 *88 * For licensing information, see the file 'LICENCE' in this directory.99 *1010- * $Id: write.c,v 1.87 2004/11/16 20:36:12 dwmw2 Exp $1010+ * $Id: write.c,v 1.92 2005/04/13 13:22:35 dwmw2 Exp $1111 *1212 */1313···3535 f->inocache = ic;3636 f->inocache->nlink = 1;3737 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;3838- f->inocache->ino = ++c->highest_ino;3938 f->inocache->state = INO_STATE_PRESENT;40394141- ri->ino = cpu_to_je32(f->inocache->ino);42404343- D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));4441 jffs2_add_ino_cache(c, f->inocache);4242+ D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));4343+ ri->ino = cpu_to_je32(f->inocache->ino);45444645 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);4746 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);···134135 raw->flash_offset = flash_ofs;135136 raw->__totlen = PAD(sizeof(*ri)+datalen);136137 raw->next_phys = NULL;138138+139139+ if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) {140140+ BUG_ON(!retried);141141+ D1(printk(KERN_DEBUG "jffs2_write_dnode : dnode_version %d, "142142+ "highest version %d -> updating dnode\n", 143143+ je32_to_cpu(ri->version), f->highest_version));144144+ ri->version = cpu_to_je32(++f->highest_version);145145+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));146146+ }137147138148 ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen,139149 (alloc_mode==ALLOC_GC)?0:f->inocache->ino);···287279 raw->flash_offset = flash_ofs;288280 raw->__totlen = PAD(sizeof(*rd)+namelen);289281 raw->next_phys = NULL;282282+283283+ if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) {284284+ BUG_ON(!retried);285285+ D1(printk(KERN_DEBUG "jffs2_write_dirent : dirent_version %d, "286286+ "highest version %d -> updating dirent\n",287287+ je32_to_cpu(rd->version), f->highest_version));288288+ rd->version = cpu_to_je32(++f->highest_version);289289+ fd->version = je32_to_cpu(rd->version);290290+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));291291+ }290292291293 ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen,292294 (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino));···643625644626 down(&dead_f->sem);645627646646- while (dead_f->dents) {647647- /* There can be only deleted ones */648648- fd = dead_f->dents;649649-650650- dead_f->dents = fd->next;651651-652652- if (fd->ino) {653653- printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n",654654- dead_f->inocache->ino, fd->name, fd->ino);655655- } else {656656- D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", fd->name, dead_f->inocache->ino));628628+ if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) {629629+ while (dead_f->dents) {630630+ /* There can be only deleted ones */631631+ fd = dead_f->dents;632632+633633+ dead_f->dents = fd->next;634634+635635+ if (fd->ino) {636636+ printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n",637637+ dead_f->inocache->ino, fd->name, fd->ino);638638+ } else {639639+ D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n",640640+ fd->name, dead_f->inocache->ino));641641+ }642642+ jffs2_mark_node_obsolete(c, fd->raw);643643+ jffs2_free_full_dirent(fd);657644 }658658- jffs2_mark_node_obsolete(c, fd->raw);659659- jffs2_free_full_dirent(fd);660645 }661646662647 dead_f->inocache->nlink--;
+37
include/asm-arm/arch-pxa/mtd-xip.h
···11+/*22+ * MTD primitives for XIP support. Architecture specific functions33+ *44+ * Do not include this file directly. It's included from linux/mtd/xip.h55+ * 66+ * Author: Nicolas Pitre77+ * Created: Nov 2, 200488+ * Copyright: (C) 2004 MontaVista Software, Inc.99+ *1010+ * This program is free software; you can redistribute it and/or modify1111+ * it under the terms of the GNU General Public License version 2 as1212+ * published by the Free Software Foundation.1313+ *1414+ * $Id: xip.h,v 1.2 2004/12/01 15:49:10 nico Exp $1515+ */1616+1717+#ifndef __ARCH_PXA_MTD_XIP_H__1818+#define __ARCH_PXA_MTD_XIP_H__1919+2020+#include <asm/arch/pxa-regs.h>2121+2222+#define xip_irqpending() (ICIP & ICMR)2323+2424+/* we sample OSCR and convert desired delta to usec (1/4 ~= 1000000/3686400) */2525+#define xip_currtime() (OSCR)2626+#define xip_elapsed_since(x) (signed)((OSCR - (x)) / 4)2727+2828+/*2929+ * xip_cpu_idle() is used when waiting for a delay equal or larger than3030+ * the system timer tick period. This should put the CPU into idle mode3131+ * to save power and to be woken up only when some interrupts are pending.3232+ * As above, this should not rely upon standard kernel code.3333+ */3434+3535+#define xip_cpu_idle() asm volatile ("mcr p14, 0, %0, c7, c0, 0" :: "r" (1))3636+3737+#endif /* __ARCH_PXA_MTD_XIP_H__ */
+26
include/asm-arm/arch-sa1100/mtd-xip.h
···11+/*22+ * MTD primitives for XIP support. Architecture specific functions33+ *44+ * Do not include this file directly. It's included from linux/mtd/xip.h55+ * 66+ * Author: Nicolas Pitre77+ * Created: Nov 2, 200488+ * Copyright: (C) 2004 MontaVista Software, Inc.99+ *1010+ * This program is free software; you can redistribute it and/or modify1111+ * it under the terms of the GNU General Public License version 2 as1212+ * published by the Free Software Foundation.1313+ *1414+ * $Id: xip.h,v 1.2 2004/12/01 15:49:10 nico Exp $1515+ */1616+1717+#ifndef __ARCH_SA1100_MTD_XIP_H__1818+#define __ARCH_SA1100_MTD_XIP_H__1919+2020+#define xip_irqpending() (ICIP & ICMR)2121+2222+/* we sample OSCR and convert desired delta to usec (1/4 ~= 1000000/3686400) */2323+#define xip_currtime() (OSCR)2424+#define xip_elapsed_since(x) (signed)((OSCR - (x)) / 4)2525+2626+#endif /* __ARCH_SA1100_MTD_XIP_H__ */
+26
include/asm-arm/mtd-xip.h
···11+/*22+ * MTD primitives for XIP support. Architecture specific functions33+ *44+ * Do not include this file directly. It's included from linux/mtd/xip.h55+ * 66+ * Author: Nicolas Pitre77+ * Created: Nov 2, 200488+ * Copyright: (C) 2004 MontaVista Software, Inc.99+ *1010+ * This program is free software; you can redistribute it and/or modify1111+ * it under the terms of the GNU General Public License version 2 as1212+ * published by the Free Software Foundation.1313+ *1414+ * $Id: xip.h,v 1.2 2004/12/01 15:49:10 nico Exp $1515+ */1616+1717+#ifndef __ARM_MTD_XIP_H__1818+#define __ARM_MTD_XIP_H__1919+2020+#include <asm/hardware.h>2121+#include <asm/arch/mtd-xip.h>2222+2323+/* fill instruction prefetch */2424+#define xip_iprefetch() do { asm volatile (".rep 8; nop; .endr"); } while (0)2525+2626+#endif /* __ARM_MTD_XIP_H__ */
+5-4
include/linux/jffs2_fs_sb.h
···11-/* $Id: jffs2_fs_sb.h,v 1.48 2004/11/20 10:41:12 dwmw2 Exp $ */11+/* $Id: jffs2_fs_sb.h,v 1.52 2005/05/19 16:12:17 gleixner Exp $ */2233#ifndef _JFFS2_FS_SB44#define _JFFS2_FS_SB···1414#include <linux/rwsem.h>15151616#define JFFS2_SB_FLAG_RO 11717-#define JFFS2_SB_FLAG_MOUNTING 21717+#define JFFS2_SB_FLAG_SCANNING 2 /* Flash scanning is in progress */1818+#define JFFS2_SB_FLAG_BUILDING 4 /* File system building is in progress */18191920struct jffs2_inodirty;2021···3231 unsigned int flags;33323433 struct task_struct *gc_task; /* GC task struct */3535- struct semaphore gc_thread_start; /* GC thread start mutex */3434+ struct completion gc_thread_start; /* GC thread start completion */3635 struct completion gc_thread_exit; /* GC thread exit completion port */37363837 struct semaphore alloc_sem; /* Used to protect all the following ···9594 to an obsoleted node. I don't like this. Alternatives welcomed. */9695 struct semaphore erase_free_sem;97969898-#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC9797+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER9998 /* Write-behind buffer for NAND flash */10099 unsigned char *wbuf;101100 uint32_t wbuf_ofs;
+73-12
include/linux/mtd/cfi.h
···1122/* Common Flash Interface structures 33 * See http://support.intel.com/design/flash/technote/index.htm44- * $Id: cfi.h,v 1.50 2004/11/20 12:46:51 dwmw2 Exp $44+ * $Id: cfi.h,v 1.54 2005/06/06 23:04:36 tpoynor Exp $55 */6677#ifndef __MTD_CFI_H__···148148 uint8_t extra[0];149149} __attribute__((packed));150150151151+struct cfi_intelext_otpinfo {152152+ uint32_t ProtRegAddr;153153+ uint16_t FactGroups;154154+ uint8_t FactProtRegSize;155155+ uint16_t UserGroups;156156+ uint8_t UserProtRegSize;157157+} __attribute__((packed));158158+151159struct cfi_intelext_blockinfo {152160 uint16_t NumIdentBlocks;153161 uint16_t BlockSize;···252244 * It looks too long to be inline, but in the common case it should almost all253245 * get optimised away. 254246 */255255-static inline map_word cfi_build_cmd(u_char cmd, struct map_info *map, struct cfi_private *cfi)247247+static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi)256248{257249 map_word val = { {0} };258250 int wordwidth, words_per_bus, chip_mode, chips_per_word;···315307}316308#define CMD(x) cfi_build_cmd((x), map, cfi)317309310310+311311+static inline unsigned char cfi_merge_status(map_word val, struct map_info *map, 312312+ struct cfi_private *cfi)313313+{314314+ int wordwidth, words_per_bus, chip_mode, chips_per_word;315315+ unsigned long onestat, res = 0;316316+ int i;317317+318318+ /* We do it this way to give the compiler a fighting chance 319319+ of optimising away all the crap for 'bankwidth' larger than320320+ an unsigned long, in the common case where that support is321321+ disabled */322322+ if (map_bankwidth_is_large(map)) {323323+ wordwidth = sizeof(unsigned long);324324+ words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1325325+ } else {326326+ wordwidth = map_bankwidth(map);327327+ words_per_bus = 1;328328+ }329329+330330+ chip_mode = map_bankwidth(map) / cfi_interleave(cfi);331331+ chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);332332+333333+ onestat = val.x[0];334334+ /* Or all status words together */335335+ for (i=1; i < words_per_bus; i++) {336336+ onestat |= val.x[i];337337+ }338338+339339+ res = onestat;340340+ switch(chips_per_word) {341341+ default: BUG();342342+#if BITS_PER_LONG >= 64343343+ case 8:344344+ res |= (onestat >> (chip_mode * 32));345345+#endif346346+ case 4:347347+ res |= (onestat >> (chip_mode * 16));348348+ case 2:349349+ res |= (onestat >> (chip_mode * 8));350350+ case 1:351351+ ;352352+ }353353+354354+ /* Last, determine what the bit-pattern should be for a single355355+ device, according to chip mode and endianness... */356356+ switch (chip_mode) {357357+ case 1:358358+ break;359359+ case 2:360360+ res = cfi16_to_cpu(res);361361+ break;362362+ case 4:363363+ res = cfi32_to_cpu(res);364364+ break;365365+ default: BUG();366366+ }367367+ return res;368368+}369369+370370+#define MERGESTATUS(x) cfi_merge_status((x), map, cfi)371371+372372+318373/*319374 * Sends a CFI command to a bank of flash for the given geometry.320375 *···426355 udelay(us);427356 cond_resched();428357 }429429-}430430-431431-static inline void cfi_spin_lock(spinlock_t *mutex)432432-{433433- spin_lock_bh(mutex);434434-}435435-436436-static inline void cfi_spin_unlock(spinlock_t *mutex)437437-{438438- spin_unlock_bh(mutex);439358}440359441360struct cfi_extquery *cfi_read_pri(struct map_info *map, uint16_t adr, uint16_t size,
+4-3
include/linux/mtd/flashchip.h
···66 *77 * (C) 2000 Red Hat. GPLd.88 *99- * $Id: flashchip.h,v 1.15 2004/11/05 22:41:06 nico Exp $99+ * $Id: flashchip.h,v 1.17 2005/03/14 18:27:15 bjd Exp $1010 *1111 */1212···2929 FL_ERASE_SUSPENDED,3030 FL_WRITING,3131 FL_WRITING_TO_BUFFER,3232+ FL_OTP_WRITE,3233 FL_WRITE_SUSPENDING,3334 FL_WRITE_SUSPENDED,3435 FL_PM_SUSPENDED,···6362 flstate_t state;6463 flstate_t oldstate;65646666- int write_suspended:1;6767- int erase_suspended:1;6565+ unsigned int write_suspended:1;6666+ unsigned int erase_suspended:1;6867 unsigned long in_progress_block_addr;69687069 spinlock_t *mutex;
···11/* 22- * $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $22+ * $Id: mtd.h,v 1.59 2005/04/11 10:19:02 gleixner Exp $33 *44 * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.55 *···1818#include <linux/types.h>1919#include <linux/module.h>2020#include <linux/uio.h>2121+#include <linux/notifier.h>21222223#include <linux/mtd/compatmac.h>2324#include <mtd/mtd-abi.h>···70697170 u_int32_t oobblock; // Size of OOB blocks (e.g. 512)7271 u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)7373- u_int32_t oobavail; // Number of bytes in OOB area available for fs 7472 u_int32_t ecctype;7573 u_int32_t eccsize;7674···80808181 // oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO)8282 struct nand_oobinfo oobinfo;8383+ u_int32_t oobavail; // Number of bytes in OOB area available for fs 83848485 /* Data for variable erase regions. If numeraseregions is zero,8586 * it means that the whole device has erasesize as given above. ···114113 * flash devices. The user data is one time programmable but the115114 * factory data is read only. 116115 */117117- int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);118118-116116+ int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);119117 int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);120120-121121- /* This function is not yet implemented */118118+ int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);119119+ int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);122120 int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);121121+ int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);123122124123 /* kvec-based read/write methods. We need these especially for NAND flash,125124 with its limited number of write cycles per erase.···147146 /* Bad block management functions */148147 int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);149148 int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);149149+150150+ struct notifier_block reboot_notifier; /* default mode before reboot */150151151152 void *priv;152153
+45-3
include/linux/mtd/nand.h
···55 * Steven J. Hill <sjhill@realitydiluted.com>66 * Thomas Gleixner <tglx@linutronix.de>77 *88- * $Id: nand.h,v 1.68 2004/11/12 10:40:37 gleixner Exp $88+ * $Id: nand.h,v 1.73 2005/05/31 19:39:17 gleixner Exp $99 *1010 * This program is free software; you can redistribute it and/or modify1111 * it under the terms of the GNU General Public License version 2 as···4848 * 02-08-2004 tglx added option field to nand structure for chip anomalities4949 * 05-25-2004 tglx added bad block table support, ST-MICRO manufacturer id5050 * update of nand_chip structure description5151+ * 01-17-2005 dmarlin added extended commands for AG-AND device and added option 5252+ * for BBT_AUTO_REFRESH.5353+ * 01-20-2005 dmarlin added optional pointer to hardware specific callback for 5454+ * extra error status checks.5155 */5256#ifndef __LINUX_MTD_NAND_H5357#define __LINUX_MTD_NAND_H···119115#define NAND_CMD_READSTART 0x30120116#define NAND_CMD_CACHEDPROG 0x15121117118118+/* Extended commands for AG-AND device */119119+/* 120120+ * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but 121121+ * there is no way to distinguish that from NAND_CMD_READ0122122+ * until the remaining sequence of commands has been completed123123+ * so add a high order bit and mask it off in the command.124124+ */125125+#define NAND_CMD_DEPLETE1 0x100126126+#define NAND_CMD_DEPLETE2 0x38127127+#define NAND_CMD_STATUS_MULTI 0x71128128+#define NAND_CMD_STATUS_ERROR 0x72129129+/* multi-bank error status (banks 0-3) */130130+#define NAND_CMD_STATUS_ERROR0 0x73131131+#define NAND_CMD_STATUS_ERROR1 0x74132132+#define NAND_CMD_STATUS_ERROR2 0x75133133+#define NAND_CMD_STATUS_ERROR3 0x76134134+#define NAND_CMD_STATUS_RESET 0x7f135135+#define NAND_CMD_STATUS_CLEAR 0xff136136+122137/* Status bits */123138#define NAND_STATUS_FAIL 0x01124139#define NAND_STATUS_FAIL_N1 0x02···166143167144/*168145 * Constants for Hardware ECC169169-*/146146+ */170147/* Reset Hardware ECC for read */171148#define NAND_ECC_READ 0172149/* Reset Hardware ECC for write */173150#define NAND_ECC_WRITE 1174151/* Enable Hardware ECC before syndrom is read back from flash */175152#define NAND_ECC_READSYN 2153153+154154+/* Bit mask for flags passed to do_nand_read_ecc */155155+#define NAND_GET_DEVICE 0x80156156+176157177158/* Option constants for bizarre disfunctionality and real178159* features···197170/* Chip has a array of 4 pages which can be read without198171 * additional ready /busy waits */199172#define NAND_4PAGE_ARRAY 0x00000040 173173+/* Chip requires that BBT is periodically rewritten to prevent174174+ * bits from adjacent blocks from 'leaking' in altering data.175175+ * This happens with the Renesas AG-AND chips, possibly others. */176176+#define BBT_AUTO_REFRESH 0x00000080200177201178/* Options valid for Samsung large page devices */202179#define NAND_SAMSUNG_LP_OPTIONS \···223192 * This can only work if we have the ecc bytes directly behind the 224193 * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */225194#define NAND_HWECC_SYNDROME 0x00020000226226-195195+/* This option skips the bbt scan during initialization. */196196+#define NAND_SKIP_BBTSCAN 0x00040000227197228198/* Options set by nand scan */229199/* Nand scan has allocated oob_buf */···253221 * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices254222 * @lock: protection lock 255223 * @active: the mtd device which holds the controller currently224224+ * @wq: wait queue to sleep on if a NAND operation is in progress225225+ * used instead of the per chip wait queue when a hw controller is available256226 */257227struct nand_hw_control {258228 spinlock_t lock;259229 struct nand_chip *active;230230+ wait_queue_head_t wq;260231};261232262233/**···318283 * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan 319284 * @controller: [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices320285 * @priv: [OPTIONAL] pointer to private chip date286286+ * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks 287287+ * (determine if errors are correctable)321288 */322289323290struct nand_chip {···375338 struct nand_bbt_descr *badblock_pattern;376339 struct nand_hw_control *controller;377340 void *priv;341341+ int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);378342};379343380344/*···387349#define NAND_MFR_NATIONAL 0x8f388350#define NAND_MFR_RENESAS 0x07389351#define NAND_MFR_STMICRO 0x20352352+#define NAND_MFR_HYNIX 0xad390353391354/**392355 * struct nand_flash_dev - NAND Flash Device ID Structure···498459extern int nand_default_bbt (struct mtd_info *mtd);499460extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);500461extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);462462+extern int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,463463+ size_t * retlen, u_char * buf, u_char * oob_buf,464464+ struct nand_oobinfo *oobsel, int flags);501465502466/*503467* Constants for oob configuration
+35
include/linux/mtd/plat-ram.h
···11+/* linux/include/mtd/plat-ram.h22+ *33+ * (c) 2004 Simtec Electronics44+ * http://www.simtec.co.uk/products/SWLINUX/55+ * Ben Dooks <ben@simtec.co.uk>66+ *77+ * Generic platform device based RAM map88+ *99+ * $Id: plat-ram.h,v 1.2 2005/01/24 00:37:40 bjd Exp $1010+ *1111+ * This program is free software; you can redistribute it and/or modify1212+ * it under the terms of the GNU General Public License version 2 as1313+ * published by the Free Software Foundation.1414+ *1515+ */1616+1717+#ifndef __LINUX_MTD_PLATRAM_H1818+#define __LINUX_MTD_PLATRAM_H __FILE__1919+2020+#define PLATRAM_RO (0)2121+#define PLATRAM_RW (1)2222+2323+struct platdata_mtd_ram {2424+ char *mapname;2525+ char **probes;2626+ struct mtd_partition *partitions;2727+ int nr_partitions;2828+ int bankwidth;2929+3030+ /* control callbacks */3131+3232+ void (*set_rw)(struct device *dev, int to);3333+};3434+3535+#endif /* __LINUX_MTD_PLATRAM_H */
+13-18
include/linux/mtd/xip.h
···5858 * returned value is <= the real elapsed time.5959 * note 2: this should be able to cope with a few seconds without6060 * overflowing.6161+ *6262+ * xip_iprefetch()6363+ * 6464+ * Macro to fill instruction prefetch6565+ * e.g. a series of nops: asm volatile (".rep 8; nop; .endr"); 6166 */62676363-#if defined(CONFIG_ARCH_SA1100) || defined(CONFIG_ARCH_PXA)6868+#include <asm/mtd-xip.h>64696565-#include <asm/hardware.h>6666-#ifdef CONFIG_ARCH_PXA6767-#include <asm/arch/pxa-regs.h>6868-#endif6969-7070-#define xip_irqpending() (ICIP & ICMR)7171-7272-/* we sample OSCR and convert desired delta to usec (1/4 ~= 1000000/3686400) */7373-#define xip_currtime() (OSCR)7474-#define xip_elapsed_since(x) (signed)((OSCR - (x)) / 4)7575-7676-#else7070+#ifndef xip_irqpending77717872#warning "missing IRQ and timer primitives for XIP MTD support"7973#warning "some of the XIP MTD support code will be disabled"···79858086#endif81878888+#ifndef xip_iprefetch8989+#define xip_iprefetch() do { } while (0)9090+#endif9191+8292/*8393 * xip_cpu_idle() is used when waiting for a delay equal or larger than8494 * the system timer tick period. This should put the CPU into idle mode8595 * to save power and to be woken up only when some interrupts are pending.8686- * As above, this should not rely upon standard kernel code.9696+ * This should not rely upon standard kernel code.8797 */8888-8989-#if defined(CONFIG_CPU_XSCALE)9090-#define xip_cpu_idle() asm volatile ("mcr p14, 0, %0, c7, c0, 0" :: "r" (1))9191-#else9898+#ifndef xip_cpu_idle9299#define xip_cpu_idle() do { } while (0)93100#endif94101
+18-1
include/mtd/mtd-abi.h
···11/*22- * $Id: mtd-abi.h,v 1.7 2004/11/23 15:37:32 gleixner Exp $22+ * $Id: mtd-abi.h,v 1.11 2005/05/19 16:08:58 gleixner Exp $33 *44 * Portions of MTD ABI definition which are shared by kernel and user space 55 */···2929#define MTD_NORFLASH 33030#define MTD_NANDFLASH 43131#define MTD_PEROM 53232+#define MTD_DATAFLASH 63233#define MTD_OTHER 143334#define MTD_UNKNOWN 153435···6160#define MTD_NANDECC_PLACE 1 // Use the given placement in the structure (YAFFS1 legacy mode)6261#define MTD_NANDECC_AUTOPLACE 2 // Use the default placement scheme6362#define MTD_NANDECC_PLACEONLY 3 // Use the given placement in the structure (Do not store ecc result on read)6363+#define MTD_NANDECC_AUTOPL_USR 4 // Use the given autoplacement scheme rather than using the default6464+6565+/* OTP mode selection */6666+#define MTD_OTP_OFF 06767+#define MTD_OTP_FACTORY 16868+#define MTD_OTP_USER 264696570struct mtd_info_user {6671 uint8_t type;···8780 uint32_t regionindex;8881};89828383+struct otp_info {8484+ uint32_t start;8585+ uint32_t length;8686+ uint32_t locked;8787+};8888+9089#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)9190#define MEMERASE _IOW('M', 2, struct erase_info_user)9291#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)···10592#define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo)10693#define MEMGETBADBLOCK _IOW('M', 11, loff_t)10794#define MEMSETBADBLOCK _IOW('M', 12, loff_t)9595+#define OTPSELECT _IOR('M', 13, int)9696+#define OTPGETREGIONCOUNT _IOW('M', 14, int)9797+#define OTPGETREGIONINFO _IOW('M', 15, struct otp_info)9898+#define OTPLOCK _IOR('M', 16, struct otp_info)10899109100struct nand_oobinfo {110101 uint32_t useecc;