1 Index: linux-2.6.5/drivers/mtd/Kconfig
2 ===================================================================
3 --- linux-2.6.5.orig/drivers/mtd/Kconfig 2004-04-03 22:36:26.000000000 -0500
4 +++ linux-2.6.5/drivers/mtd/Kconfig 2005-02-01 17:11:17.000000000 -0500
6 -# $Id: Kconfig,v 1.3 2003/05/28 11:02:23 dwmw2 Exp $
7 +# $Id: Kconfig,v 1.6 2004/08/09 13:19:42 dwmw2 Exp $
9 menu "Memory Technology Devices (MTD)"
12 Determines the verbosity level of the MTD debugging messages.
15 - tristate "MTD partitioning support"
16 + bool "MTD partitioning support"
19 If you have a device which needs to divide its flash chip(s) up
21 SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
24 +config MTD_REDBOOT_PARTS_UNALLOCATED
25 + bool " Include unallocated flash regions"
26 + depends on MTD_REDBOOT_PARTS
28 + If you need to register each unallocated flash region as a MTD
29 + 'partition', enable this option.
31 +config MTD_REDBOOT_PARTS_READONLY
32 + bool " Force read-only for RedBoot system images"
33 + depends on MTD_REDBOOT_PARTS
35 + If you need to force read-only for 'RedBoot', 'RedBoot Config' and
36 + 'FIS directory' images, enable this option.
38 config MTD_CMDLINE_PARTS
39 - tristate "Command line partition table parsing"
40 - depends on MTD_PARTITIONS
41 + bool "Command line partition table parsing"
42 + depends on MTD_PARTITIONS = "y"
44 Allow generic configuration of the MTD paritition tables via the kernel
45 command line. Multiple flash resources are supported for hardware where
46 Index: linux-2.6.5/drivers/mtd/Makefile
47 ===================================================================
48 --- linux-2.6.5.orig/drivers/mtd/Makefile 2004-04-03 22:36:57.000000000 -0500
49 +++ linux-2.6.5/drivers/mtd/Makefile 2005-02-01 17:11:17.000000000 -0500
52 # Makefile for the memory technology device drivers.
54 -# $Id: Makefile.common,v 1.2 2003/05/23 11:38:29 dwmw2 Exp $
56 -# *** BIG UGLY NOTE ***
58 -# The shiny new inter_module_xxx has introduced yet another ugly link
59 -# order dependency, which I'd previously taken great care to avoid.
60 -# We now have to ensure that the chip drivers are initialised before the
61 -# map drivers, and that the doc200[01] drivers are initialised before
64 -# We'll hopefully merge the doc200[01] drivers and docprobe back into
65 -# a single driver some time soon, but the CFI drivers are going to have
71 +# $Id: Makefile.common,v 1.5 2004/08/10 20:51:49 dwmw2 Exp $
74 -obj-$(CONFIG_MTD) += mtdcore.o
76 +mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
77 +obj-$(CONFIG_MTD) += $(mtd-y)
79 obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
80 -obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
81 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
82 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
83 obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
84 Index: linux-2.6.5/drivers/mtd/afs.c
85 ===================================================================
86 --- linux-2.6.5.orig/drivers/mtd/afs.c 2004-04-03 22:38:15.000000000 -0500
87 +++ linux-2.6.5/drivers/mtd/afs.c 2005-02-01 17:11:17.000000000 -0500
89 This is access code for flashes using ARM's flash partitioning
92 - $Id: afs.c,v 1.12 2003/06/13 15:31:06 rmk Exp $
93 + $Id: afs.c,v 1.13 2004/02/27 22:09:59 rmk Exp $
95 ======================================================================*/
97 Index: linux-2.6.5/drivers/mtd/chips/Kconfig
98 ===================================================================
99 --- linux-2.6.5.orig/drivers/mtd/chips/Kconfig 2004-04-03 22:36:54.000000000 -0500
100 +++ linux-2.6.5/drivers/mtd/chips/Kconfig 2005-02-01 17:11:17.000000000 -0500
102 # drivers/mtd/chips/Kconfig
103 -# $Id: Kconfig,v 1.3 2003/05/28 15:13:24 dwmw2 Exp $
104 +# $Id: Kconfig,v 1.9 2004/07/16 15:32:14 dwmw2 Exp $
106 menu "RAM/ROM/Flash chip drivers"
109 arrangements of CFI chips. If unsure, say 'N' and all options
110 which are supported by the current code will be enabled.
113 - bool "Support 8-bit buswidth"
114 - depends on MTD_CFI_GEOMETRY
115 +config MTD_MAP_BANK_WIDTH_1
116 + bool "Support 8-bit buswidth" if MTD_CFI_GEOMETRY
119 If you wish to support CFI devices on a physical bus which is
120 8 bits wide, say 'Y'.
123 - bool "Support 16-bit buswidth"
124 - depends on MTD_CFI_GEOMETRY
125 +config MTD_MAP_BANK_WIDTH_2
126 + bool "Support 16-bit buswidth" if MTD_CFI_GEOMETRY
129 If you wish to support CFI devices on a physical bus which is
130 16 bits wide, say 'Y'.
133 - bool "Support 32-bit buswidth"
134 - depends on MTD_CFI_GEOMETRY
135 +config MTD_MAP_BANK_WIDTH_4
136 + bool "Support 32-bit buswidth" if MTD_CFI_GEOMETRY
139 If you wish to support CFI devices on a physical bus which is
140 32 bits wide, say 'Y'.
143 - bool "Support 64-bit buswidth"
144 - depends on MTD_CFI_GEOMETRY
145 +config MTD_MAP_BANK_WIDTH_8
146 + bool "Support 64-bit buswidth" if MTD_CFI_GEOMETRY
149 If you wish to support CFI devices on a physical bus which is
150 64 bits wide, say 'Y'.
152 +config MTD_MAP_BANK_WIDTH_16
153 + bool "Support 128-bit buswidth" if MTD_CFI_GEOMETRY
156 + If you wish to support CFI devices on a physical bus which is
157 + 128 bits wide, say 'Y'.
159 +config MTD_MAP_BANK_WIDTH_32
160 + bool "Support 256-bit buswidth" if MTD_CFI_GEOMETRY
163 + If you wish to support CFI devices on a physical bus which is
164 + 256 bits wide, say 'Y'.
167 - bool "Support 1-chip flash interleave" if !MTD_CFI_B1
168 - depends on MTD_CFI_GEOMETRY
169 - default y if MTD_CFI_B1
170 + bool "Support 1-chip flash interleave" if MTD_CFI_GEOMETRY
173 If your flash chips are not interleaved - i.e. you only have one
174 flash chip addressed by each bus cycle, then say 'Y'.
177 - bool "Support 2-chip flash interleave"
178 - depends on MTD_CFI_GEOMETRY
179 + bool "Support 2-chip flash interleave" if MTD_CFI_GEOMETRY
182 If your flash chips are interleaved in pairs - i.e. you have two
183 flash chips addressed by each bus cycle, then say 'Y'.
186 - bool "Support 4-chip flash interleave"
187 - depends on MTD_CFI_GEOMETRY
188 + bool "Support 4-chip flash interleave" if MTD_CFI_GEOMETRY
191 If your flash chips are interleaved in fours - i.e. you have four
192 flash chips addressed by each bus cycle, then say 'Y'.
195 - bool "Support 8-chip flash interleave"
196 - depends on MTD_CFI_GEOMETRY
197 + bool "Support 8-chip flash interleave" if MTD_CFI_GEOMETRY
200 If your flash chips are interleaved in eights - i.e. you have eight
201 flash chips addressed by each bus cycle, then say 'Y'.
203 provides support for one of those command sets, used on chips
204 including the AMD Am29LV320.
206 +config MTD_CFI_AMDSTD_RETRY
207 + int "Retry failed commands (erase/program)"
208 + depends on MTD_CFI_AMDSTD
211 + Some chips, when attached to a shared bus, don't properly filter
212 + bus traffic that is destined to other devices. This broken
213 + behavior causes erase and program sequences to be aborted when
214 + the sequences are mixed with traffic for other devices.
216 + SST49LF040 (and related) chips are know to be broken.
218 +config MTD_CFI_AMDSTD_RETRY_MAX
219 + int "Max retries of failed commands (erase/program)"
220 + depends on MTD_CFI_AMDSTD_RETRY
223 + If you have an SST49LF040 (or related chip) then this value should
224 + be set to at least 1. This can also be adjusted at driver load
225 + time with the retry_cmd_max module parameter.
228 tristate "Support for ST (Advanced Architecture) flash chips"
229 depends on MTD_GEN_PROBE
231 sets which a CFI-compliant chip may claim to implement. This code
232 provides support for one of those command sets.
236 + default y if MTD_CFI_INTELEXT=y || MTD_CFI_AMDSTD=y || MTD_CFI_STAA=y
237 + default m if MTD_CFI_INTELEXT=m || MTD_CFI_AMDSTD=m || MTD_CFI_STAA=m
240 tristate "Support for RAM chips in bus mapping"
243 with this driver will return -ENODEV upon access.
245 config MTD_OBSOLETE_CHIPS
246 + depends on MTD && BROKEN
247 bool "Older (theoretically obsoleted now) drivers for non-CFI chips"
249 This option does not enable any code directly, but will allow you to
250 Index: linux-2.6.5/drivers/mtd/chips/Makefile
251 ===================================================================
252 --- linux-2.6.5.orig/drivers/mtd/chips/Makefile 2004-04-03 22:36:53.000000000 -0500
253 +++ linux-2.6.5/drivers/mtd/chips/Makefile 2005-02-01 17:11:17.000000000 -0500
256 # linux/drivers/chips/Makefile
258 -# $Id: Makefile.common,v 1.1 2003/05/21 15:00:01 dwmw2 Exp $
259 +# $Id: Makefile.common,v 1.4 2004/07/12 16:07:30 dwmw2 Exp $
261 # *** BIG UGLY NOTE ***
263 # The removal of get_module_symbol() and replacement with
264 # inter_module_register() et al has introduced a link order dependency
265 # here where previously there was none. We now have to ensure that
266 -# the CFI command set drivers are linked before cfi_probe.o
267 +# the CFI command set drivers are linked before gen_probe.o
269 obj-$(CONFIG_MTD) += chipreg.o
270 obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o
271 obj-$(CONFIG_MTD_CFI) += cfi_probe.o
272 +obj-$(CONFIG_MTD_CFI_UTIL) += cfi_util.o
273 obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o
274 obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o
275 obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o
276 Index: linux-2.6.5/drivers/mtd/chips/amd_flash.c
277 ===================================================================
278 --- linux-2.6.5.orig/drivers/mtd/chips/amd_flash.c 2004-04-03 22:36:53.000000000 -0500
279 +++ linux-2.6.5/drivers/mtd/chips/amd_flash.c 2005-02-01 17:11:17.000000000 -0500
282 * Author: Jonas Holmberg <jonas.holmberg@axis.com>
284 - * $Id: amd_flash.c,v 1.23 2003/06/12 09:24:13 dwmw2 Exp $
285 + * $Id: amd_flash.c,v 1.25 2004/08/09 13:19:43 dwmw2 Exp $
287 * Copyright (c) 2001 Axis Communications AB
290 "memory for MTD erase region info\n", map->name);
292 map->fldrv_priv = NULL;
299 map->fldrv_priv = private;
301 map->fldrv = &amd_flash_chipdrv;
304 + __module_get(THIS_MODULE);
308 @@ -1307,9 +1307,7 @@
311 instr->state = MTD_ERASE_DONE;
312 - if (instr->callback) {
313 - instr->callback(instr);
315 + mtd_erase_callback(instr);
319 Index: linux-2.6.5/drivers/mtd/chips/cfi_cmdset_0001.c
320 ===================================================================
321 --- linux-2.6.5.orig/drivers/mtd/chips/cfi_cmdset_0001.c 2004-04-03 22:36:54.000000000 -0500
322 +++ linux-2.6.5/drivers/mtd/chips/cfi_cmdset_0001.c 2005-02-01 17:11:17.000000000 -0500
325 * (C) 2000 Red Hat. GPL'd
327 - * $Id: cfi_cmdset_0001.c,v 1.126 2003/06/23 07:45:48 dwmw2 Exp $
328 + * $Id: cfi_cmdset_0001.c,v 1.156 2004/09/17 11:45:05 eric Exp $
331 * 10/10/2000 Nicolas Pitre <nico@cam.org>
333 #include <linux/mtd/compatmac.h>
334 #include <linux/mtd/cfi.h>
336 +/* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */
338 // debugging, turns off buffer write mode if set to 1
339 #define FORCE_WORD_WRITE 0
341 +#define MANUFACTURER_INTEL 0x0089
342 +#define I82802AB 0x00ad
343 +#define I82802AC 0x00ac
344 +#define MANUFACTURER_ST 0x0020
345 +#define M50LPW080 0x002F
347 static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
348 -static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
349 -static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
350 +//static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
351 +//static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
352 static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
353 static int cfi_intelext_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
354 static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *);
357 struct mtd_info *cfi_cmdset_0001(struct map_info *, int);
359 -static struct mtd_info *cfi_intelext_setup (struct map_info *);
360 +static struct mtd_info *cfi_intelext_setup (struct mtd_info *);
361 +static int cfi_intelext_partition_fixup(struct map_info *, struct cfi_private **);
363 static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len,
364 size_t *retlen, u_char **mtdbuf);
365 static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from,
368 +static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
369 +static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
370 +#include "fwh_lock.h"
375 * *********** SETUP AND PROBE BITS ***********
377 static void cfi_tell_features(struct cfi_pri_intelext *extp)
380 - printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport);
381 - printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported");
382 - printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported");
383 - printk(" - Suspend Program: %s\n", extp->FeatureSupport&4?"supported":"unsupported");
384 - printk(" - Legacy Lock/Unlock: %s\n", extp->FeatureSupport&8?"supported":"unsupported");
385 - printk(" - Queued Erase: %s\n", extp->FeatureSupport&16?"supported":"unsupported");
386 - printk(" - Instant block lock: %s\n", extp->FeatureSupport&32?"supported":"unsupported");
387 - printk(" - Protection Bits: %s\n", extp->FeatureSupport&64?"supported":"unsupported");
388 - printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported");
389 - printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported");
390 - for (i=9; i<32; i++) {
391 + printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport);
392 + printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported");
393 + printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported");
394 + printk(" - Suspend Program: %s\n", extp->FeatureSupport&4?"supported":"unsupported");
395 + printk(" - Legacy Lock/Unlock: %s\n", extp->FeatureSupport&8?"supported":"unsupported");
396 + printk(" - Queued Erase: %s\n", extp->FeatureSupport&16?"supported":"unsupported");
397 + printk(" - Instant block lock: %s\n", extp->FeatureSupport&32?"supported":"unsupported");
398 + printk(" - Protection Bits: %s\n", extp->FeatureSupport&64?"supported":"unsupported");
399 + printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported");
400 + printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported");
401 + printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported");
402 + for (i=10; i<32; i++) {
403 if (extp->FeatureSupport & (1<<i))
404 printk(" - Unknown Bit %X: supported\n", i);
406 @@ -110,13 +125,93 @@
409 printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n",
410 - extp->VccOptimal >> 8, extp->VccOptimal & 0xf);
411 + extp->VccOptimal >> 4, extp->VccOptimal & 0xf);
412 if (extp->VppOptimal)
413 printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n",
414 - extp->VppOptimal >> 8, extp->VppOptimal & 0xf);
415 + extp->VppOptimal >> 4, extp->VppOptimal & 0xf);
419 +#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
420 +/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
421 +static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
423 + struct map_info *map = mtd->priv;
424 + struct cfi_private *cfi = map->fldrv_priv;
425 + struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
427 + printk(KERN_WARNING "cfi_cmdset_0001: Suspend "
428 + "erase on write disabled.\n");
429 + extp->SuspendCmdSupport &= ~1;
433 +static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param)
435 + struct map_info *map = mtd->priv;
436 + struct cfi_private *cfi = map->fldrv_priv;
438 + cfi->cfiq->BufWriteTimeoutTyp = 0; /* Not supported */
439 + cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */
442 +static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param)
444 + struct map_info *map = mtd->priv;
445 + struct cfi_private *cfi = map->fldrv_priv;
447 + /* Note this is done after the region info is endian swapped */
448 + cfi->cfiq->EraseRegionInfo[1] =
449 + (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e;
452 +static void fixup_use_point(struct mtd_info *mtd, void *param)
454 + struct map_info *map = mtd->priv;
455 + if (!mtd->point && map_is_linear(map)) {
456 + mtd->point = cfi_intelext_point;
457 + mtd->unpoint = cfi_intelext_unpoint;
461 +static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
463 + struct map_info *map = mtd->priv;
464 + struct cfi_private *cfi = map->fldrv_priv;
465 + if (cfi->cfiq->BufWriteTimeoutTyp) {
466 + printk(KERN_INFO "Using buffer write method\n" );
467 + mtd->write = cfi_intelext_write_buffers;
471 +static struct cfi_fixup cfi_fixup_table[] = {
472 +#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
473 + { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
475 +#if !FORCE_WORD_WRITE
476 + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL },
478 + { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
479 + { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
480 + { 0, 0, NULL, NULL }
483 +static struct cfi_fixup jedec_fixup_table[] = {
484 + { MANUFACTURER_INTEL, I82802AB, fixup_use_fwh_lock, NULL, },
485 + { MANUFACTURER_INTEL, I82802AC, fixup_use_fwh_lock, NULL, },
486 + { MANUFACTURER_ST, M50LPW080, fixup_use_fwh_lock, NULL, },
487 + { 0, 0, NULL, NULL }
489 +static struct cfi_fixup fixup_table[] = {
490 + /* The CFI vendor ids and the JEDEC vendor IDs appear
491 + * to be common. It is like the devices id's are as
492 + * well. This table is to pick all cases where
493 + * we know that is the case.
495 + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point, NULL },
496 + { 0, 0, NULL, NULL }
499 /* This routine is made available to other mtd code via
500 * inter_module_register. It must only be accessed through
501 * inter_module_get which will bump the use count of this module. The
503 struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
505 struct cfi_private *cfi = map->fldrv_priv;
506 + struct mtd_info *mtd;
508 - __u32 base = cfi->chips[0].start;
510 + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
512 + printk(KERN_ERR "Failed to allocate memory for MTD device\n");
515 + memset(mtd, 0, sizeof(*mtd));
517 + mtd->type = MTD_NORFLASH;
519 + /* Fill in the default mtd operations */
520 + mtd->erase = cfi_intelext_erase_varsize;
521 + mtd->read = cfi_intelext_read;
522 + mtd->write = cfi_intelext_write_words;
523 + mtd->sync = cfi_intelext_sync;
524 + mtd->lock = cfi_intelext_lock;
525 + mtd->unlock = cfi_intelext_unlock;
526 + mtd->suspend = cfi_intelext_suspend;
527 + mtd->resume = cfi_intelext_resume;
528 + mtd->flags = MTD_CAP_NORFLASH;
529 + mtd->name = map->name;
531 if (cfi->cfi_mode == CFI_MODE_CFI) {
533 * It's a real CFI chip, not one for which the probe
534 @@ -138,33 +254,10 @@
536 __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
537 struct cfi_pri_intelext *extp;
538 - int ofs_factor = cfi->interleave * cfi->device_type;
540 - //printk(" Intel/Sharp Extended Query Table at 0x%4.4X\n", adr);
544 - /* Switch it into Query Mode */
545 - cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
547 - extp = kmalloc(sizeof(*extp), GFP_KERNEL);
548 + extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "Intel/Sharp");
550 - printk(KERN_ERR "Failed to allocate memory\n");
554 - /* Read in the Extended Query Table */
555 - for (i=0; i<sizeof(*extp); i++) {
556 - ((unsigned char *)extp)[i] =
557 - cfi_read_query(map, (base+((adr+i)*ofs_factor)));
560 - if (extp->MajorVersion != '1' ||
561 - (extp->MinorVersion < '0' || extp->MinorVersion > '3')) {
562 - printk(KERN_WARNING " Unknown IntelExt Extended Query "
563 - "version %c.%c.\n", extp->MajorVersion,
564 - extp->MinorVersion);
571 extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport);
572 extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask);
573 extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr);
575 + /* Install our own private info structure */
576 + cfi->cmdset_priv = extp;
578 + cfi_fixup(mtd, cfi_fixup_table);
580 #ifdef DEBUG_CFI_FEATURES
581 /* Tell the user about it in lots of lovely detail */
582 @@ -179,19 +277,15 @@
585 if(extp->SuspendCmdSupport & 1) {
586 -//#define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
587 -#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
588 -/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
589 - printk(KERN_WARNING "cfi_cmdset_0001: Suspend "
590 - "erase on write disabled.\n");
591 - extp->SuspendCmdSupport &= ~1;
593 printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n");
596 - /* Install our own private info structure */
597 - cfi->cmdset_priv = extp;
599 + else if (cfi->cfi_mode == CFI_MODE_JEDEC) {
600 + /* Apply jedec specific fixups */
601 + cfi_fixup(mtd, jedec_fixup_table);
603 + /* Apply generic fixups */
604 + cfi_fixup(mtd, fixup_table);
606 for (i=0; i< cfi->numchips; i++) {
607 cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
608 @@ -202,30 +296,19 @@
610 map->fldrv = &cfi_intelext_chipdrv;
612 - /* Make sure it's in read mode */
613 - cfi_send_gen_cmd(0xff, 0x55, base, map, cfi, cfi->device_type, NULL);
614 - return cfi_intelext_setup(map);
615 + return cfi_intelext_setup(mtd);
618 -static struct mtd_info *cfi_intelext_setup(struct map_info *map)
619 +static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
621 + struct map_info *map = mtd->priv;
622 struct cfi_private *cfi = map->fldrv_priv;
623 - struct mtd_info *mtd;
624 unsigned long offset = 0;
626 unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
628 - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
629 //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
632 - printk(KERN_ERR "Failed to allocate memory for MTD device\n");
636 - memset(mtd, 0, sizeof(*mtd));
638 - mtd->type = MTD_NORFLASH;
639 mtd->size = devsize * cfi->numchips;
641 mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
642 @@ -265,32 +348,16 @@
643 mtd->eraseregions[i].numblocks);
646 - /* Also select the correct geometry setup too */
647 - mtd->erase = cfi_intelext_erase_varsize;
648 - mtd->read = cfi_intelext_read;
650 - if (map_is_linear(map)) {
651 - mtd->point = cfi_intelext_point;
652 - mtd->unpoint = cfi_intelext_unpoint;
655 - if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) {
656 - printk(KERN_INFO "Using buffer write method\n" );
657 - mtd->write = cfi_intelext_write_buffers;
659 - printk(KERN_INFO "Using word write method\n" );
660 - mtd->write = cfi_intelext_write_words;
663 mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg;
664 mtd->read_fact_prot_reg = cfi_intelext_read_fact_prot_reg;
665 - mtd->sync = cfi_intelext_sync;
666 - mtd->lock = cfi_intelext_lock;
667 - mtd->unlock = cfi_intelext_unlock;
668 - mtd->suspend = cfi_intelext_suspend;
669 - mtd->resume = cfi_intelext_resume;
670 - mtd->flags = MTD_CAP_NORFLASH;
671 - map->fldrv = &cfi_intelext_chipdrv;
672 - mtd->name = map->name;
675 + /* This function has the potential to distort the reality
676 + a bit and therefore should be called last. */
677 + if (cfi_intelext_partition_fixup(map, &cfi) != 0)
680 __module_get(THIS_MODULE);
683 @@ -301,10 +368,87 @@
686 kfree(cfi->cmdset_priv);
691 +static int cfi_intelext_partition_fixup(struct map_info *map,
692 + struct cfi_private **pcfi)
694 + struct cfi_private *cfi = *pcfi;
695 + struct cfi_pri_intelext *extp = cfi->cmdset_priv;
698 + * Probing of multi-partition flash ships.
700 + * This is extremely crude at the moment and should probably be
701 + * extracted entirely from the Intel extended query data instead.
702 + * Right now a L18 flash is assumed if multiple operations is
705 + * To support multiple partitions when available, we simply arrange
706 + * for each of them to have their own flchip structure even if they
707 + * are on the same physical chip. This means completely recreating
708 + * a new cfi_private structure right here which is a blatent code
709 + * layering violation, but this is still the least intrusive
710 + * arrangement at this point. This can be rearranged in the future
711 + * if someone feels motivated enough. --nico
713 + if (extp && extp->FeatureSupport & (1 << 9)) {
714 + struct cfi_private *newcfi;
715 + struct flchip *chip;
716 + struct flchip_shared *shared;
717 + int numparts, partshift, numvirtchips, i, j;
720 + * The L18 flash memory array is divided
721 + * into multiple 8-Mbit partitions.
723 + numparts = 1 << (cfi->cfiq->DevSize - 20);
724 + partshift = 20 + __ffs(cfi->interleave);
725 + numvirtchips = cfi->numchips * numparts;
727 + newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL);
730 + shared = kmalloc(sizeof(struct flchip_shared) * cfi->numchips, GFP_KERNEL);
735 + memcpy(newcfi, cfi, sizeof(struct cfi_private));
736 + newcfi->numchips = numvirtchips;
737 + newcfi->chipshift = partshift;
739 + chip = &newcfi->chips[0];
740 + for (i = 0; i < cfi->numchips; i++) {
741 + shared[i].writing = shared[i].erasing = NULL;
742 + spin_lock_init(&shared[i].lock);
743 + for (j = 0; j < numparts; j++) {
744 + *chip = cfi->chips[i];
745 + chip->start += j << partshift;
746 + chip->priv = &shared[i];
747 + /* those should be reset too since
748 + they create memory references. */
749 + init_waitqueue_head(&chip->wq);
750 + spin_lock_init(&chip->_spinlock);
751 + chip->mutex = &chip->_spinlock;
756 + printk(KERN_DEBUG "%s: %d sets of %d interleaved chips "
757 + "--> %d partitions of %#x bytes\n",
758 + map->name, cfi->numchips, cfi->interleave,
759 + newcfi->numchips, 1<<newcfi->chipshift);
761 + map->fldrv_priv = newcfi;
770 * *********** CHIP ACCESS FUNCTIONS ***********
772 @@ -313,25 +457,87 @@
774 DECLARE_WAITQUEUE(wait, current);
775 struct cfi_private *cfi = map->fldrv_priv;
776 - cfi_word status, status_OK = CMD(0x80);
777 + map_word status, status_OK = CMD(0x80), status_PWS = CMD(0x01);
779 - struct cfi_pri_intelext *cfip = (struct cfi_pri_intelext *)cfi->cmdset_priv;
780 + struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
783 timeo = jiffies + HZ;
785 + if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING)) {
787 + * OK. We have possibility for contension on the write/erase
788 + * operations which are global to the real chip and not per
789 + * partition. So let's fight it over in the partition which
790 + * currently has authority on the operation.
792 + * The rules are as follows:
794 + * - any write operation must own shared->writing.
796 + * - any erase operation must own _both_ shared->writing and
799 + * - contension arbitration is handled in the owner's context.
801 + * The 'shared' struct can be read when its lock is taken.
802 + * However any writes to it can only be made when the current
803 + * owner's lock is also held.
805 + struct flchip_shared *shared = chip->priv;
806 + struct flchip *contender;
807 + spin_lock(&shared->lock);
808 + contender = shared->writing;
809 + if (contender && contender != chip) {
811 + * The engine to perform desired operation on this
812 + * partition is already in use by someone else.
813 + * Let's fight over it in the context of the chip
814 + * currently using it. If it is possible to suspend,
815 + * that other partition will do just that, otherwise
816 + * it'll happily send us to sleep. In any case, when
817 + * get_chip returns success we're clear to go ahead.
819 + int ret = spin_trylock(contender->mutex);
820 + spin_unlock(&shared->lock);
823 + spin_unlock(chip->mutex);
824 + ret = get_chip(map, contender, contender->start, mode);
825 + spin_lock(chip->mutex);
827 + spin_unlock(contender->mutex);
830 + timeo = jiffies + HZ;
831 + spin_lock(&shared->lock);
834 + /* We now own it */
835 + shared->writing = chip;
836 + if (mode == FL_ERASING)
837 + shared->erasing = chip;
838 + if (contender && contender != chip)
839 + spin_unlock(contender->mutex);
840 + spin_unlock(&shared->lock);
843 switch (chip->state) {
847 - status = cfi_read(map, adr);
848 - if ((status & status_OK) == status_OK)
849 + status = map_read(map, adr);
850 + if (map_word_andequal(map, status, status_OK, status_OK))
853 + /* At this point we're fine with write operations
854 + in other partitions as they don't conflict. */
855 + if (chip->priv && map_word_andequal(map, status, status_PWS, status_PWS))
858 if (time_after(jiffies, timeo)) {
859 - printk(KERN_ERR "Waiting for chip to be ready timed out. Status %llx\n",
860 - (long long)status);
861 - spin_unlock(chip->mutex);
862 + printk(KERN_ERR "Waiting for chip to be ready timed out. Status %lx\n",
866 spin_unlock(chip->mutex);
867 @@ -347,38 +553,39 @@
871 - if (!(cfip->FeatureSupport & 2) ||
873 + !(cfip->FeatureSupport & 2) ||
874 !(mode == FL_READY || mode == FL_POINT ||
875 (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1))))
880 - cfi_write(map, CMD(0xB0), adr);
881 + map_write(map, CMD(0xB0), adr);
883 /* If the flash has finished erasing, then 'erase suspend'
884 * appears to make some (28F320) flash devices switch to
885 * 'read' mode. Make sure that we switch to 'read status'
886 * mode so we get the right data. --rmk
888 - cfi_write(map, CMD(0x70), adr);
889 + map_write(map, CMD(0x70), adr);
890 chip->oldstate = FL_ERASING;
891 chip->state = FL_ERASE_SUSPENDING;
892 chip->erase_suspended = 1;
894 - status = cfi_read(map, adr);
895 - if ((status & status_OK) == status_OK)
896 + status = map_read(map, adr);
897 + if (map_word_andequal(map, status, status_OK, status_OK))
900 if (time_after(jiffies, timeo)) {
901 /* Urgh. Resume and pretend we weren't here. */
902 - cfi_write(map, CMD(0xd0), adr);
903 + map_write(map, CMD(0xd0), adr);
904 /* Make sure we're in 'read status' mode if it had finished */
905 - cfi_write(map, CMD(0x70), adr);
906 + map_write(map, CMD(0x70), adr);
907 chip->state = FL_ERASING;
908 chip->oldstate = FL_READY;
909 printk(KERN_ERR "Chip not ready after erase "
910 - "suspended: status = 0x%x\n", status);
911 + "suspended: status = 0x%lx\n", status.x[0]);
917 struct cfi_private *cfi = map->fldrv_priv;
920 + struct flchip_shared *shared = chip->priv;
921 + spin_lock(&shared->lock);
922 + if (shared->writing == chip) {
923 + /* We own the ability to write, but we're done */
924 + shared->writing = shared->erasing;
925 + if (shared->writing && shared->writing != chip) {
926 + /* give back ownership to who we loaned it from */
927 + struct flchip *loaner = shared->writing;
928 + spin_lock(loaner->mutex);
929 + spin_unlock(&shared->lock);
930 + spin_unlock(chip->mutex);
931 + put_chip(map, loaner, loaner->start);
932 + spin_lock(chip->mutex);
933 + spin_unlock(loaner->mutex);
935 + if (chip->oldstate != FL_ERASING) {
936 + shared->erasing = NULL;
937 + if (chip->oldstate != FL_WRITING)
938 + shared->writing = NULL;
940 + spin_unlock(&shared->lock);
945 switch(chip->oldstate) {
947 chip->state = chip->oldstate;
948 @@ -424,13 +657,15 @@
949 sending the 0x70 (Read Status) command to an erasing
950 chip and expecting it to be ignored, that's what we
952 - cfi_write(map, CMD(0xd0), adr);
953 - cfi_write(map, CMD(0x70), adr);
954 + map_write(map, CMD(0xd0), adr);
955 + map_write(map, CMD(0x70), adr);
956 chip->oldstate = FL_READY;
957 chip->state = FL_ERASING;
962 + case FL_JEDEC_QUERY:
963 /* We should really make set_vpp() count, rather than doing this */
969 /* Ensure cmd read/writes are aligned. */
970 - cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1);
971 + cmd_addr = adr & ~(map_bankwidth(map)-1);
973 spin_lock(chip->mutex);
978 if (chip->state != FL_POINT && chip->state != FL_READY)
979 - cfi_write(map, CMD(0xff), cmd_addr);
980 + map_write(map, CMD(0xff), cmd_addr);
982 chip->state = FL_POINT;
983 chip->ref_point_counter++;
984 @@ -475,12 +710,10 @@
988 - if (from + len > mtd->size)
989 + if (!map->virt || (from + len > mtd->size))
992 *mtdbuf = (void *)map->virt + from;
993 - if(*mtdbuf == NULL)
994 - return -EINVAL; /* can not point this region */
997 /* Now lock the chip(s) to POINT state */
1001 /* Ensure cmd read/writes are aligned. */
1002 - cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1);
1003 + cmd_addr = adr & ~(map_bankwidth(map)-1);
1005 spin_lock(chip->mutex);
1006 ret = get_chip(map, chip, cmd_addr, FL_READY);
1010 if (chip->state != FL_POINT && chip->state != FL_READY) {
1011 - cfi_write(map, CMD(0xff), cmd_addr);
1012 + map_write(map, CMD(0xff), cmd_addr);
1014 chip->state = FL_READY;
1022 static int cfi_intelext_read_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, int base_offst, int reg_sz)
1024 struct map_info *map = mtd->priv;
1028 if (chip->state != FL_JEDEC_QUERY) {
1029 - cfi_write(map, CMD(0x90), chip->start);
1030 + map_write(map, CMD(0x90), chip->start);
1031 chip->state = FL_JEDEC_QUERY;
1035 int base_offst,reg_sz;
1037 /* Check that we actually have some protection registers */
1038 - if(!(extp->FeatureSupport&64)){
1039 + if(!extp || !(extp->FeatureSupport&64)){
1040 printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name);
1044 int base_offst,reg_sz;
1046 /* Check that we actually have some protection registers */
1047 - if(!(extp->FeatureSupport&64)){
1048 + if(!extp || !(extp->FeatureSupport&64)){
1049 printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name);
1052 @@ -717,12 +950,12 @@
1054 return cfi_intelext_read_prot_reg(mtd, from, len, retlen, buf, base_offst, reg_sz);
1059 -static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, cfi_word datum)
1060 +static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum)
1062 struct cfi_private *cfi = map->fldrv_priv;
1063 - cfi_word status, status_OK;
1064 + map_word status, status_OK;
1065 unsigned long timeo;
1068 @@ -739,11 +972,12 @@
1072 - cfi_write(map, CMD(0x40), adr);
1073 - cfi_write(map, datum, adr);
1074 + map_write(map, CMD(0x40), adr);
1075 + map_write(map, datum, adr);
1076 chip->state = FL_WRITING;
1078 spin_unlock(chip->mutex);
1079 + INVALIDATE_CACHED_RANGE(map, adr, map_bankwidth(map));
1080 cfi_udelay(chip->word_write_time);
1081 spin_lock(chip->mutex);
1087 - status = cfi_read(map, adr);
1088 - if ((status & status_OK) == status_OK)
1089 + status = map_read(map, adr);
1090 + if (map_word_andequal(map, status, status_OK, status_OK))
1093 /* OK Still waiting */
1094 @@ -793,11 +1027,11 @@
1095 /* Done and happy. */
1096 chip->state = FL_STATUS;
1097 /* check for lock bit */
1098 - if (status & CMD(0x02)) {
1099 + if (map_word_bitsset(map, status, CMD(0x02))) {
1101 - cfi_write(map, CMD(0x50), adr);
1102 + map_write(map, CMD(0x50), adr);
1103 /* put back into read status register mode */
1104 - cfi_write(map, CMD(0x70), adr);
1105 + map_write(map, CMD(0x70), adr);
1109 @@ -824,35 +1058,22 @@
1110 ofs = to - (chipnum << cfi->chipshift);
1112 /* If it's not bus-aligned, do the first byte write */
1113 - if (ofs & (CFIDEV_BUSWIDTH-1)) {
1114 - unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1);
1115 + if (ofs & (map_bankwidth(map)-1)) {
1116 + unsigned long bus_ofs = ofs & ~(map_bankwidth(map)-1);
1117 int gap = ofs - bus_ofs;
1119 - u_char tmp_buf[8];
1123 - tmp_buf[i++] = 0xff;
1124 - while (len && i < CFIDEV_BUSWIDTH)
1125 - tmp_buf[i++] = buf[n++], len--;
1126 - while (i < CFIDEV_BUSWIDTH)
1127 - tmp_buf[i++] = 0xff;
1129 - if (cfi_buswidth_is_2()) {
1130 - datum = *(__u16*)tmp_buf;
1131 - } else if (cfi_buswidth_is_4()) {
1132 - datum = *(__u32*)tmp_buf;
1133 - } else if (cfi_buswidth_is_8()) {
1134 - datum = *(__u64*)tmp_buf;
1136 - return -EINVAL; /* should never happen, but be safe */
1141 + n = min_t(int, len, map_bankwidth(map)-gap);
1142 + datum = map_word_ff(map);
1143 + datum = map_word_load_partial(map, datum, buf, gap, n);
1145 ret = do_write_oneword(map, &cfi->chips[chipnum],
1155 @@ -865,30 +1086,18 @@
1159 - while(len >= CFIDEV_BUSWIDTH) {
1162 - if (cfi_buswidth_is_1()) {
1163 - datum = *(__u8*)buf;
1164 - } else if (cfi_buswidth_is_2()) {
1165 - datum = *(__u16*)buf;
1166 - } else if (cfi_buswidth_is_4()) {
1167 - datum = *(__u32*)buf;
1168 - } else if (cfi_buswidth_is_8()) {
1169 - datum = *(__u64*)buf;
1173 + while(len >= map_bankwidth(map)) {
1174 + map_word datum = map_word_load(map, buf);
1176 ret = do_write_oneword(map, &cfi->chips[chipnum],
1181 - ofs += CFIDEV_BUSWIDTH;
1182 - buf += CFIDEV_BUSWIDTH;
1183 - (*retlen) += CFIDEV_BUSWIDTH;
1184 - len -= CFIDEV_BUSWIDTH;
1185 + ofs += map_bankwidth(map);
1186 + buf += map_bankwidth(map);
1187 + (*retlen) += map_bankwidth(map);
1188 + len -= map_bankwidth(map);
1190 if (ofs >> cfi->chipshift) {
1192 @@ -898,32 +1107,18 @@
1196 - if (len & (CFIDEV_BUSWIDTH-1)) {
1198 - u_char tmp_buf[8];
1202 - tmp_buf[i++] = buf[n++];
1203 - while (i < CFIDEV_BUSWIDTH)
1204 - tmp_buf[i++] = 0xff;
1206 - if (cfi_buswidth_is_2()) {
1207 - datum = *(__u16*)tmp_buf;
1208 - } else if (cfi_buswidth_is_4()) {
1209 - datum = *(__u32*)tmp_buf;
1210 - } else if (cfi_buswidth_is_8()) {
1211 - datum = *(__u64*)tmp_buf;
1213 - return -EINVAL; /* should never happen, but be safe */
1215 + if (len & (map_bankwidth(map)-1)) {
1218 + datum = map_word_ff(map);
1219 + datum = map_word_load_partial(map, datum, buf, 0, len);
1221 ret = do_write_oneword(map, &cfi->chips[chipnum],
1231 @@ -934,11 +1129,11 @@
1232 unsigned long adr, const u_char *buf, int len)
1234 struct cfi_private *cfi = map->fldrv_priv;
1235 - cfi_word status, status_OK;
1236 + map_word status, status_OK;
1237 unsigned long cmd_adr, timeo;
1238 int wbufsize, z, ret=0, bytes, words;
1240 - wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize;
1241 + wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
1243 cmd_adr = adr & ~(wbufsize-1);
1245 @@ -952,29 +1147,28 @@
1249 - if (chip->state != FL_STATUS)
1250 - cfi_write(map, CMD(0x70), cmd_adr);
1252 - status = cfi_read(map, cmd_adr);
1254 /* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set
1255 [...], the device will not accept any more Write to Buffer commands".
1256 So we must check here and reset those bits if they're set. Otherwise
1257 we're just pissing in the wind */
1258 - if (status & CMD(0x30)) {
1259 - printk(KERN_WARNING "SR.4 or SR.5 bits set in buffer write (status %x). Clearing.\n", status);
1260 - cfi_write(map, CMD(0x50), cmd_adr);
1261 - cfi_write(map, CMD(0x70), cmd_adr);
1262 + if (chip->state != FL_STATUS)
1263 + map_write(map, CMD(0x70), cmd_adr);
1264 + status = map_read(map, cmd_adr);
1265 + if (map_word_bitsset(map, status, CMD(0x30))) {
1266 + printk(KERN_WARNING "SR.4 or SR.5 bits set in buffer write (status %lx). Clearing.\n", status.x[0]);
1267 + map_write(map, CMD(0x50), cmd_adr);
1268 + map_write(map, CMD(0x70), cmd_adr);
1272 chip->state = FL_WRITING_TO_BUFFER;
1276 - cfi_write(map, CMD(0xe8), cmd_adr);
1277 + map_write(map, CMD(0xe8), cmd_adr);
1279 - status = cfi_read(map, cmd_adr);
1280 - if ((status & status_OK) == status_OK)
1281 + status = map_read(map, cmd_adr);
1282 + if (map_word_andequal(map, status, status_OK, status_OK))
1285 spin_unlock(chip->mutex);
1286 @@ -983,84 +1177,47 @@
1289 /* Argh. Not ready for write to buffer */
1290 - cfi_write(map, CMD(0x70), cmd_adr);
1291 + map_write(map, CMD(0x70), cmd_adr);
1292 chip->state = FL_STATUS;
1293 - printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %llx, status = %llx\n", (__u64)status, (__u64)cfi_read(map, cmd_adr));
1294 + printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %lx, status = %lx\n",
1295 + status.x[0], map_read(map, cmd_adr).x[0]);
1296 /* Odd. Clear status bits */
1297 - cfi_write(map, CMD(0x50), cmd_adr);
1298 - cfi_write(map, CMD(0x70), cmd_adr);
1299 + map_write(map, CMD(0x50), cmd_adr);
1300 + map_write(map, CMD(0x70), cmd_adr);
1306 /* Write length of data to come */
1307 - bytes = len & (CFIDEV_BUSWIDTH-1);
1308 - words = len / CFIDEV_BUSWIDTH;
1309 - cfi_write(map, CMD(words - !bytes), cmd_adr );
1310 + bytes = len & (map_bankwidth(map)-1);
1311 + words = len / map_bankwidth(map);
1312 + map_write(map, CMD(words - !bytes), cmd_adr );
1316 - while(z < words * CFIDEV_BUSWIDTH) {
1317 - if (cfi_buswidth_is_1()) {
1318 - u8 *b = (u8 *)buf;
1320 - map_write8 (map, *b++, adr+z);
1321 - buf = (const u_char *)b;
1322 - } else if (cfi_buswidth_is_2()) {
1323 - u16 *b = (u16 *)buf;
1325 - map_write16 (map, *b++, adr+z);
1326 - buf = (const u_char *)b;
1327 - } else if (cfi_buswidth_is_4()) {
1328 - u32 *b = (u32 *)buf;
1330 - map_write32 (map, *b++, adr+z);
1331 - buf = (const u_char *)b;
1332 - } else if (cfi_buswidth_is_8()) {
1333 - u64 *b = (u64 *)buf;
1335 - map_write64 (map, *b++, adr+z);
1336 - buf = (const u_char *)b;
1341 - z += CFIDEV_BUSWIDTH;
1342 + while(z < words * map_bankwidth(map)) {
1343 + map_word datum = map_word_load(map, buf);
1344 + map_write(map, datum, adr+z);
1346 + z += map_bankwidth(map);
1347 + buf += map_bankwidth(map);
1352 - u_char tmp_buf[8], *tmp_p = tmp_buf;
1356 - tmp_buf[i++] = buf[n++];
1357 - while (i < CFIDEV_BUSWIDTH)
1358 - tmp_buf[i++] = 0xff;
1359 - if (cfi_buswidth_is_2()) {
1360 - u16 *b = (u16 *)tmp_p;
1362 - map_write16 (map, *b++, adr+z);
1363 - tmp_p = (u_char *)b;
1364 - } else if (cfi_buswidth_is_4()) {
1365 - u32 *b = (u32 *)tmp_p;
1367 - map_write32 (map, *b++, adr+z);
1368 - tmp_p = (u_char *)b;
1369 - } else if (cfi_buswidth_is_8()) {
1370 - u64 *b = (u64 *)tmp_p;
1372 - map_write64 (map, *b++, adr+z);
1373 - tmp_p = (u_char *)b;
1378 + datum = map_word_ff(map);
1379 + datum = map_word_load_partial(map, datum, buf, 0, bytes);
1380 + map_write(map, datum, adr+z);
1384 - cfi_write(map, CMD(0xd0), cmd_adr);
1385 + map_write(map, CMD(0xd0), cmd_adr);
1386 chip->state = FL_WRITING;
1388 spin_unlock(chip->mutex);
1389 + INVALIDATE_CACHED_RANGE(map, adr, len);
1390 cfi_udelay(chip->buffer_write_time);
1391 spin_lock(chip->mutex);
1393 @@ -1080,8 +1237,8 @@
1397 - status = cfi_read(map, cmd_adr);
1398 - if ((status & status_OK) == status_OK)
1399 + status = map_read(map, cmd_adr);
1400 + if (map_word_andequal(map, status, status_OK, status_OK))
1403 /* OK Still waiting */
1404 @@ -1110,11 +1267,11 @@
1405 chip->state = FL_STATUS;
1407 /* check for lock bit */
1408 - if (status & CMD(0x02)) {
1409 + if (map_word_bitsset(map, status, CMD(0x02))) {
1411 - cfi_write(map, CMD(0x50), cmd_adr);
1412 + map_write(map, CMD(0x50), cmd_adr);
1413 /* put back into read status register mode */
1414 - cfi_write(map, CMD(0x70), adr);
1415 + map_write(map, CMD(0x70), adr);
1419 @@ -1129,7 +1286,7 @@
1421 struct map_info *map = mtd->priv;
1422 struct cfi_private *cfi = map->fldrv_priv;
1423 - int wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize;
1424 + int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
1428 @@ -1142,8 +1299,8 @@
1429 ofs = to - (chipnum << cfi->chipshift);
1431 /* If it's not bus-aligned, do the first word write */
1432 - if (ofs & (CFIDEV_BUSWIDTH-1)) {
1433 - size_t local_len = (-ofs)&(CFIDEV_BUSWIDTH-1);
1434 + if (ofs & (map_bankwidth(map)-1)) {
1435 + size_t local_len = (-ofs)&(map_bankwidth(map)-1);
1436 if (local_len > len)
1438 ret = cfi_intelext_write_words(mtd, to, local_len,
1439 @@ -1162,7 +1319,6 @@
1443 - /* Write buffer is worth it only if more than one word to write... */
1445 /* We must not cross write block boundaries */
1446 int size = wbufsize - (ofs & (wbufsize-1));
1447 @@ -1189,102 +1345,11 @@
1451 -typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
1452 - unsigned long adr, void *thunk);
1454 -static int cfi_intelext_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
1455 - loff_t ofs, size_t len, void *thunk)
1457 - struct map_info *map = mtd->priv;
1458 - struct cfi_private *cfi = map->fldrv_priv;
1459 - unsigned long adr;
1460 - int chipnum, ret = 0;
1462 - struct mtd_erase_region_info *regions = mtd->eraseregions;
1464 - if (ofs > mtd->size)
1467 - if ((len + ofs) > mtd->size)
1470 - /* Check that both start and end of the requested erase are
1471 - * aligned with the erasesize at the appropriate addresses.
1476 - /* Skip all erase regions which are ended before the start of
1477 - the requested erase. Actually, to save on the calculations,
1478 - we skip to the first erase region which starts after the
1479 - start of the requested erase, and then go back one.
1482 - while (i < mtd->numeraseregions && ofs >= regions[i].offset)
1486 - /* OK, now i is pointing at the erase region in which this
1487 - erase request starts. Check the start of the requested
1488 - erase range is aligned with the erase size which is in
1492 - if (ofs & (regions[i].erasesize-1))
1495 - /* Remember the erase region we start on */
1498 - /* Next, check that the end of the requested erase is aligned
1499 - * with the erase region at that address.
1502 - while (i<mtd->numeraseregions && (ofs + len) >= regions[i].offset)
1505 - /* As before, drop back one to point at the region in which
1506 - the address actually falls
1510 - if ((ofs + len) & (regions[i].erasesize-1))
1513 - chipnum = ofs >> cfi->chipshift;
1514 - adr = ofs - (chipnum << cfi->chipshift);
1519 - ret = (*frob)(map, &cfi->chips[chipnum], adr, thunk);
1524 - adr += regions[i].erasesize;
1525 - len -= regions[i].erasesize;
1527 - if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
1530 - if (adr >> cfi->chipshift) {
1534 - if (chipnum >= cfi->numchips)
1543 -static int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk)
1544 +static int do_erase_oneblock(struct map_info *map, struct flchip *chip,
1545 + unsigned long adr, int len, void *thunk)
1547 struct cfi_private *cfi = map->fldrv_priv;
1548 - cfi_word status, status_OK;
1549 + map_word status, status_OK;
1550 unsigned long timeo;
1552 DECLARE_WAITQUEUE(wait, current);
1553 @@ -1305,17 +1370,17 @@
1556 /* Clear the status register first */
1557 - cfi_write(map, CMD(0x50), adr);
1558 + map_write(map, CMD(0x50), adr);
1561 - cfi_write(map, CMD(0x20), adr);
1562 - cfi_write(map, CMD(0xD0), adr);
1563 + map_write(map, CMD(0x20), adr);
1564 + map_write(map, CMD(0xD0), adr);
1565 chip->state = FL_ERASING;
1566 chip->erase_suspended = 0;
1568 spin_unlock(chip->mutex);
1569 - set_current_state(TASK_UNINTERRUPTIBLE);
1570 - schedule_timeout((chip->erase_time*HZ)/(2*1000));
1571 + INVALIDATE_CACHED_RANGE(map, adr, len);
1572 + msleep(chip->erase_time / 2);
1573 spin_lock(chip->mutex);
1575 /* FIXME. Use a timer to check this, and return immediately. */
1576 @@ -1340,19 +1405,19 @@
1577 chip->erase_suspended = 0;
1580 - status = cfi_read(map, adr);
1581 - if ((status & status_OK) == status_OK)
1582 + status = map_read(map, adr);
1583 + if (map_word_andequal(map, status, status_OK, status_OK))
1586 /* OK Still waiting */
1587 if (time_after(jiffies, timeo)) {
1588 - cfi_write(map, CMD(0x70), adr);
1589 + map_write(map, CMD(0x70), adr);
1590 chip->state = FL_STATUS;
1591 - printk(KERN_ERR "waiting for erase at %08lx to complete timed out. Xstatus = %llx, status = %llx.\n",
1592 - adr, (__u64)status, (__u64)cfi_read(map, adr));
1593 + printk(KERN_ERR "waiting for erase at %08lx to complete timed out. Xstatus = %lx, status = %lx.\n",
1594 + adr, status.x[0], map_read(map, adr).x[0]);
1595 /* Clear status bits */
1596 - cfi_write(map, CMD(0x50), adr);
1597 - cfi_write(map, CMD(0x70), adr);
1598 + map_write(map, CMD(0x50), adr);
1599 + map_write(map, CMD(0x70), adr);
1601 spin_unlock(chip->mutex);
1603 @@ -1369,43 +1434,46 @@
1606 /* We've broken this before. It doesn't hurt to be safe */
1607 - cfi_write(map, CMD(0x70), adr);
1608 + map_write(map, CMD(0x70), adr);
1609 chip->state = FL_STATUS;
1610 - status = cfi_read(map, adr);
1611 + status = map_read(map, adr);
1613 /* check for lock bit */
1614 - if (status & CMD(0x3a)) {
1615 - unsigned char chipstatus = status;
1616 - if (status != CMD(status & 0xff)) {
1618 - for (i = 1; i<CFIDEV_INTERLEAVE; i++) {
1619 - chipstatus |= status >> (cfi->device_type * 8);
1620 + if (map_word_bitsset(map, status, CMD(0x3a))) {
1621 + unsigned char chipstatus = status.x[0];
1622 + if (!map_word_equal(map, status, CMD(chipstatus))) {
1624 + for (w=0; w<map_words(map); w++) {
1625 + for (i = 0; i<cfi_interleave(cfi); i++) {
1626 + chipstatus |= status.x[w] >> (cfi->device_type * 8);
1629 - printk(KERN_WARNING "Status is not identical for all chips: 0x%llx. Merging to give 0x%02x\n", (__u64)status, chipstatus);
1630 + printk(KERN_WARNING "Status is not identical for all chips: 0x%lx. Merging to give 0x%02x\n",
1631 + status.x[0], chipstatus);
1633 /* Reset the error bits */
1634 - cfi_write(map, CMD(0x50), adr);
1635 - cfi_write(map, CMD(0x70), adr);
1636 + map_write(map, CMD(0x50), adr);
1637 + map_write(map, CMD(0x70), adr);
1639 if ((chipstatus & 0x30) == 0x30) {
1640 - printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%llx\n", (__u64)status);
1641 + printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%x\n", chipstatus);
1643 } else if (chipstatus & 0x02) {
1644 /* Protection bit set */
1646 } else if (chipstatus & 0x8) {
1648 - printk(KERN_WARNING "Chip reports voltage low on erase: status 0x%llx\n", (__u64)status);
1649 + printk(KERN_WARNING "Chip reports voltage low on erase: status 0x%x\n", chipstatus);
1651 } else if (chipstatus & 0x20) {
1653 - printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%llx. Retrying...\n", adr, (__u64)status);
1654 + printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x. Retrying...\n", adr, chipstatus);
1655 timeo = jiffies + HZ;
1656 chip->state = FL_STATUS;
1657 spin_unlock(chip->mutex);
1660 - printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%llx\n", adr, (__u64)status);
1661 + printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x\n", adr, chipstatus);
1665 @@ -1423,13 +1491,12 @@
1669 - ret = cfi_intelext_varsize_frob(mtd, do_erase_oneblock, ofs, len, 0);
1670 + ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
1674 instr->state = MTD_ERASE_DONE;
1675 - if (instr->callback)
1676 - instr->callback(instr);
1677 + mtd_erase_callback(instr);
1681 @@ -1475,7 +1542,8 @@
1684 #ifdef DEBUG_LOCK_BITS
1685 -static int do_printlockstatus_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk)
1686 +static int do_printlockstatus_oneblock(struct map_info *map, struct flchip *chip,
1687 + unsigned long adr, int len, void *thunk)
1689 struct cfi_private *cfi = map->fldrv_priv;
1690 int ofs_factor = cfi->interleave * cfi->device_type;
1691 @@ -1483,8 +1551,7 @@
1692 cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
1693 printk(KERN_DEBUG "block status register for 0x%08lx is %x\n",
1694 adr, cfi_read_query(map, adr+(2*ofs_factor)));
1695 - cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
1697 + chip->state = FL_JEDEC_QUERY;
1701 @@ -1492,10 +1559,11 @@
1702 #define DO_XXLOCK_ONEBLOCK_LOCK ((void *) 1)
1703 #define DO_XXLOCK_ONEBLOCK_UNLOCK ((void *) 2)
1705 -static int do_xxlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk)
1706 +static int do_xxlock_oneblock(struct map_info *map, struct flchip *chip,
1707 + unsigned long adr, int len, void *thunk)
1709 struct cfi_private *cfi = map->fldrv_priv;
1710 - cfi_word status, status_OK;
1711 + map_word status, status_OK;
1712 unsigned long timeo = jiffies + HZ;
1715 @@ -1512,13 +1580,13 @@
1719 - cfi_write(map, CMD(0x60), adr);
1720 + map_write(map, CMD(0x60), adr);
1722 if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) {
1723 - cfi_write(map, CMD(0x01), adr);
1724 + map_write(map, CMD(0x01), adr);
1725 chip->state = FL_LOCKING;
1726 } else if (thunk == DO_XXLOCK_ONEBLOCK_UNLOCK) {
1727 - cfi_write(map, CMD(0xD0), adr);
1728 + map_write(map, CMD(0xD0), adr);
1729 chip->state = FL_UNLOCKING;
1732 @@ -1533,15 +1601,16 @@
1733 timeo = jiffies + (HZ*20);
1736 - status = cfi_read(map, adr);
1737 - if ((status & status_OK) == status_OK)
1738 + status = map_read(map, adr);
1739 + if (map_word_andequal(map, status, status_OK, status_OK))
1742 /* OK Still waiting */
1743 if (time_after(jiffies, timeo)) {
1744 - cfi_write(map, CMD(0x70), adr);
1745 + map_write(map, CMD(0x70), adr);
1746 chip->state = FL_STATUS;
1747 - printk(KERN_ERR "waiting for unlock to complete timed out. Xstatus = %llx, status = %llx.\n", (__u64)status, (__u64)cfi_read(map, adr));
1748 + printk(KERN_ERR "waiting for unlock to complete timed out. Xstatus = %lx, status = %lx.\n",
1749 + status.x[0], map_read(map, adr).x[0]);
1751 spin_unlock(chip->mutex);
1753 @@ -1567,18 +1636,18 @@
1754 #ifdef DEBUG_LOCK_BITS
1755 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
1756 __FUNCTION__, ofs, len);
1757 - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
1759 + cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
1763 - ret = cfi_intelext_varsize_frob(mtd, do_xxlock_oneblock,
1764 - ofs, len, DO_XXLOCK_ONEBLOCK_LOCK);
1765 + ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
1766 + ofs, len, DO_XXLOCK_ONEBLOCK_LOCK);
1768 #ifdef DEBUG_LOCK_BITS
1769 - printk(KERN_DEBUG __FUNCTION__
1770 - "%s: lock status after, ret=%d\n", __FUNCTION__, ret);
1771 - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
1773 + printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
1774 + __FUNCTION__, ret);
1775 + cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
1780 @@ -1591,17 +1660,18 @@
1781 #ifdef DEBUG_LOCK_BITS
1782 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
1783 __FUNCTION__, ofs, len);
1784 - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
1786 + cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
1790 - ret = cfi_intelext_varsize_frob(mtd, do_xxlock_oneblock,
1791 + ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
1792 ofs, len, DO_XXLOCK_ONEBLOCK_UNLOCK);
1794 #ifdef DEBUG_LOCK_BITS
1795 - printk(KERN_DEBUG "%s: lock status after, ret=%d\n", __FUNCTION__, ret);
1796 - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
1798 + printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
1799 + __FUNCTION__, ret);
1800 + cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
1805 @@ -1679,7 +1749,7 @@
1807 /* Go to known state. Chip may have been power cycled */
1808 if (chip->state == FL_PM_SUSPENDED) {
1809 - cfi_write(map, CMD(0xFF), 0);
1810 + map_write(map, CMD(0xFF), cfi->chips[i].start);
1811 chip->state = FL_READY;
1814 @@ -1694,6 +1764,7 @@
1815 struct cfi_private *cfi = map->fldrv_priv;
1816 kfree(cfi->cmdset_priv);
1818 + kfree(cfi->chips[0].priv);
1820 kfree(mtd->eraseregions);
1822 Index: linux-2.6.5/drivers/mtd/chips/cfi_cmdset_0002.c
1823 ===================================================================
1824 --- linux-2.6.5.orig/drivers/mtd/chips/cfi_cmdset_0002.c 2004-04-03 22:36:57.000000000 -0500
1825 +++ linux-2.6.5/drivers/mtd/chips/cfi_cmdset_0002.c 2005-02-01 17:11:17.000000000 -0500
1827 * AMD & Fujitsu Standard Vendor Command Set (ID 0x0002)
1829 * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
1830 + * Copyright (C) 2004 Arcom Control Systems Ltd <linux@arcom.com>
1832 * 2_by_8 routines added by Simon Munton
1834 + * 4_by_16 work by Carolyn J. Smith
1836 + * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
1840 - * $Id: cfi_cmdset_0002.c,v 1.74 2003/05/28 12:51:48 dwmw2 Exp $
1841 + * $Id: cfi_cmdset_0002.c,v 1.109 2004/09/15 23:48:09 thayne Exp $
1845 +#include <linux/config.h>
1846 #include <linux/module.h>
1847 #include <linux/types.h>
1848 #include <linux/kernel.h>
1850 #include <linux/slab.h>
1851 #include <linux/delay.h>
1852 #include <linux/interrupt.h>
1853 +#include <linux/mtd/compatmac.h>
1854 #include <linux/mtd/map.h>
1855 #include <linux/mtd/mtd.h>
1856 #include <linux/mtd/cfi.h>
1857 -#include <linux/mtd/compatmac.h>
1859 #define AMD_BOOTLOC_BUG
1860 +#define FORCE_WORD_WRITE 0
1862 +#define MAX_WORD_RETRIES 3
1864 +#define MANUFACTURER_AMD 0x0001
1865 +#define MANUFACTURER_SST 0x00BF
1866 +#define SST49LF004B 0x0060
1868 static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
1869 -static int cfi_amdstd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
1870 +static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
1871 +static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
1872 static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *);
1873 -static int cfi_amdstd_erase_onesize(struct mtd_info *, struct erase_info *);
1874 static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *);
1875 static void cfi_amdstd_sync (struct mtd_info *);
1876 static int cfi_amdstd_suspend (struct mtd_info *);
1878 static void cfi_amdstd_destroy(struct mtd_info *);
1880 struct mtd_info *cfi_cmdset_0002(struct map_info *, int);
1881 -static struct mtd_info *cfi_amdstd_setup (struct map_info *);
1882 +static struct mtd_info *cfi_amdstd_setup (struct mtd_info *);
1884 +static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
1885 +static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
1886 +#include "fwh_lock.h"
1888 static struct mtd_chip_driver cfi_amdstd_chipdrv = {
1889 .probe = NULL, /* Not usable directly */
1890 @@ -55,50 +71,199 @@
1894 +/* #define DEBUG_CFI_FEATURES */
1897 +#ifdef DEBUG_CFI_FEATURES
1898 +static void cfi_tell_features(struct cfi_pri_amdstd *extp)
1900 + const char* erase_suspend[3] = {
1901 + "Not supported", "Read only", "Read/write"
1903 + const char* top_bottom[6] = {
1904 + "No WP", "8x8KiB sectors at top & bottom, no WP",
1905 + "Bottom boot", "Top boot",
1906 + "Uniform, Bottom WP", "Uniform, Top WP"
1909 + printk(" Silicon revision: %d\n", extp->SiliconRevision >> 1);
1910 + printk(" Address sensitive unlock: %s\n",
1911 + (extp->SiliconRevision & 1) ? "Not required" : "Required");
1913 + if (extp->EraseSuspend < ARRAY_SIZE(erase_suspend))
1914 + printk(" Erase Suspend: %s\n", erase_suspend[extp->EraseSuspend]);
1916 + printk(" Erase Suspend: Unknown value %d\n", extp->EraseSuspend);
1918 + if (extp->BlkProt == 0)
1919 + printk(" Block protection: Not supported\n");
1921 + printk(" Block protection: %d sectors per group\n", extp->BlkProt);
1924 + printk(" Temporary block unprotect: %s\n",
1925 + extp->TmpBlkUnprotect ? "Supported" : "Not supported");
1926 + printk(" Block protect/unprotect scheme: %d\n", extp->BlkProtUnprot);
1927 + printk(" Number of simultaneous operations: %d\n", extp->SimultaneousOps);
1928 + printk(" Burst mode: %s\n",
1929 + extp->BurstMode ? "Supported" : "Not supported");
1930 + if (extp->PageMode == 0)
1931 + printk(" Page mode: Not supported\n");
1933 + printk(" Page mode: %d word page\n", extp->PageMode << 2);
1935 + printk(" Vpp Supply Minimum Program/Erase Voltage: %d.%d V\n",
1936 + extp->VppMin >> 4, extp->VppMin & 0xf);
1937 + printk(" Vpp Supply Maximum Program/Erase Voltage: %d.%d V\n",
1938 + extp->VppMax >> 4, extp->VppMax & 0xf);
1940 + if (extp->TopBottom < ARRAY_SIZE(top_bottom))
1941 + printk(" Top/Bottom Boot Block: %s\n", top_bottom[extp->TopBottom]);
1943 + printk(" Top/Bottom Boot Block: Unknown value %d\n", extp->TopBottom);
1947 +#ifdef AMD_BOOTLOC_BUG
1948 +/* Wheee. Bring me the head of someone at AMD. */
1949 +static void fixup_amd_bootblock(struct mtd_info *mtd, void* param)
1951 + struct map_info *map = mtd->priv;
1952 + struct cfi_private *cfi = map->fldrv_priv;
1953 + struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
1954 + __u8 major = extp->MajorVersion;
1955 + __u8 minor = extp->MinorVersion;
1957 + if (((major << 8) | minor) < 0x3131) {
1958 + /* CFI version 1.0 => don't trust bootloc */
1959 + if (cfi->id & 0x80) {
1960 + printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id);
1961 + extp->TopBottom = 3; /* top boot */
1963 + extp->TopBottom = 2; /* bottom boot */
1969 +static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
1971 + struct map_info *map = mtd->priv;
1972 + struct cfi_private *cfi = map->fldrv_priv;
1973 + if (cfi->cfiq->BufWriteTimeoutTyp) {
1974 + DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" );
1975 + mtd->write = cfi_amdstd_write_buffers;
1979 +static void fixup_use_secsi(struct mtd_info *mtd, void *param)
1981 + /* Setup for chips with a secsi area */
1982 + mtd->read_user_prot_reg = cfi_amdstd_secsi_read;
1983 + mtd->read_fact_prot_reg = cfi_amdstd_secsi_read;
1986 +static void fixup_use_erase_chip(struct mtd_info *mtd, void *param)
1988 + struct map_info *map = mtd->priv;
1989 + struct cfi_private *cfi = map->fldrv_priv;
1990 + if ((cfi->cfiq->NumEraseRegions == 1) &&
1991 + ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) {
1992 + mtd->erase = cfi_amdstd_erase_chip;
1997 +static struct cfi_fixup cfi_fixup_table[] = {
1998 +#ifdef AMD_BOOTLOC_BUG
1999 + { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
2001 + { CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, },
2002 + { CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, },
2003 + { CFI_MFR_AMD, 0x0055, fixup_use_secsi, NULL, },
2004 + { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, },
2005 + { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, },
2006 + { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, },
2007 +#if !FORCE_WORD_WRITE
2008 + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
2010 + { 0, 0, NULL, NULL }
2012 +static struct cfi_fixup jedec_fixup_table[] = {
2013 + { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },
2014 + { 0, 0, NULL, NULL }
2017 +static struct cfi_fixup fixup_table[] = {
2018 + /* The CFI vendor ids and the JEDEC vendor IDs appear
2019 + * to be common. It is like the devices id's are as
2020 + * well. This table is to pick all cases where
2021 + * we know that is the case.
2023 + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
2024 + { 0, 0, NULL, NULL }
2028 struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
2030 struct cfi_private *cfi = map->fldrv_priv;
2031 - unsigned char bootloc;
2032 - int ofs_factor = cfi->interleave * cfi->device_type;
2033 + struct mtd_info *mtd;
2035 - __u8 major, minor;
2036 - __u32 base = cfi->chips[0].start;
2038 + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
2040 + printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
2043 + memset(mtd, 0, sizeof(*mtd));
2045 + mtd->type = MTD_NORFLASH;
2047 + /* Fill in the default mtd operations */
2048 + mtd->erase = cfi_amdstd_erase_varsize;
2049 + mtd->write = cfi_amdstd_write_words;
2050 + mtd->read = cfi_amdstd_read;
2051 + mtd->sync = cfi_amdstd_sync;
2052 + mtd->suspend = cfi_amdstd_suspend;
2053 + mtd->resume = cfi_amdstd_resume;
2054 + mtd->flags = MTD_CAP_NORFLASH;
2055 + mtd->name = map->name;
2057 if (cfi->cfi_mode==CFI_MODE_CFI){
2058 + unsigned char bootloc;
2060 + * It's a real CFI chip, not one for which the probe
2061 + * routine faked a CFI structure. So we read the feature
2064 __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
2065 + struct cfi_pri_amdstd *extp;
2067 - cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
2069 - major = cfi_read_query(map, base + (adr+3)*ofs_factor);
2070 - minor = cfi_read_query(map, base + (adr+4)*ofs_factor);
2072 - printk(KERN_NOTICE " Amd/Fujitsu Extended Query Table v%c.%c at 0x%4.4X\n",
2073 - major, minor, adr);
2074 - cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL);
2076 - cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL);
2077 - cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
2078 - cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
2079 - /* FIXME - should have a delay before continuing */
2080 - cfi->mfr = cfi_read_query(map, base);
2081 - cfi->id = cfi_read_query(map, base + ofs_factor);
2082 + extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu");
2088 + /* Install our own private info structure */
2089 + cfi->cmdset_priv = extp;
2091 + /* Apply cfi device specific fixups */
2092 + cfi_fixup(mtd, cfi_fixup_table);
2094 +#ifdef DEBUG_CFI_FEATURES
2095 + /* Tell the user about it in lots of lovely detail */
2096 + cfi_tell_features(extp);
2099 + bootloc = extp->TopBottom;
2100 + if ((bootloc != 2) && (bootloc != 3)) {
2101 + printk(KERN_WARNING "%s: CFI does not contain boot "
2102 + "bank location. Assuming top.\n", map->name);
2106 - /* Wheee. Bring me the head of someone at AMD. */
2107 -#ifdef AMD_BOOTLOC_BUG
2108 - if (((major << 8) | minor) < 0x3131) {
2109 - /* CFI version 1.0 => don't trust bootloc */
2110 - if (cfi->id & 0x80) {
2111 - printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id);
2112 - bootloc = 3; /* top boot */
2114 - bootloc = 2; /* bottom boot */
2119 - cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
2120 - bootloc = cfi_read_query(map, base + (adr+15)*ofs_factor);
2122 if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) {
2123 printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name);
2125 @@ -112,32 +277,50 @@
2129 - * FIXME - These might already be setup (more correctly)
2130 - * buy jedec_probe.c.
2131 + * These might already be setup (more correctly) by
2132 + * jedec_probe.c - still need it for cfi_probe.c path.
2134 - switch (cfi->device_type) {
2135 - case CFI_DEVICETYPE_X8:
2136 - cfi->addr_unlock1 = 0x555;
2137 - cfi->addr_unlock2 = 0x2aa;
2139 - case CFI_DEVICETYPE_X16:
2140 - cfi->addr_unlock1 = 0xaaa;
2141 - if (map->buswidth == cfi->interleave) {
2142 - /* X16 chip(s) in X8 mode */
2143 - cfi->addr_unlock2 = 0x555;
2145 - cfi->addr_unlock2 = 0x554;
2146 + if ( ! (cfi->addr_unlock1 && cfi->addr_unlock2) ) {
2147 + switch (cfi->device_type) {
2148 + case CFI_DEVICETYPE_X8:
2149 + cfi->addr_unlock1 = 0x555;
2150 + cfi->addr_unlock2 = 0x2aa;
2152 + case CFI_DEVICETYPE_X16:
2153 + cfi->addr_unlock1 = 0xaaa;
2154 + if (map_bankwidth(map) == cfi_interleave(cfi)) {
2155 + /* X16 chip(s) in X8 mode */
2156 + cfi->addr_unlock2 = 0x555;
2158 + cfi->addr_unlock2 = 0x554;
2161 + case CFI_DEVICETYPE_X32:
2162 + cfi->addr_unlock1 = 0x1554;
2163 + if (map_bankwidth(map) == cfi_interleave(cfi)*2) {
2164 + /* X32 chip(s) in X16 mode */
2165 + cfi->addr_unlock1 = 0xaaa;
2167 + cfi->addr_unlock2 = 0xaa8;
2171 + printk(KERN_WARNING
2172 + "MTD %s(): Unsupported device type %d\n",
2173 + __func__, cfi->device_type);
2179 - case CFI_DEVICETYPE_X32:
2180 - cfi->addr_unlock1 = 0x1555;
2181 - cfi->addr_unlock2 = 0xaaa;
2184 - printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0002 device type %d\n", cfi->device_type);
2189 + else if (cfi->cfi_mode == CFI_MODE_JEDEC) {
2190 + /* Apply jedec specific fixups */
2191 + cfi_fixup(mtd, jedec_fixup_table);
2193 + /* Apply generic fixups */
2194 + cfi_fixup(mtd, fixup_table);
2196 for (i=0; i< cfi->numchips; i++) {
2197 cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
2198 @@ -146,135 +329,66 @@
2201 map->fldrv = &cfi_amdstd_chipdrv;
2203 - cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL);
2204 - return cfi_amdstd_setup(map);
2206 + return cfi_amdstd_setup(mtd);
2209 -static struct mtd_info *cfi_amdstd_setup(struct map_info *map)
2211 +static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
2213 + struct map_info *map = mtd->priv;
2214 struct cfi_private *cfi = map->fldrv_priv;
2215 - struct mtd_info *mtd;
2216 unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
2217 + unsigned long offset = 0;
2220 - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
2221 printk(KERN_NOTICE "number of %s chips: %d\n",
2222 - (cfi->cfi_mode == CFI_MODE_CFI)?"CFI":"JEDEC",cfi->numchips);
2223 + (cfi->cfi_mode == CFI_MODE_CFI)?"CFI":"JEDEC",cfi->numchips);
2224 + /* Select the correct geometry setup */
2225 + mtd->size = devsize * cfi->numchips;
2228 - printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
2230 + mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
2231 + mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
2232 + * mtd->numeraseregions, GFP_KERNEL);
2233 + if (!mtd->eraseregions) {
2234 + printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n");
2238 - memset(mtd, 0, sizeof(*mtd));
2240 - mtd->type = MTD_NORFLASH;
2241 - /* Also select the correct geometry setup too */
2242 - mtd->size = devsize * cfi->numchips;
2244 - if (cfi->cfiq->NumEraseRegions == 1) {
2245 - /* No need to muck about with multiple erase sizes */
2246 - mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave;
2248 - unsigned long offset = 0;
2251 - mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
2252 - mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL);
2253 - if (!mtd->eraseregions) {
2254 - printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n");
2258 - for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
2259 - unsigned long ernum, ersize;
2260 - ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
2261 - ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
2262 + for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
2263 + unsigned long ernum, ersize;
2264 + ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
2265 + ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
2267 - if (mtd->erasesize < ersize) {
2268 - mtd->erasesize = ersize;
2270 - for (j=0; j<cfi->numchips; j++) {
2271 - mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
2272 - mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
2273 - mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
2275 - offset += (ersize * ernum);
2277 - if (offset != devsize) {
2279 - printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
2281 + if (mtd->erasesize < ersize) {
2282 + mtd->erasesize = ersize;
2286 - for (i=0; i<mtd->numeraseregions;i++){
2287 - printk("%d: offset=0x%x,size=0x%x,blocks=%d\n",
2288 - i,mtd->eraseregions[i].offset,
2289 - mtd->eraseregions[i].erasesize,
2290 - mtd->eraseregions[i].numblocks);
2295 - switch (CFIDEV_BUSWIDTH)
2301 - if (mtd->numeraseregions > 1)
2302 - mtd->erase = cfi_amdstd_erase_varsize;
2305 - if (((cfi->cfiq->EraseRegionInfo[0] & 0xffff) + 1) == 1)
2306 - mtd->erase = cfi_amdstd_erase_chip;
2308 - mtd->erase = cfi_amdstd_erase_onesize;
2309 - mtd->read = cfi_amdstd_read;
2310 - mtd->write = cfi_amdstd_write;
2314 - printk(KERN_WARNING "Unsupported buswidth\n");
2315 + for (j=0; j<cfi->numchips; j++) {
2316 + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
2317 + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
2318 + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
2320 + offset += (ersize * ernum);
2322 + if (offset != devsize) {
2324 + printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
2328 - if (cfi->fast_prog) {
2329 - /* In cfi_amdstd_write() we frob the protection stuff
2330 - without paying any attention to the state machine.
2331 - This upsets in-progress erases. So we turn this flag
2332 - off for now till the code gets fixed. */
2333 - printk(KERN_NOTICE "cfi_cmdset_0002: Disabling fast programming due to code brokenness.\n");
2334 - cfi->fast_prog = 0;
2337 + for (i=0; i<mtd->numeraseregions;i++){
2338 + printk("%d: offset=0x%x,size=0x%x,blocks=%d\n",
2339 + i,mtd->eraseregions[i].offset,
2340 + mtd->eraseregions[i].erasesize,
2341 + mtd->eraseregions[i].numblocks);
2345 + /* FIXME: erase-suspend-program is broken. See
2346 + http://lists.infradead.org/pipermail/linux-mtd/2003-December/009001.html */
2347 + printk(KERN_NOTICE "cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.\n");
2349 - /* does this chip have a secsi area? */
2360 - mtd->read_user_prot_reg = cfi_amdstd_secsi_read;
2361 - mtd->read_fact_prot_reg = cfi_amdstd_secsi_read;
2368 - mtd->sync = cfi_amdstd_sync;
2369 - mtd->suspend = cfi_amdstd_suspend;
2370 - mtd->resume = cfi_amdstd_resume;
2371 - mtd->flags = MTD_CAP_NORFLASH;
2372 - map->fldrv = &cfi_amdstd_chipdrv;
2373 - mtd->name = map->name;
2374 __module_get(THIS_MODULE);
2377 @@ -289,46 +403,182 @@
2381 -static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
2383 + * Return true if the chip is ready.
2385 + * Ready is one of: read mode, query mode, erase-suspend-read mode (in any
2386 + * non-suspended sector) and is indicated by no toggle bits toggling.
2388 + * Note that anything more complicated than checking if no bits are toggling
2389 + * (including checking DQ5 for an error status) is tricky to get working
2390 + * correctly and is therefore not done (particulary with interleaved chips
2391 + * as each chip must be checked independantly of the others).
2393 +static int chip_ready(struct map_info *map, unsigned long addr)
2397 + d = map_read(map, addr);
2398 + t = map_read(map, addr);
2400 + return map_word_equal(map, d, t);
2403 +static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
2405 DECLARE_WAITQUEUE(wait, current);
2406 - unsigned long timeo = jiffies + HZ;
2407 + struct cfi_private *cfi = map->fldrv_priv;
2408 + unsigned long timeo;
2409 + struct cfi_pri_amdstd *cfip = (struct cfi_pri_amdstd *)cfi->cmdset_priv;
2412 + timeo = jiffies + HZ;
2414 - cfi_spin_lock(chip->mutex);
2415 + switch (chip->state) {
2417 - if (chip->state != FL_READY){
2419 - printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state);
2423 + if (chip_ready(map, adr))
2426 + if (time_after(jiffies, timeo)) {
2427 + printk(KERN_ERR "Waiting for chip to be ready timed out.\n");
2428 + cfi_spin_unlock(chip->mutex);
2431 + cfi_spin_unlock(chip->mutex);
2433 + cfi_spin_lock(chip->mutex);
2434 + /* Someone else might have been playing with it. */
2439 + case FL_CFI_QUERY:
2440 + case FL_JEDEC_QUERY:
2444 + if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */
2447 + if (!(mode == FL_READY || mode == FL_POINT
2449 + || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))
2450 + || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1))))
2453 + /* We could check to see if we're trying to access the sector
2454 + * that is currently being erased. However, no user will try
2455 + * anything like that so we just wait for the timeout. */
2457 + /* Erase suspend */
2458 + /* It's harmless to issue the Erase-Suspend and Erase-Resume
2459 + * commands when the erase algorithm isn't in progress. */
2460 + map_write(map, CMD(0xB0), chip->in_progress_block_addr);
2461 + chip->oldstate = FL_ERASING;
2462 + chip->state = FL_ERASE_SUSPENDING;
2463 + chip->erase_suspended = 1;
2465 + if (chip_ready(map, adr))
2468 + if (time_after(jiffies, timeo)) {
2469 + /* Should have suspended the erase by now.
2470 + * Send an Erase-Resume command as either
2471 + * there was an error (so leave the erase
2472 + * routine to recover from it) or we trying to
2473 + * use the erase-in-progress sector. */
2474 + map_write(map, CMD(0x30), chip->in_progress_block_addr);
2475 + chip->state = FL_ERASING;
2476 + chip->oldstate = FL_READY;
2477 + printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
2481 + cfi_spin_unlock(chip->mutex);
2483 + cfi_spin_lock(chip->mutex);
2484 + /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING.
2485 + So we can just loop here. */
2487 + chip->state = FL_READY;
2491 + /* Only if there's no operation suspended... */
2492 + if (mode == FL_READY && chip->oldstate == FL_READY)
2497 set_current_state(TASK_UNINTERRUPTIBLE);
2498 add_wait_queue(&chip->wq, &wait);
2500 cfi_spin_unlock(chip->mutex);
2503 remove_wait_queue(&chip->wq, &wait);
2505 - if(signal_pending(current))
2508 - timeo = jiffies + HZ;
2509 + cfi_spin_lock(chip->mutex);
2517 +static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr)
2519 + struct cfi_private *cfi = map->fldrv_priv;
2521 + switch(chip->oldstate) {
2523 + chip->state = chip->oldstate;
2524 + map_write(map, CMD(0x30), chip->in_progress_block_addr);
2525 + chip->oldstate = FL_READY;
2526 + chip->state = FL_ERASING;
2531 + /* We should really make set_vpp() count, rather than doing this */
2535 + printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate);
2537 + wake_up(&chip->wq);
2541 +static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
2543 + unsigned long cmd_addr;
2544 + struct cfi_private *cfi = map->fldrv_priv;
2549 - chip->state = FL_READY;
2550 + /* Ensure cmd read/writes are aligned. */
2551 + cmd_addr = adr & ~(map_bankwidth(map)-1);
2553 + cfi_spin_lock(chip->mutex);
2554 + ret = get_chip(map, chip, cmd_addr, FL_READY);
2556 + cfi_spin_unlock(chip->mutex);
2560 + if (chip->state != FL_POINT && chip->state != FL_READY) {
2561 + map_write(map, CMD(0xf0), cmd_addr);
2562 + chip->state = FL_READY;
2565 map_copy_from(map, buf, adr, len);
2567 - wake_up(&chip->wq);
2568 - cfi_spin_unlock(chip->mutex);
2569 + put_chip(map, chip, cmd_addr);
2571 + cfi_spin_unlock(chip->mutex);
2576 static int cfi_amdstd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
2578 struct map_info *map = mtd->priv;
2584 static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
2586 DECLARE_WAITQUEUE(wait, current);
2587 @@ -381,11 +632,11 @@
2589 if (chip->state != FL_READY){
2591 - printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state);
2592 + printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state);
2594 set_current_state(TASK_UNINTERRUPTIBLE);
2595 add_wait_queue(&chip->wq, &wait);
2598 cfi_spin_unlock(chip->mutex);
2601 @@ -402,13 +653,15 @@
2604 chip->state = FL_READY;
2607 + /* should these be CFI_DEVICETYPE_X8 instead of cfi->device_type? */
2608 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
2609 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
2610 cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
2612 map_copy_from(map, buf, adr, len);
2614 + /* should these be CFI_DEVICETYPE_X8 instead of cfi->device_type? */
2615 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
2616 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
2617 cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
2618 @@ -463,215 +716,388 @@
2622 -static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, cfi_word datum, int fast)
2624 +static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum)
2626 - unsigned long timeo = jiffies + HZ;
2627 - unsigned int oldstatus, status, prev_oldstatus, prev_status;
2629 struct cfi_private *cfi = map->fldrv_priv;
2630 - /* We use a 1ms + 1 jiffies generic timeout for writes (most devices have
2631 - a max write time of a few hundreds usec). However, we should use the
2632 - maximum timeout value given by the chip at probe time instead.
2633 - Unfortunately, struct flchip does have a field for maximum timeout,
2634 - only for typical which can be far too short depending of the conditions.
2635 - The ' + 1' is to avoid having a timeout of 0 jiffies if HZ is smaller
2636 - than 1000. Using a static variable allows makes us save the costly
2637 - divide operation at each word write.*/
2638 - static unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
2639 - DECLARE_WAITQUEUE(wait, current);
2640 + unsigned long timeo = jiffies + HZ;
2642 + * We use a 1ms + 1 jiffies generic timeout for writes (most devices
2643 + * have a max write time of a few hundreds usec). However, we should
2644 + * use the maximum timeout value given by the chip at probe time
2645 + * instead. Unfortunately, struct flchip does have a field for
2646 + * maximum timeout, only for typical which can be far too short
2647 + * depending of the conditions. The ' + 1' is to avoid having a
2648 + * timeout of 0 jiffies if HZ is smaller than 1000.
2650 + unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
2653 + map_word oldd, curd;
2654 + int retry_cnt = 0;
2656 + adr += chip->start;
2658 + cfi_spin_lock(chip->mutex);
2659 + ret = get_chip(map, chip, adr, FL_WRITING);
2661 + cfi_spin_unlock(chip->mutex);
2665 + DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
2666 + __func__, adr, datum.x[0] );
2669 + * Check for a NOP for the case when the datum to write is already
2670 + * present - it saves time and works around buggy chips that corrupt
2671 + * data at other locations when 0xff is written to a location that
2672 + * already contains 0xff.
2674 + oldd = map_read(map, adr);
2675 + if (map_word_equal(map, oldd, datum)) {
2676 + DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n",
2684 + * The CFI_DEVICETYPE_X8 argument is needed even when
2685 + * cfi->device_type != CFI_DEVICETYPE_X8. The addresses for
2686 + * command sequences don't scale even when the device is
2687 + * wider. This is the case for many of the cfi_send_gen_cmd()
2688 + * below. I'm not sure, however, why some use
2689 + * cfi->device_type.
2691 + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
2692 + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
2693 + cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
2694 + map_write(map, datum, adr);
2695 + chip->state = FL_WRITING;
2697 + cfi_spin_unlock(chip->mutex);
2698 + cfi_udelay(chip->word_write_time);
2699 cfi_spin_lock(chip->mutex);
2701 - if (chip->state != FL_READY) {
2702 + /* See comment above for timeout value. */
2703 + timeo = jiffies + uWriteTimeout;
2705 + if (chip->state != FL_WRITING) {
2706 + /* Someone's suspended the write. Sleep */
2707 + DECLARE_WAITQUEUE(wait, current);
2709 + set_current_state(TASK_UNINTERRUPTIBLE);
2710 + add_wait_queue(&chip->wq, &wait);
2711 + cfi_spin_unlock(chip->mutex);
2713 + remove_wait_queue(&chip->wq, &wait);
2714 + timeo = jiffies + (HZ / 2); /* FIXME */
2715 + cfi_spin_lock(chip->mutex);
2719 + /* Test to see if toggling has stopped. */
2720 + oldd = map_read(map, adr);
2721 + curd = map_read(map, adr);
2722 + if (map_word_equal(map, curd, oldd)) {
2723 + /* Do we have the correct value? */
2724 + if (map_word_equal(map, curd, datum)) {
2727 + /* Nope something has gone wrong. */
2731 + if (time_after(jiffies, timeo)) {
2732 + printk(KERN_WARNING "MTD %s(): software timeout\n",
2737 + /* Latency issues. Drop the lock, wait a while and retry */
2738 + cfi_spin_unlock(chip->mutex);
2740 + cfi_spin_lock(chip->mutex);
2743 + /* reset on all failures. */
2744 + map_write( map, CMD(0xF0), chip->start );
2745 + /* FIXME - should have reset delay before continuing */
2746 + if (++retry_cnt <= MAX_WORD_RETRIES)
2751 + chip->state = FL_READY;
2752 + put_chip(map, chip, adr);
2753 + cfi_spin_unlock(chip->mutex);
2759 +static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
2760 + size_t *retlen, const u_char *buf)
2762 + struct map_info *map = mtd->priv;
2763 + struct cfi_private *cfi = map->fldrv_priv;
2766 + unsigned long ofs, chipstart;
2767 + DECLARE_WAITQUEUE(wait, current);
2773 + chipnum = to >> cfi->chipshift;
2774 + ofs = to - (chipnum << cfi->chipshift);
2775 + chipstart = cfi->chips[chipnum].start;
2777 + /* If it's not bus-aligned, do the first byte write */
2778 + if (ofs & (map_bankwidth(map)-1)) {
2779 + unsigned long bus_ofs = ofs & ~(map_bankwidth(map)-1);
2780 + int i = ofs - bus_ofs;
2785 + cfi_spin_lock(cfi->chips[chipnum].mutex);
2787 + if (cfi->chips[chipnum].state != FL_READY) {
2789 - printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", chip->state);
2790 + printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
2792 - set_current_state(TASK_UNINTERRUPTIBLE);
2793 - add_wait_queue(&chip->wq, &wait);
2795 - cfi_spin_unlock(chip->mutex);
2796 + set_current_state(TASK_UNINTERRUPTIBLE);
2797 + add_wait_queue(&cfi->chips[chipnum].wq, &wait);
2800 - remove_wait_queue(&chip->wq, &wait);
2801 + cfi_spin_unlock(cfi->chips[chipnum].mutex);
2804 + remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
2806 - printk(KERN_DEBUG "Wake up to write:\n");
2807 - if(signal_pending(current))
2809 + if(signal_pending(current))
2812 - timeo = jiffies + HZ;
2818 + /* Load 'tmp_buf' with old contents of flash */
2819 + tmp_buf = map_read(map, bus_ofs+chipstart);
2821 - chip->state = FL_WRITING;
2822 + cfi_spin_unlock(cfi->chips[chipnum].mutex);
2824 + /* Number of bytes to copy from buffer */
2825 + n = min_t(int, len, map_bankwidth(map)-i);
2827 + tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);
2829 + ret = do_write_oneword(map, &cfi->chips[chipnum],
2830 + bus_ofs, tmp_buf);
2839 + if (ofs >> cfi->chipshift) {
2842 + if (chipnum == cfi->numchips)
2847 + /* We are now aligned, write as much as possible */
2848 + while(len >= map_bankwidth(map)) {
2851 + datum = map_word_load(map, buf);
2853 + ret = do_write_oneword(map, &cfi->chips[chipnum],
2858 + ofs += map_bankwidth(map);
2859 + buf += map_bankwidth(map);
2860 + (*retlen) += map_bankwidth(map);
2861 + len -= map_bankwidth(map);
2863 + if (ofs >> cfi->chipshift) {
2866 + if (chipnum == cfi->numchips)
2868 + chipstart = cfi->chips[chipnum].start;
2872 + /* Write the trailing bytes if any */
2873 + if (len & (map_bankwidth(map)-1)) {
2877 + cfi_spin_lock(cfi->chips[chipnum].mutex);
2879 + if (cfi->chips[chipnum].state != FL_READY) {
2881 + printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
2883 + set_current_state(TASK_UNINTERRUPTIBLE);
2884 + add_wait_queue(&cfi->chips[chipnum].wq, &wait);
2886 + cfi_spin_unlock(cfi->chips[chipnum].mutex);
2889 + remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
2891 + if(signal_pending(current))
2897 + tmp_buf = map_read(map, ofs + chipstart);
2899 + cfi_spin_unlock(cfi->chips[chipnum].mutex);
2901 + tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);
2903 + ret = do_write_oneword(map, &cfi->chips[chipnum],
2916 + * FIXME: interleaved mode not tested, and probably not supported!
2918 +static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
2919 + unsigned long adr, const u_char *buf, int len)
2921 + struct cfi_private *cfi = map->fldrv_priv;
2922 + unsigned long timeo = jiffies + HZ;
2923 + /* see comments in do_write_oneword() regarding uWriteTimeo. */
2924 + unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
2926 + unsigned long cmd_adr;
2931 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8x)\n",
2932 - __func__, adr, datum );
2936 - if (fast) { /* Unlock bypass */
2937 - cfi_send_gen_cmd(0xA0, 0, chip->start, map, cfi, cfi->device_type, NULL);
2938 + cfi_spin_lock(chip->mutex);
2939 + ret = get_chip(map, chip, adr, FL_WRITING);
2941 + cfi_spin_unlock(chip->mutex);
2945 - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
2946 - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
2947 - cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
2949 + datum = map_word_load(map, buf);
2951 + DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
2952 + __func__, adr, datum.x[0] );
2955 + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
2956 + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
2957 + //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
2959 + /* Write Buffer Load */
2960 + map_write(map, CMD(0x25), cmd_adr);
2962 + chip->state = FL_WRITING_TO_BUFFER;
2964 + /* Write length of data to come */
2965 + words = len / map_bankwidth(map);
2966 + map_write(map, CMD(words - 1), cmd_adr);
2969 + while(z < words * map_bankwidth(map)) {
2970 + datum = map_word_load(map, buf);
2971 + map_write(map, datum, adr + z);
2973 + z += map_bankwidth(map);
2974 + buf += map_bankwidth(map);
2976 - cfi_write(map, datum, adr);
2977 + z -= map_bankwidth(map);
2981 + /* Write Buffer Program Confirm: GO GO GO */
2982 + map_write(map, CMD(0x29), cmd_adr);
2983 + chip->state = FL_WRITING;
2985 cfi_spin_unlock(chip->mutex);
2986 - cfi_udelay(chip->word_write_time);
2987 + cfi_udelay(chip->buffer_write_time);
2988 cfi_spin_lock(chip->mutex);
2991 - * Polling toggle bits instead of reading back many times
2992 - * This ensures that write operation is really completed,
2993 - * or tells us why it failed.
2995 - * It appears tha the polling and decoding of error state might
2996 - * be simplified. Don't do it unless you really know what you
2997 - * are doing. You must remember that JESD21-C 3.5.3 states that
2998 - * the status must be read back an _additional_ two times before
2999 - * a failure is determined. This is because these devices have
3000 - * internal state machines that are asynchronous to the external
3001 - * data bus. During an erase or write the read-back status of the
3002 - * polling bits might be transitioning internaly when the external
3003 - * read-back occurs. This means that the bits aren't in the final
3004 - * state and they might appear to report an error as they transition
3005 - * and are in a weird state. This will produce infrequent errors
3006 - * that will usually disappear the next time an erase or write
3007 - * happens (Try tracking those errors down!). To ensure that
3008 - * the bits are not in transition the location must be read-back
3009 - * two more times and compared against what was written - BOTH reads
3010 - * MUST match what was written - don't think this can be simplified
3011 - * to only the last read matching. If the comparison fails, error
3012 - * state can then be decoded.
3014 - * - Thayne Harbaugh
3017 - /* See comment above for timeout value. */
3018 timeo = jiffies + uWriteTimeout;
3020 - oldstatus = cfi_read(map, adr);
3021 - status = cfi_read(map, adr);
3022 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3023 - __func__, oldstatus, status );
3026 - * This only checks if dq6 is still toggling and that our
3027 - * timer hasn't expired. We purposefully ignore the chips
3028 - * internal timer that will assert dq5 and leave dq6 toggling.
3029 - * This is done for a variety of reasons:
3030 - * 1) Not all chips support dq5.
3031 - * 2) Dealing with asynchronous status bit and data updates
3032 - * and reading a device two more times creates _messy_
3033 - * logic when trying to deal with interleaved devices -
3034 - * some may be changing while others are still busy.
3035 - * 3) Checking dq5 only helps to optimize an error case that
3036 - * should at worst be infrequent and at best non-existent.
3038 - * If our timeout occurs _then_ we will check dq5 to see
3039 - * if the device also had an internal timeout.
3041 - while( ( ( status ^ oldstatus ) & dq6 )
3042 - && ! ( ta = time_after(jiffies, timeo) ) ) {
3045 + if (chip->state != FL_WRITING) {
3046 + /* Someone's suspended the write. Sleep */
3047 + DECLARE_WAITQUEUE(wait, current);
3049 - if (need_resched()) {
3050 + set_current_state(TASK_UNINTERRUPTIBLE);
3051 + add_wait_queue(&chip->wq, &wait);
3052 cfi_spin_unlock(chip->mutex);
3055 + remove_wait_queue(&chip->wq, &wait);
3056 + timeo = jiffies + (HZ / 2); /* FIXME */
3057 cfi_spin_lock(chip->mutex);
3063 - oldstatus = cfi_read( map, adr );
3064 - status = cfi_read( map, adr );
3065 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3066 - __func__, oldstatus, status );
3068 + if (chip_ready(map, adr))
3071 + if( time_after(jiffies, timeo))
3075 - * Something kicked us out of the read-back loop. We'll
3076 - * check success befor checking failure.
3077 - * Even though dq6 might be true data, it is unkown if
3078 - * all of the other bits have changed to true data due to
3079 - * the asynchronous nature of the internal state machine.
3080 - * We will read two more times and use this to either
3081 - * verify that the write completed successfully or
3082 - * that something really went wrong. BOTH reads
3083 - * must match what was written - this certifies that
3084 - * bits aren't still changing and that the status
3085 - * bits erroneously match the datum that was written.
3087 - prev_oldstatus = oldstatus;
3088 - prev_status = status;
3089 - oldstatus = cfi_read(map, adr);
3090 - status = cfi_read(map, adr);
3091 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3092 - __func__, oldstatus, status );
3094 - if ( oldstatus == datum && status == datum ) {
3095 - /* success - do nothing */
3100 - int dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1;
3101 - if ( status & dq5mask ) {
3102 - /* dq5 asserted - decode interleave chips */
3103 - printk( KERN_WARNING
3104 - "MTD %s(): FLASH internal timeout: 0x%.8x\n",
3106 - status & dq5mask );
3108 - printk( KERN_WARNING
3109 - "MTD %s(): Software timed out during write.\n",
3112 - goto write_failed;
3113 + /* Latency issues. Drop the lock, wait a while and retry */
3114 + cfi_spin_unlock(chip->mutex);
3116 + cfi_spin_lock(chip->mutex);
3120 - * If we get to here then it means that something
3121 - * is wrong and it's not a timeout. Something
3122 - * is seriously wacky! Dump some debug info.
3124 - printk(KERN_WARNING
3125 - "MTD %s(): Wacky! Unable to decode failure status\n",
3126 + printk(KERN_WARNING "MTD %s(): software timeout\n",
3129 - printk(KERN_WARNING
3130 - "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
3131 - __func__, adr, datum,
3132 - prev_oldstatus, prev_status,
3133 - oldstatus, status);
3137 /* reset on all failures. */
3138 - cfi_write( map, CMD(0xF0), chip->start );
3139 + map_write( map, CMD(0xF0), chip->start );
3140 /* FIXME - should have reset delay before continuing */
3146 chip->state = FL_READY;
3147 - wake_up(&chip->wq);
3148 + put_chip(map, chip, adr);
3149 cfi_spin_unlock(chip->mutex);
3154 -static int cfi_amdstd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
3156 +static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
3157 + size_t *retlen, const u_char *buf)
3159 struct map_info *map = mtd->priv;
3160 struct cfi_private *cfi = map->fldrv_priv;
3161 + int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
3164 - unsigned long ofs, chipstart;
3165 + unsigned long ofs;
3169 @@ -679,176 +1105,94 @@
3171 chipnum = to >> cfi->chipshift;
3172 ofs = to - (chipnum << cfi->chipshift);
3173 - chipstart = cfi->chips[chipnum].start;
3175 - /* If it's not bus-aligned, do the first byte write */
3176 - if (ofs & (CFIDEV_BUSWIDTH-1)) {
3177 - unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1);
3178 - int i = ofs - bus_ofs;
3180 - u_char tmp_buf[8];
3183 - map_copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
3184 - while (len && i < CFIDEV_BUSWIDTH)
3185 - tmp_buf[i++] = buf[n++], len--;
3187 - if (cfi_buswidth_is_2()) {
3188 - datum = *(__u16*)tmp_buf;
3189 - } else if (cfi_buswidth_is_4()) {
3190 - datum = *(__u32*)tmp_buf;
3192 - return -EINVAL; /* should never happen, but be safe */
3195 - ret = do_write_oneword(map, &cfi->chips[chipnum],
3196 - bus_ofs, datum, 0);
3198 + /* If it's not bus-aligned, do the first word write */
3199 + if (ofs & (map_bankwidth(map)-1)) {
3200 + size_t local_len = (-ofs)&(map_bankwidth(map)-1);
3201 + if (local_len > len)
3203 + ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<<cfi->chipshift),
3204 + local_len, retlen, buf);
3215 if (ofs >> cfi->chipshift) {
3219 if (chipnum == cfi->numchips)
3224 - if (cfi->fast_prog) {
3225 - /* Go into unlock bypass mode */
3226 - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL);
3227 - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL);
3228 - cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL);
3231 - /* We are now aligned, write as much as possible */
3232 - while(len >= CFIDEV_BUSWIDTH) {
3234 + /* Write buffer is worth it only if more than one word to write... */
3235 + while (len >= map_bankwidth(map) * 2) {
3236 + /* We must not cross write block boundaries */
3237 + int size = wbufsize - (ofs & (wbufsize-1));
3241 + if (size % map_bankwidth(map))
3242 + size -= size % map_bankwidth(map);
3244 - if (cfi_buswidth_is_1()) {
3245 - datum = *(__u8*)buf;
3246 - } else if (cfi_buswidth_is_2()) {
3247 - datum = *(__u16*)buf;
3248 - } else if (cfi_buswidth_is_4()) {
3249 - datum = *(__u32*)buf;
3253 - ret = do_write_oneword(map, &cfi->chips[chipnum],
3254 - ofs, datum, cfi->fast_prog);
3256 - if (cfi->fast_prog){
3257 - /* Get out of unlock bypass mode */
3258 - cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
3259 - cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
3261 + ret = do_write_buffer(map, &cfi->chips[chipnum],
3267 - ofs += CFIDEV_BUSWIDTH;
3268 - buf += CFIDEV_BUSWIDTH;
3269 - (*retlen) += CFIDEV_BUSWIDTH;
3270 - len -= CFIDEV_BUSWIDTH;
3273 + (*retlen) += size;
3276 if (ofs >> cfi->chipshift) {
3277 - if (cfi->fast_prog){
3278 - /* Get out of unlock bypass mode */
3279 - cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
3280 - cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
3285 if (chipnum == cfi->numchips)
3287 - chipstart = cfi->chips[chipnum].start;
3288 - if (cfi->fast_prog){
3289 - /* Go into unlock bypass mode for next set of chips */
3290 - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL);
3291 - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL);
3292 - cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL);
3297 - if (cfi->fast_prog){
3298 - /* Get out of unlock bypass mode */
3299 - cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
3300 - cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
3303 + size_t retlen_dregs = 0;
3305 - /* Write the trailing bytes if any */
3306 - if (len & (CFIDEV_BUSWIDTH-1)) {
3308 - u_char tmp_buf[8];
3311 - map_copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
3313 - tmp_buf[i++] = buf[n++];
3315 - if (cfi_buswidth_is_2()) {
3316 - datum = *(__u16*)tmp_buf;
3317 - } else if (cfi_buswidth_is_4()) {
3318 - datum = *(__u32*)tmp_buf;
3320 - return -EINVAL; /* should never happen, but be safe */
3322 + ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<<cfi->chipshift),
3323 + len, &retlen_dregs, buf);
3325 - ret = do_write_oneword(map, &cfi->chips[chipnum],
3331 + *retlen += retlen_dregs;
3340 + * Handle devices with one erase region, that only implement
3341 + * the chip erase command.
3343 static inline int do_erase_chip(struct map_info *map, struct flchip *chip)
3345 - unsigned int oldstatus, status, prev_oldstatus, prev_status;
3347 + struct cfi_private *cfi = map->fldrv_priv;
3348 unsigned long timeo = jiffies + HZ;
3349 unsigned long int adr;
3350 - struct cfi_private *cfi = map->fldrv_priv;
3351 DECLARE_WAITQUEUE(wait, current);
3354 - cfi_word ones = 0;
3357 - cfi_spin_lock(chip->mutex);
3358 + adr = cfi->addr_unlock1;
3360 - if (chip->state != FL_READY){
3361 - set_current_state(TASK_UNINTERRUPTIBLE);
3362 - add_wait_queue(&chip->wq, &wait);
3364 + cfi_spin_lock(chip->mutex);
3365 + ret = get_chip(map, chip, adr, FL_WRITING);
3367 cfi_spin_unlock(chip->mutex);
3372 - remove_wait_queue(&chip->wq, &wait);
3374 - if(signal_pending(current))
3377 - timeo = jiffies + HZ;
3382 - chip->state = FL_ERASING;
3383 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
3384 __func__, chip->start );
3386 - /* Handle devices with one erase region, that only implement
3387 - * the chip erase command.
3391 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
3392 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
3393 @@ -856,175 +1200,82 @@
3394 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
3395 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
3396 cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
3397 - timeo = jiffies + (HZ*20);
3398 - adr = cfi->addr_unlock1;
3400 - /* Wait for the end of programing/erasure by using the toggle method.
3401 - * As long as there is a programming procedure going on, bit 6
3402 - * is toggling it's state with each consecutive read.
3403 - * The toggling stops as soon as the procedure is completed.
3405 - * If the process has gone on for too long on the chip bit 5 gets.
3406 - * After bit5 is set you can kill the operation by sending a reset
3407 - * command to the chip.
3409 - /* see comments in do_write_oneword */
3411 + chip->state = FL_ERASING;
3412 + chip->erase_suspended = 0;
3413 + chip->in_progress_block_addr = adr;
3415 - oldstatus = cfi_read(map, adr);
3416 - status = cfi_read(map, adr);
3417 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3418 - __func__, oldstatus, status );
3420 - while( ( ( status ^ oldstatus ) & dq6 )
3421 - && ! ( ta = time_after(jiffies, timeo) ) ) {
3423 + cfi_spin_unlock(chip->mutex);
3424 + set_current_state(TASK_UNINTERRUPTIBLE);
3425 + schedule_timeout((chip->erase_time*HZ)/(2*1000));
3426 + cfi_spin_lock(chip->mutex);
3428 - /* an initial short sleep */
3429 - cfi_spin_unlock(chip->mutex);
3430 - schedule_timeout(HZ/100);
3431 - cfi_spin_lock(chip->mutex);
3433 + timeo = jiffies + (HZ*20);
3436 if (chip->state != FL_ERASING) {
3437 /* Someone's suspended the erase. Sleep */
3438 set_current_state(TASK_UNINTERRUPTIBLE);
3439 add_wait_queue(&chip->wq, &wait);
3441 cfi_spin_unlock(chip->mutex);
3442 - printk("erase suspended. Sleeping\n");
3445 remove_wait_queue(&chip->wq, &wait);
3447 - if (signal_pending(current))
3450 - timeo = jiffies + (HZ*2); /* FIXME */
3451 cfi_spin_lock(chip->mutex);
3454 + if (chip->erase_suspended) {
3455 + /* This erase was suspended and resumed.
3456 + Adjust the timeout */
3457 + timeo = jiffies + (HZ*20); /* FIXME */
3458 + chip->erase_suspended = 0;
3461 - /* Busy wait for 1/10 of a milisecond */
3462 - for(wait_reps = 0;
3464 - && ( ( status ^ oldstatus ) & dq6 );
3467 - /* Latency issues. Drop the lock, wait a while and retry */
3468 - cfi_spin_unlock(chip->mutex);
3471 + if (chip_ready(map, adr))
3474 - cfi_spin_lock(chip->mutex);
3475 - oldstatus = cfi_read(map, adr);
3476 - status = cfi_read(map, adr);
3477 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3478 - __func__, oldstatus, status );
3480 - oldstatus = cfi_read(map, adr);
3481 - status = cfi_read(map, adr);
3482 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3483 - __func__, oldstatus, status );
3486 - prev_oldstatus = oldstatus;
3487 - prev_status = status;
3488 - oldstatus = cfi_read(map, adr);
3489 - status = cfi_read(map, adr);
3490 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3491 - __func__, oldstatus, status );
3493 - if ( cfi_buswidth_is_1() ) {
3495 - } else if ( cfi_buswidth_is_2() ) {
3497 - } else if ( cfi_buswidth_is_4() ) {
3500 - printk(KERN_WARNING "Unsupported buswidth\n");
3501 - goto erase_failed;
3504 - if ( oldstatus == ones && status == ones ) {
3505 - /* success - do nothing */
3508 + if (time_after(jiffies, timeo))
3512 - int dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1;
3513 - if ( status & dq5mask ) {
3514 - /* dq5 asserted - decode interleave chips */
3515 - printk( KERN_WARNING
3516 - "MTD %s(): FLASH internal timeout: 0x%.8x\n",
3518 - status & dq5mask );
3520 - printk( KERN_WARNING
3521 - "MTD %s(): Software timed out during write.\n",
3524 - goto erase_failed;
3525 + /* Latency issues. Drop the lock, wait a while and retry */
3526 + cfi_spin_unlock(chip->mutex);
3527 + set_current_state(TASK_UNINTERRUPTIBLE);
3528 + schedule_timeout(1);
3529 + cfi_spin_lock(chip->mutex);
3532 - printk(KERN_WARNING
3533 - "MTD %s(): Wacky! Unable to decode failure status\n",
3534 + printk(KERN_WARNING "MTD %s(): software timeout\n",
3537 - printk(KERN_WARNING
3538 - "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
3539 - __func__, adr, ones,
3540 - prev_oldstatus, prev_status,
3541 - oldstatus, status);
3545 /* reset on all failures. */
3546 - cfi_write( map, CMD(0xF0), chip->start );
3547 + map_write( map, CMD(0xF0), chip->start );
3548 /* FIXME - should have reset delay before continuing */
3554 chip->state = FL_READY;
3555 - wake_up(&chip->wq);
3556 + put_chip(map, chip, adr);
3557 cfi_spin_unlock(chip->mutex);
3563 -static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
3564 +static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk)
3566 - unsigned int oldstatus, status, prev_oldstatus, prev_status;
3568 - unsigned long timeo = jiffies + HZ;
3569 struct cfi_private *cfi = map->fldrv_priv;
3570 + unsigned long timeo = jiffies + HZ;
3571 DECLARE_WAITQUEUE(wait, current);
3574 - cfi_word ones = 0;
3577 - cfi_spin_lock(chip->mutex);
3578 + adr += chip->start;
3580 - if (chip->state != FL_READY){
3581 - set_current_state(TASK_UNINTERRUPTIBLE);
3582 - add_wait_queue(&chip->wq, &wait);
3584 + cfi_spin_lock(chip->mutex);
3585 + ret = get_chip(map, chip, adr, FL_ERASING);
3587 cfi_spin_unlock(chip->mutex);
3592 - remove_wait_queue(&chip->wq, &wait);
3594 - if(signal_pending(current))
3597 - timeo = jiffies + HZ;
3602 - chip->state = FL_ERASING;
3604 - adr += chip->start;
3605 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
3608 @@ -1034,279 +1285,85 @@
3609 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
3610 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
3611 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
3612 + map_write(map, CMD(0x30), adr);
3614 - cfi_write(map, CMD(0x30), adr);
3615 + chip->state = FL_ERASING;
3616 + chip->erase_suspended = 0;
3617 + chip->in_progress_block_addr = adr;
3619 - timeo = jiffies + (HZ*20);
3621 - /* Wait for the end of programing/erasure by using the toggle method.
3622 - * As long as there is a programming procedure going on, bit 6
3623 - * is toggling it's state with each consecutive read.
3624 - * The toggling stops as soon as the procedure is completed.
3626 - * If the process has gone on for too long on the chip bit 5 gets.
3627 - * After bit5 is set you can kill the operation by sending a reset
3628 - * command to the chip.
3630 - /* see comments in do_write_oneword */
3632 + cfi_spin_unlock(chip->mutex);
3633 + set_current_state(TASK_UNINTERRUPTIBLE);
3634 + schedule_timeout((chip->erase_time*HZ)/(2*1000));
3635 + cfi_spin_lock(chip->mutex);
3637 - oldstatus = cfi_read(map, adr);
3638 - status = cfi_read(map, adr);
3639 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3640 - __func__, oldstatus, status );
3642 - while( ( ( status ^ oldstatus ) & dq6 )
3643 - && ! ( ta = time_after(jiffies, timeo) ) ) {
3645 + timeo = jiffies + (HZ*20);
3647 - /* an initial short sleep */
3648 - cfi_spin_unlock(chip->mutex);
3649 - schedule_timeout(HZ/100);
3650 - cfi_spin_lock(chip->mutex);
3653 if (chip->state != FL_ERASING) {
3654 /* Someone's suspended the erase. Sleep */
3655 set_current_state(TASK_UNINTERRUPTIBLE);
3656 add_wait_queue(&chip->wq, &wait);
3658 cfi_spin_unlock(chip->mutex);
3659 - printk(KERN_DEBUG "erase suspended. Sleeping\n");
3662 remove_wait_queue(&chip->wq, &wait);
3664 - if (signal_pending(current))
3667 - timeo = jiffies + (HZ*2); /* FIXME */
3668 cfi_spin_lock(chip->mutex);
3672 - /* Busy wait for 1/10 of a milisecond */
3673 - for(wait_reps = 0;
3675 - && ( ( status ^ oldstatus ) & dq6 );
3678 - /* Latency issues. Drop the lock, wait a while and retry */
3679 - cfi_spin_unlock(chip->mutex);
3683 - cfi_spin_lock(chip->mutex);
3684 - oldstatus = cfi_read(map, adr);
3685 - status = cfi_read(map, adr);
3686 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3687 - __func__, oldstatus, status );
3689 - oldstatus = cfi_read(map, adr);
3690 - status = cfi_read(map, adr);
3691 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3692 - __func__, oldstatus, status );
3695 - prev_oldstatus = oldstatus;
3696 - prev_status = status;
3697 - oldstatus = cfi_read(map, adr);
3698 - status = cfi_read(map, adr);
3699 - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
3700 - __func__, oldstatus, status );
3702 - if ( cfi_buswidth_is_1() ) {
3704 - } else if ( cfi_buswidth_is_2() ) {
3706 - } else if ( cfi_buswidth_is_4() ) {
3709 - printk(KERN_WARNING "Unsupported buswidth\n");
3710 - goto erase_failed;
3713 - if ( oldstatus == ones && status == ones ) {
3714 - /* success - do nothing */
3719 - int dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1;
3720 - if ( status & dq5mask ) {
3721 - /* dq5 asserted - decode interleave chips */
3722 - printk( KERN_WARNING
3723 - "MTD %s(): FLASH internal timeout: 0x%.8x\n",
3725 - status & dq5mask );
3727 - printk( KERN_WARNING
3728 - "MTD %s(): Software timed out during write.\n",
3730 + if (chip->erase_suspended) {
3731 + /* This erase was suspended and resumed.
3732 + Adjust the timeout */
3733 + timeo = jiffies + (HZ*20); /* FIXME */
3734 + chip->erase_suspended = 0;
3736 - goto erase_failed;
3739 - printk(KERN_WARNING
3740 - "MTD %s(): Wacky! Unable to decode failure status\n",
3742 + if (chip_ready(map, adr))
3745 - printk(KERN_WARNING
3746 - "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
3747 - __func__, adr, ones,
3748 - prev_oldstatus, prev_status,
3749 - oldstatus, status);
3750 + if (time_after(jiffies, timeo))
3755 + /* Latency issues. Drop the lock, wait a while and retry */
3756 + cfi_spin_unlock(chip->mutex);
3757 + set_current_state(TASK_UNINTERRUPTIBLE);
3758 + schedule_timeout(1);
3759 + cfi_spin_lock(chip->mutex);
3762 + printk(KERN_WARNING "MTD %s(): software timeout\n",
3765 /* reset on all failures. */
3766 - cfi_write( map, CMD(0xF0), chip->start );
3767 + map_write( map, CMD(0xF0), chip->start );
3768 /* FIXME - should have reset delay before continuing */
3774 chip->state = FL_READY;
3775 - wake_up(&chip->wq);
3776 + put_chip(map, chip, adr);
3777 cfi_spin_unlock(chip->mutex);
3781 -static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
3783 - struct map_info *map = mtd->priv;
3784 - struct cfi_private *cfi = map->fldrv_priv;
3785 - unsigned long adr, len;
3786 - int chipnum, ret = 0;
3788 - struct mtd_erase_region_info *regions = mtd->eraseregions;
3790 - if (instr->addr > mtd->size)
3793 - if ((instr->len + instr->addr) > mtd->size)
3796 - /* Check that both start and end of the requested erase are
3797 - * aligned with the erasesize at the appropriate addresses.
3802 - /* Skip all erase regions which are ended before the start of
3803 - the requested erase. Actually, to save on the calculations,
3804 - we skip to the first erase region which starts after the
3805 - start of the requested erase, and then go back one.
3808 - while (i < mtd->numeraseregions && instr->addr >= regions[i].offset)
3812 - /* OK, now i is pointing at the erase region in which this
3813 - erase request starts. Check the start of the requested
3814 - erase range is aligned with the erase size which is in
3818 - if (instr->addr & (regions[i].erasesize-1))
3821 - /* Remember the erase region we start on */
3824 - /* Next, check that the end of the requested erase is aligned
3825 - * with the erase region at that address.
3828 - while (i<mtd->numeraseregions && (instr->addr + instr->len) >= regions[i].offset)
3831 - /* As before, drop back one to point at the region in which
3832 - the address actually falls
3836 - if ((instr->addr + instr->len) & (regions[i].erasesize-1))
3839 - chipnum = instr->addr >> cfi->chipshift;
3840 - adr = instr->addr - (chipnum << cfi->chipshift);
3846 - ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
3851 - adr += regions[i].erasesize;
3852 - len -= regions[i].erasesize;
3854 - if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
3857 - if (adr >> cfi->chipshift) {
3861 - if (chipnum >= cfi->numchips)
3866 - instr->state = MTD_ERASE_DONE;
3867 - if (instr->callback)
3868 - instr->callback(instr);
3873 -static int cfi_amdstd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr)
3874 +int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
3876 - struct map_info *map = mtd->priv;
3877 - struct cfi_private *cfi = map->fldrv_priv;
3878 - unsigned long adr, len;
3879 - int chipnum, ret = 0;
3881 - if (instr->addr & (mtd->erasesize - 1))
3884 - if (instr->len & (mtd->erasesize -1))
3887 - if ((instr->len + instr->addr) > mtd->size)
3889 + unsigned long ofs, len;
3892 - chipnum = instr->addr >> cfi->chipshift;
3893 - adr = instr->addr - (chipnum << cfi->chipshift);
3894 + ofs = instr->addr;
3898 - ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
3903 - adr += mtd->erasesize;
3904 - len -= mtd->erasesize;
3905 + ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
3909 - if (adr >> cfi->chipshift) {
3913 - if (chipnum >= cfi->numchips)
3918 instr->state = MTD_ERASE_DONE;
3919 - if (instr->callback)
3920 - instr->callback(instr);
3921 + mtd_erase_callback(instr);
3927 static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
3929 struct map_info *map = mtd->priv;
3930 @@ -1324,12 +1381,12 @@
3933 instr->state = MTD_ERASE_DONE;
3934 - if (instr->callback)
3935 - instr->callback(instr);
3936 + mtd_erase_callback(instr);
3942 static void cfi_amdstd_sync (struct mtd_info *mtd)
3944 struct map_info *map = mtd->priv;
3945 @@ -1368,7 +1425,7 @@
3949 - remove_wait_queue(&chip->wq, &wait);
3950 + remove_wait_queue(&chip->wq, &wait);
3954 @@ -1427,7 +1484,7 @@
3955 /* Unlock the chips again */
3958 - for (i--; i >=0; i--) {
3959 + for (i--; i >=0; i--) {
3960 chip = &cfi->chips[i];
3962 cfi_spin_lock(chip->mutex);
3963 @@ -1443,6 +1500,7 @@
3968 static void cfi_amdstd_resume(struct mtd_info *mtd)
3970 struct map_info *map = mtd->priv;
3971 @@ -1458,7 +1516,7 @@
3973 if (chip->state == FL_PM_SUSPENDED) {
3974 chip->state = FL_READY;
3975 - cfi_write(map, CMD(0xF0), chip->start);
3976 + map_write(map, CMD(0xF0), chip->start);
3980 @@ -1480,21 +1538,23 @@
3982 static char im_name[]="cfi_cmdset_0002";
3985 int __init cfi_amdstd_init(void)
3987 inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002);
3992 static void __exit cfi_amdstd_exit(void)
3994 inter_module_unregister(im_name);
3998 module_init(cfi_amdstd_init);
3999 module_exit(cfi_amdstd_exit);
4001 MODULE_LICENSE("GPL");
4002 MODULE_AUTHOR("Crossnet Co. <info@crossnet.co.jp> et al.");
4003 MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips");
4005 Index: linux-2.6.5/drivers/mtd/chips/cfi_cmdset_0020.c
4006 ===================================================================
4007 --- linux-2.6.5.orig/drivers/mtd/chips/cfi_cmdset_0020.c 2004-04-03 22:36:55.000000000 -0500
4008 +++ linux-2.6.5/drivers/mtd/chips/cfi_cmdset_0020.c 2005-02-01 17:11:17.000000000 -0500
4011 * (C) 2000 Red Hat. GPL'd
4013 + * $Id: cfi_cmdset_0020.c,v 1.15 2004/08/09 13:19:43 dwmw2 Exp $
4015 * 10/10/2000 Nicolas Pitre <nico@cam.org>
4016 * - completely revamped method functions so they are aware and
4019 static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
4020 static int cfi_staa_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
4021 -static int cfi_staa_writev(struct mtd_info *mtd, const struct iovec *vecs,
4022 +static int cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs,
4023 unsigned long count, loff_t to, size_t *retlen);
4024 static int cfi_staa_erase_varsize(struct mtd_info *, struct erase_info *);
4025 static void cfi_staa_sync (struct mtd_info *);
4028 struct cfi_private *cfi = map->fldrv_priv;
4030 - __u32 base = cfi->chips[0].start;
4032 if (cfi->cfi_mode) {
4034 @@ -126,36 +126,11 @@
4036 __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
4037 struct cfi_pri_intelext *extp;
4038 - int ofs_factor = cfi->interleave * cfi->device_type;
4040 - printk(" ST Microelectronics Extended Query Table at 0x%4.4X\n", adr);
4042 + extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "ST Microelectronics");
4046 - /* Switch it into Query Mode */
4047 - cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
4049 - extp = kmalloc(sizeof(*extp), GFP_KERNEL);
4051 - printk(KERN_ERR "Failed to allocate memory\n");
4055 - /* Read in the Extended Query Table */
4056 - for (i=0; i<sizeof(*extp); i++) {
4057 - ((unsigned char *)extp)[i] =
4058 - cfi_read_query(map, (base+((adr+i)*ofs_factor)));
4061 - if (extp->MajorVersion != '1' ||
4062 - (extp->MinorVersion < '0' || extp->MinorVersion > '2')) {
4063 - printk(KERN_WARNING " Unknown staa Extended Query "
4064 - "version %c.%c.\n", extp->MajorVersion,
4065 - extp->MinorVersion);
4070 /* Do some byteswapping if necessary */
4071 extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport);
4072 extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask);
4074 cfi->chips[i].erase_time = 1024;
4077 - /* Make sure it's in read mode */
4078 - cfi_send_gen_cmd(0xff, 0x55, base, map, cfi, cfi->device_type, NULL);
4079 return cfi_staa_setup(map);
4084 static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
4086 - __u32 status, status_OK;
4087 + map_word status, status_OK;
4088 unsigned long timeo;
4089 DECLARE_WAITQUEUE(wait, current);
4094 /* Ensure cmd read/writes are aligned. */
4095 - cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1);
4096 + cmd_addr = adr & ~(map_bankwidth(map)-1);
4098 /* Let's determine this according to the interleave only once */
4099 status_OK = CMD(0x80);
4100 @@ -290,33 +263,33 @@
4102 switch (chip->state) {
4104 - if (!((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2)
4105 + if (!(((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2))
4106 goto sleep; /* We don't support erase suspend */
4108 - cfi_write (map, CMD(0xb0), cmd_addr);
4109 + map_write (map, CMD(0xb0), cmd_addr);
4110 /* If the flash has finished erasing, then 'erase suspend'
4111 * appears to make some (28F320) flash devices switch to
4112 * 'read' mode. Make sure that we switch to 'read status'
4113 * mode so we get the right data. --rmk
4115 - cfi_write(map, CMD(0x70), cmd_addr);
4116 + map_write(map, CMD(0x70), cmd_addr);
4117 chip->oldstate = FL_ERASING;
4118 chip->state = FL_ERASE_SUSPENDING;
4119 // printk("Erase suspending at 0x%lx\n", cmd_addr);
4121 - status = cfi_read(map, cmd_addr);
4122 - if ((status & status_OK) == status_OK)
4123 + status = map_read(map, cmd_addr);
4124 + if (map_word_andequal(map, status, status_OK, status_OK))
4127 if (time_after(jiffies, timeo)) {
4129 - cfi_write(map, CMD(0xd0), cmd_addr);
4130 + map_write(map, CMD(0xd0), cmd_addr);
4131 /* make sure we're in 'read status' mode */
4132 - cfi_write(map, CMD(0x70), cmd_addr);
4133 + map_write(map, CMD(0x70), cmd_addr);
4134 chip->state = FL_ERASING;
4135 spin_unlock_bh(chip->mutex);
4136 printk(KERN_ERR "Chip not ready after erase "
4137 - "suspended: status = 0x%x\n", status);
4138 + "suspended: status = 0x%lx\n", status.x[0]);
4146 - cfi_write(map, CMD(0xff), cmd_addr);
4147 + map_write(map, CMD(0xff), cmd_addr);
4148 chip->state = FL_READY;
4151 @@ -340,13 +313,13 @@
4154 case FL_JEDEC_QUERY:
4155 - cfi_write(map, CMD(0x70), cmd_addr);
4156 + map_write(map, CMD(0x70), cmd_addr);
4157 chip->state = FL_STATUS;
4160 - status = cfi_read(map, cmd_addr);
4161 - if ((status & status_OK) == status_OK) {
4162 - cfi_write(map, CMD(0xff), cmd_addr);
4163 + status = map_read(map, cmd_addr);
4164 + if (map_word_andequal(map, status, status_OK, status_OK)) {
4165 + map_write(map, CMD(0xff), cmd_addr);
4166 chip->state = FL_READY;
4170 /* Urgh. Chip not yet ready to talk to us. */
4171 if (time_after(jiffies, timeo)) {
4172 spin_unlock_bh(chip->mutex);
4173 - printk(KERN_ERR "waiting for chip to be ready timed out in read. WSM status = %x\n", status);
4174 + printk(KERN_ERR "waiting for chip to be ready timed out in read. WSM status = %lx\n", status.x[0]);
4179 sending the 0x70 (Read Status) command to an erasing
4180 chip and expecting it to be ignored, that's what we
4182 - cfi_write(map, CMD(0xd0), cmd_addr);
4183 - cfi_write(map, CMD(0x70), cmd_addr);
4184 + map_write(map, CMD(0xd0), cmd_addr);
4185 + map_write(map, CMD(0x70), cmd_addr);
4189 @@ -441,16 +414,16 @@
4190 unsigned long adr, const u_char *buf, int len)
4192 struct cfi_private *cfi = map->fldrv_priv;
4193 - __u32 status, status_OK;
4194 + map_word status, status_OK;
4195 unsigned long cmd_adr, timeo;
4196 DECLARE_WAITQUEUE(wait, current);
4199 /* M58LW064A requires bus alignment for buffer wriets -- saw */
4200 - if (adr & (CFIDEV_BUSWIDTH-1))
4201 + if (adr & (map_bankwidth(map)-1))
4204 - wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize;
4205 + wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
4207 cmd_adr = adr & ~(wbufsize-1);
4209 @@ -476,21 +449,21 @@
4212 case FL_JEDEC_QUERY:
4213 - cfi_write(map, CMD(0x70), cmd_adr);
4214 + map_write(map, CMD(0x70), cmd_adr);
4215 chip->state = FL_STATUS;
4216 #ifdef DEBUG_CFI_FEATURES
4217 - printk("%s: 1 status[%x]\n", __FUNCTION__, cfi_read(map, cmd_adr));
4218 + printk("%s: 1 status[%x]\n", __FUNCTION__, map_read(map, cmd_adr));
4222 - status = cfi_read(map, cmd_adr);
4223 - if ((status & status_OK) == status_OK)
4224 + status = map_read(map, cmd_adr);
4225 + if (map_word_andequal(map, status, status_OK, status_OK))
4227 /* Urgh. Chip not yet ready to talk to us. */
4228 if (time_after(jiffies, timeo)) {
4229 spin_unlock_bh(chip->mutex);
4230 - printk(KERN_ERR "waiting for chip to be ready timed out in buffer write Xstatus = %x, status = %x\n",
4231 - status, cfi_read(map, cmd_adr));
4232 + printk(KERN_ERR "waiting for chip to be ready timed out in buffer write Xstatus = %lx, status = %lx\n",
4233 + status.x[0], map_read(map, cmd_adr).x[0]);
4237 @@ -512,13 +485,13 @@
4241 - cfi_write(map, CMD(0xe8), cmd_adr);
4242 + map_write(map, CMD(0xe8), cmd_adr);
4243 chip->state = FL_WRITING_TO_BUFFER;
4247 - status = cfi_read(map, cmd_adr);
4248 - if ((status & status_OK) == status_OK)
4249 + status = map_read(map, cmd_adr);
4250 + if (map_word_andequal(map, status, status_OK, status_OK))
4253 spin_unlock_bh(chip->mutex);
4254 @@ -528,41 +501,26 @@
4256 /* Argh. Not ready for write to buffer */
4258 - cfi_write(map, CMD(0x70), cmd_adr);
4259 + map_write(map, CMD(0x70), cmd_adr);
4260 chip->state = FL_STATUS;
4261 spin_unlock_bh(chip->mutex);
4262 - printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %x\n", status);
4263 + printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %lx\n", status.x[0]);
4268 /* Write length of data to come */
4269 - cfi_write(map, CMD(len/CFIDEV_BUSWIDTH-1), cmd_adr );
4270 + map_write(map, CMD(len/map_bankwidth(map)-1), cmd_adr );
4273 - for (z = 0; z < len; z += CFIDEV_BUSWIDTH) {
4274 - if (cfi_buswidth_is_1()) {
4275 - u8 *b = (u8 *)buf;
4277 - map_write8 (map, *b++, adr+z);
4278 - buf = (const u_char *)b;
4279 - } else if (cfi_buswidth_is_2()) {
4280 - u16 *b = (u16 *)buf;
4282 - map_write16 (map, *b++, adr+z);
4283 - buf = (const u_char *)b;
4284 - } else if (cfi_buswidth_is_4()) {
4285 - u32 *b = (u32 *)buf;
4287 - map_write32 (map, *b++, adr+z);
4288 - buf = (const u_char *)b;
4293 + for (z = 0; z < len;
4294 + z += map_bankwidth(map), buf += map_bankwidth(map)) {
4296 + d = map_word_load(map, buf);
4297 + map_write(map, d, adr+z);
4300 - cfi_write(map, CMD(0xd0), cmd_adr);
4301 + map_write(map, CMD(0xd0), cmd_adr);
4302 chip->state = FL_WRITING;
4304 spin_unlock_bh(chip->mutex);
4305 @@ -584,16 +542,16 @@
4309 - status = cfi_read(map, cmd_adr);
4310 - if ((status & status_OK) == status_OK)
4311 + status = map_read(map, cmd_adr);
4312 + if (map_word_andequal(map, status, status_OK, status_OK))
4315 /* OK Still waiting */
4316 if (time_after(jiffies, timeo)) {
4318 - cfi_write(map, CMD(0x50), cmd_adr);
4319 + map_write(map, CMD(0x50), cmd_adr);
4320 /* put back into read status register mode */
4321 - cfi_write(map, CMD(0x70), adr);
4322 + map_write(map, CMD(0x70), adr);
4323 chip->state = FL_STATUS;
4325 spin_unlock_bh(chip->mutex);
4326 @@ -620,19 +578,18 @@
4327 chip->state = FL_STATUS;
4329 /* check for errors: 'lock bit', 'VPP', 'dead cell'/'unerased cell' or 'incorrect cmd' -- saw */
4330 - if ((status & CMD(0x02)) || (status & CMD(0x08)) ||
4331 - (status & CMD(0x10)) || (status & CMD(0x20))) {
4332 + if (map_word_bitsset(map, status, CMD(0x3a))) {
4333 #ifdef DEBUG_CFI_FEATURES
4334 - printk("%s: 2 status[%x]\n", __FUNCTION__, status);
4335 + printk("%s: 2 status[%lx]\n", __FUNCTION__, status.x[0]);
4337 - /* clear status */
4338 - cfi_write(map, CMD(0x50), cmd_adr);
4339 - /* put back into read status register mode */
4340 - cfi_write(map, CMD(0x70), adr);
4341 - wake_up(&chip->wq);
4342 - spin_unlock_bh(chip->mutex);
4343 - return (status & CMD(0x02)) ? -EROFS : -EIO;
4345 + /* clear status */
4346 + map_write(map, CMD(0x50), cmd_adr);
4347 + /* put back into read status register mode */
4348 + map_write(map, CMD(0x70), adr);
4349 + wake_up(&chip->wq);
4350 + spin_unlock_bh(chip->mutex);
4351 + return map_word_bitsset(map, status, CMD(0x02)) ? -EROFS : -EIO;
4354 spin_unlock_bh(chip->mutex);
4358 struct map_info *map = mtd->priv;
4359 struct cfi_private *cfi = map->fldrv_priv;
4360 - int wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize;
4361 + int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
4366 ofs = to - (chipnum << cfi->chipshift);
4368 #ifdef DEBUG_CFI_FEATURES
4369 - printk("%s: CFIDEV_BUSWIDTH[%x]\n", __FUNCTION__, CFIDEV_BUSWIDTH);
4370 + printk("%s: map_bankwidth(map)[%x]\n", __FUNCTION__, map_bankwidth(map));
4371 printk("%s: chipnum[%x] wbufsize[%x]\n", __FUNCTION__, chipnum, wbufsize);
4372 printk("%s: ofs[%x] len[%x]\n", __FUNCTION__, ofs, len);
4375 #define ECCBUF_DIV(x) ((x) & ~(ECCBUF_SIZE - 1))
4376 #define ECCBUF_MOD(x) ((x) & (ECCBUF_SIZE - 1))
4378 -cfi_staa_writev(struct mtd_info *mtd, const struct iovec *vecs,
4379 +cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs,
4380 unsigned long count, loff_t to, size_t *retlen)
4384 static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
4386 struct cfi_private *cfi = map->fldrv_priv;
4387 - __u32 status, status_OK;
4388 + map_word status, status_OK;
4389 unsigned long timeo;
4391 DECLARE_WAITQUEUE(wait, current);
4392 @@ -789,12 +746,12 @@
4394 case FL_JEDEC_QUERY:
4396 - cfi_write(map, CMD(0x70), adr);
4397 + map_write(map, CMD(0x70), adr);
4398 chip->state = FL_STATUS;
4401 - status = cfi_read(map, adr);
4402 - if ((status & status_OK) == status_OK)
4403 + status = map_read(map, adr);
4404 + if (map_word_andequal(map, status, status_OK, status_OK))
4407 /* Urgh. Chip not yet ready to talk to us. */
4408 @@ -823,11 +780,11 @@
4411 /* Clear the status register first */
4412 - cfi_write(map, CMD(0x50), adr);
4413 + map_write(map, CMD(0x50), adr);
4416 - cfi_write(map, CMD(0x20), adr);
4417 - cfi_write(map, CMD(0xD0), adr);
4418 + map_write(map, CMD(0x20), adr);
4419 + map_write(map, CMD(0xD0), adr);
4420 chip->state = FL_ERASING;
4422 spin_unlock_bh(chip->mutex);
4423 @@ -851,15 +808,15 @@
4427 - status = cfi_read(map, adr);
4428 - if ((status & status_OK) == status_OK)
4429 + status = map_read(map, adr);
4430 + if (map_word_andequal(map, status, status_OK, status_OK))
4433 /* OK Still waiting */
4434 if (time_after(jiffies, timeo)) {
4435 - cfi_write(map, CMD(0x70), adr);
4436 + map_write(map, CMD(0x70), adr);
4437 chip->state = FL_STATUS;
4438 - printk(KERN_ERR "waiting for erase to complete timed out. Xstatus = %x, status = %x.\n", status, cfi_read(map, adr));
4439 + printk(KERN_ERR "waiting for erase to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]);
4441 spin_unlock_bh(chip->mutex);
4443 @@ -875,43 +832,46 @@
4446 /* We've broken this before. It doesn't hurt to be safe */
4447 - cfi_write(map, CMD(0x70), adr);
4448 + map_write(map, CMD(0x70), adr);
4449 chip->state = FL_STATUS;
4450 - status = cfi_read(map, adr);
4451 + status = map_read(map, adr);
4453 /* check for lock bit */
4454 - if (status & CMD(0x3a)) {
4455 - unsigned char chipstatus = status;
4456 - if (status != CMD(status & 0xff)) {
4458 - for (i = 1; i<CFIDEV_INTERLEAVE; i++) {
4459 - chipstatus |= status >> (cfi->device_type * 8);
4460 + if (map_word_bitsset(map, status, CMD(0x3a))) {
4461 + unsigned char chipstatus = status.x[0];
4462 + if (!map_word_equal(map, status, CMD(chipstatus))) {
4464 + for (w=0; w<map_words(map); w++) {
4465 + for (i = 0; i<cfi_interleave(cfi); i++) {
4466 + chipstatus |= status.x[w] >> (cfi->device_type * 8);
4469 - printk(KERN_WARNING "Status is not identical for all chips: 0x%x. Merging to give 0x%02x\n", status, chipstatus);
4470 + printk(KERN_WARNING "Status is not identical for all chips: 0x%lx. Merging to give 0x%02x\n",
4471 + status.x[0], chipstatus);
4473 /* Reset the error bits */
4474 - cfi_write(map, CMD(0x50), adr);
4475 - cfi_write(map, CMD(0x70), adr);
4476 + map_write(map, CMD(0x50), adr);
4477 + map_write(map, CMD(0x70), adr);
4479 if ((chipstatus & 0x30) == 0x30) {
4480 - printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%x\n", status);
4481 + printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%x\n", chipstatus);
4483 } else if (chipstatus & 0x02) {
4484 /* Protection bit set */
4486 } else if (chipstatus & 0x8) {
4488 - printk(KERN_WARNING "Chip reports voltage low on erase: status 0x%x\n", status);
4489 + printk(KERN_WARNING "Chip reports voltage low on erase: status 0x%x\n", chipstatus);
4491 } else if (chipstatus & 0x20) {
4493 - printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x. Retrying...\n", adr, status);
4494 + printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x. Retrying...\n", adr, chipstatus);
4495 timeo = jiffies + HZ;
4496 chip->state = FL_STATUS;
4497 spin_unlock_bh(chip->mutex);
4500 - printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x\n", adr, status);
4501 + printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x\n", adr, chipstatus);
4505 @@ -1006,8 +966,7 @@
4508 instr->state = MTD_ERASE_DONE;
4509 - if (instr->callback)
4510 - instr->callback(instr);
4511 + mtd_erase_callback(instr);
4515 @@ -1072,7 +1031,7 @@
4516 static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
4518 struct cfi_private *cfi = map->fldrv_priv;
4519 - __u32 status, status_OK;
4520 + map_word status, status_OK;
4521 unsigned long timeo = jiffies + HZ;
4522 DECLARE_WAITQUEUE(wait, current);
4524 @@ -1090,12 +1049,12 @@
4526 case FL_JEDEC_QUERY:
4528 - cfi_write(map, CMD(0x70), adr);
4529 + map_write(map, CMD(0x70), adr);
4530 chip->state = FL_STATUS;
4533 - status = cfi_read(map, adr);
4534 - if ((status & status_OK) == status_OK)
4535 + status = map_read(map, adr);
4536 + if (map_word_andequal(map, status, status_OK, status_OK))
4539 /* Urgh. Chip not yet ready to talk to us. */
4540 @@ -1123,8 +1082,8 @@
4544 - cfi_write(map, CMD(0x60), adr);
4545 - cfi_write(map, CMD(0x01), adr);
4546 + map_write(map, CMD(0x60), adr);
4547 + map_write(map, CMD(0x01), adr);
4548 chip->state = FL_LOCKING;
4550 spin_unlock_bh(chip->mutex);
4551 @@ -1137,15 +1096,15 @@
4552 timeo = jiffies + (HZ*2);
4555 - status = cfi_read(map, adr);
4556 - if ((status & status_OK) == status_OK)
4557 + status = map_read(map, adr);
4558 + if (map_word_andequal(map, status, status_OK, status_OK))
4561 /* OK Still waiting */
4562 if (time_after(jiffies, timeo)) {
4563 - cfi_write(map, CMD(0x70), adr);
4564 + map_write(map, CMD(0x70), adr);
4565 chip->state = FL_STATUS;
4566 - printk(KERN_ERR "waiting for lock to complete timed out. Xstatus = %x, status = %x.\n", status, cfi_read(map, adr));
4567 + printk(KERN_ERR "waiting for lock to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]);
4569 spin_unlock_bh(chip->mutex);
4571 @@ -1221,7 +1180,7 @@
4572 static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
4574 struct cfi_private *cfi = map->fldrv_priv;
4575 - __u32 status, status_OK;
4576 + map_word status, status_OK;
4577 unsigned long timeo = jiffies + HZ;
4578 DECLARE_WAITQUEUE(wait, current);
4580 @@ -1239,12 +1198,12 @@
4582 case FL_JEDEC_QUERY:
4584 - cfi_write(map, CMD(0x70), adr);
4585 + map_write(map, CMD(0x70), adr);
4586 chip->state = FL_STATUS;
4589 - status = cfi_read(map, adr);
4590 - if ((status & status_OK) == status_OK)
4591 + status = map_read(map, adr);
4592 + if (map_word_andequal(map, status, status_OK, status_OK))
4595 /* Urgh. Chip not yet ready to talk to us. */
4596 @@ -1272,8 +1231,8 @@
4600 - cfi_write(map, CMD(0x60), adr);
4601 - cfi_write(map, CMD(0xD0), adr);
4602 + map_write(map, CMD(0x60), adr);
4603 + map_write(map, CMD(0xD0), adr);
4604 chip->state = FL_UNLOCKING;
4606 spin_unlock_bh(chip->mutex);
4607 @@ -1286,15 +1245,15 @@
4608 timeo = jiffies + (HZ*2);
4611 - status = cfi_read(map, adr);
4612 - if ((status & status_OK) == status_OK)
4613 + status = map_read(map, adr);
4614 + if (map_word_andequal(map, status, status_OK, status_OK))
4617 /* OK Still waiting */
4618 if (time_after(jiffies, timeo)) {
4619 - cfi_write(map, CMD(0x70), adr);
4620 + map_write(map, CMD(0x70), adr);
4621 chip->state = FL_STATUS;
4622 - printk(KERN_ERR "waiting for unlock to complete timed out. Xstatus = %x, status = %x.\n", status, cfi_read(map, adr));
4623 + printk(KERN_ERR "waiting for unlock to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]);
4625 spin_unlock_bh(chip->mutex);
4627 @@ -1423,7 +1382,7 @@
4629 /* Go to known state. Chip may have been power cycled */
4630 if (chip->state == FL_PM_SUSPENDED) {
4631 - cfi_write(map, CMD(0xFF), 0);
4632 + map_write(map, CMD(0xFF), 0);
4633 chip->state = FL_READY;
4636 @@ -1440,11 +1399,6 @@
4640 -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
4641 -#define cfi_staa_init init_module
4642 -#define cfi_staa_exit cleanup_module
4645 static char im_name[]="cfi_cmdset_0020";
4647 int __init cfi_staa_init(void)
4648 Index: linux-2.6.5/drivers/mtd/chips/cfi_probe.c
4649 ===================================================================
4650 --- linux-2.6.5.orig/drivers/mtd/chips/cfi_probe.c 2004-04-03 22:37:40.000000000 -0500
4651 +++ linux-2.6.5/drivers/mtd/chips/cfi_probe.c 2005-02-01 17:11:17.000000000 -0500
4654 Common Flash Interface probe code.
4655 (C) 2000 Red Hat. GPL'd.
4656 - $Id: cfi_probe.c,v 1.71 2003/05/28 12:51:48 dwmw2 Exp $
4657 + $Id: cfi_probe.c,v 1.77 2004/07/14 08:38:44 dwmw2 Exp $
4660 #include <linux/config.h>
4664 static int cfi_probe_chip(struct map_info *map, __u32 base,
4665 - struct flchip *chips, struct cfi_private *cfi);
4666 + unsigned long *chip_map, struct cfi_private *cfi);
4667 static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi);
4669 struct mtd_info *cfi_probe(struct map_info *map);
4671 in: interleave,type,mode
4672 ret: table index, <0 for error
4674 -static inline int qry_present(struct map_info *map, __u32 base,
4675 +static int qry_present(struct map_info *map, __u32 base,
4676 struct cfi_private *cfi)
4678 int osf = cfi->interleave * cfi->device_type; // scale factor
4682 - if (cfi_read(map,base+osf*0x10)==cfi_build_cmd('Q',map,cfi) &&
4683 - cfi_read(map,base+osf*0x11)==cfi_build_cmd('R',map,cfi) &&
4684 - cfi_read(map,base+osf*0x12)==cfi_build_cmd('Y',map,cfi))
4686 + qry = cfi_build_cmd('Q', map, cfi);
4687 + val = map_read(map, base + osf*0x10);
4689 - return 0; // nothing found
4690 + if (!map_word_equal(map, qry, val))
4693 + qry = cfi_build_cmd('R', map, cfi);
4694 + val = map_read(map, base + osf*0x11);
4696 + if (!map_word_equal(map, qry, val))
4699 + qry = cfi_build_cmd('Y', map, cfi);
4700 + val = map_read(map, base + osf*0x12);
4702 + if (!map_word_equal(map, qry, val))
4705 + return 1; // nothing found
4708 static int cfi_probe_chip(struct map_info *map, __u32 base,
4709 - struct flchip *chips, struct cfi_private *cfi)
4710 + unsigned long *chip_map, struct cfi_private *cfi)
4717 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
4718 + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
4719 cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
4721 if (!qry_present(map,base,cfi))
4725 /* Check each previous chip to see if it's an alias */
4726 - for (i=0; i<cfi->numchips; i++) {
4727 + for (i=0; i < (base >> cfi->chipshift); i++) {
4728 + unsigned long start;
4729 + if(!test_bit(i, chip_map)) {
4730 + /* Skip location; no valid chip at this address */
4733 + start = i << cfi->chipshift;
4734 /* This chip should be in read mode if it's one
4735 we've already touched. */
4736 - if (qry_present(map,chips[i].start,cfi)) {
4737 + if (qry_present(map, start, cfi)) {
4738 /* Eep. This chip also had the QRY marker.
4739 * Is it an alias for the new one? */
4740 - cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL);
4741 + cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL);
4742 + cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
4744 /* If the QRY marker goes away, it's an alias */
4745 - if (!qry_present(map, chips[i].start, cfi)) {
4746 + if (!qry_present(map, start, cfi)) {
4747 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
4748 - map->name, base, chips[i].start);
4749 + map->name, base, start);
4752 /* Yes, it's actually got QRY for data. Most
4753 @@ -97,10 +120,11 @@
4754 * too and if it's the same, assume it's an alias. */
4755 /* FIXME: Use other modes to do a proper check */
4756 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
4757 + cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
4759 if (qry_present(map, base, cfi)) {
4760 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
4761 - map->name, base, chips[i].start);
4762 + map->name, base, start);
4766 @@ -108,21 +132,16 @@
4768 /* OK, if we got to here, then none of the previous chips appear to
4769 be aliases for the current one. */
4770 - if (cfi->numchips == MAX_CFI_CHIPS) {
4771 - printk(KERN_WARNING"%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS);
4772 - /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */
4775 - chips[cfi->numchips].start = base;
4776 - chips[cfi->numchips].state = FL_READY;
4777 + set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
4780 /* Put it back into Read Mode */
4781 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
4782 + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
4784 - printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n",
4785 + printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
4786 map->name, cfi->interleave, cfi->device_type*8, base,
4788 + map->bankwidth*8);
4793 memset(cfi->cfiq,0,sizeof(struct cfi_ident));
4795 cfi->cfi_mode = CFI_MODE_CFI;
4796 - cfi->fast_prog=1; /* CFI supports fast programming */
4798 /* Read the CFI info structure */
4799 for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) {
4800 @@ -180,8 +198,29 @@
4801 (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);
4805 + /* Note we put the device back into Read Mode BEFORE going into Auto
4806 + * Select Mode, as some devices support nesting of modes, others
4807 + * don't. This way should always work.
4808 + * On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and
4809 + * so should be treated as nops or illegal (and so put the device
4810 + * back into Read Mode, which is a nop in this case).
4812 + cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
4813 + cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL);
4814 + cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
4815 + cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
4816 + cfi->mfr = cfi_read_query(map, base);
4817 + cfi->id = cfi_read_query(map, base + ofs_factor);
4819 /* Put it back into Read Mode */
4820 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
4821 + /* ... even if it's an Intel chip */
4822 + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
4824 + printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
4825 + map->name, cfi->interleave, cfi->device_type*8, base,
4826 + map->bankwidth*8);
4830 @@ -241,11 +280,11 @@
4831 printk("No Alternate Algorithm Table\n");
4834 - printk("Vcc Minimum: %x.%x V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf);
4835 - printk("Vcc Maximum: %x.%x V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf);
4836 + printk("Vcc Minimum: %2d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf);
4837 + printk("Vcc Maximum: %2d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf);
4839 - printk("Vpp Minimum: %x.%x V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf);
4840 - printk("Vpp Maximum: %x.%x V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf);
4841 + printk("Vpp Minimum: %2d.%d V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf);
4842 + printk("Vpp Maximum: %2d.%d V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf);
4845 printk("No Vpp line\n");
4846 Index: linux-2.6.5/drivers/mtd/chips/cfi_util.c
4847 ===================================================================
4848 --- linux-2.6.5.orig/drivers/mtd/chips/cfi_util.c 1969-12-31 19:00:00.000000000 -0500
4849 +++ linux-2.6.5/drivers/mtd/chips/cfi_util.c 2005-02-01 17:11:17.000000000 -0500
4852 + * Common Flash Interface support:
4853 + * Generic utility functions not dependant on command set
4855 + * Copyright (C) 2002 Red Hat
4856 + * Copyright (C) 2003 STMicroelectronics Limited
4858 + * This code is covered by the GPL.
4860 + * $Id: cfi_util.c,v 1.5 2004/08/12 06:40:23 eric Exp $
4864 +#include <linux/module.h>
4865 +#include <linux/types.h>
4866 +#include <linux/kernel.h>
4867 +#include <linux/sched.h>
4868 +#include <asm/io.h>
4869 +#include <asm/byteorder.h>
4871 +#include <linux/errno.h>
4872 +#include <linux/slab.h>
4873 +#include <linux/delay.h>
4874 +#include <linux/interrupt.h>
4875 +#include <linux/mtd/mtd.h>
4876 +#include <linux/mtd/map.h>
4877 +#include <linux/mtd/cfi.h>
4878 +#include <linux/mtd/compatmac.h>
4880 +struct cfi_extquery *
4881 +cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name)
4883 + struct cfi_private *cfi = map->fldrv_priv;
4884 + __u32 base = 0; // cfi->chips[0].start;
4885 + int ofs_factor = cfi->interleave * cfi->device_type;
4887 + struct cfi_extquery *extp = NULL;
4889 + printk(" %s Extended Query Table at 0x%4.4X\n", name, adr);
4893 + /* Switch it into Query Mode */
4894 + cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
4896 + extp = kmalloc(size, GFP_KERNEL);
4898 + printk(KERN_ERR "Failed to allocate memory\n");
4902 + /* Read in the Extended Query Table */
4903 + for (i=0; i<size; i++) {
4904 + ((unsigned char *)extp)[i] =
4905 + cfi_read_query(map, base+((adr+i)*ofs_factor));
4908 + if (extp->MajorVersion != '1' ||
4909 + (extp->MinorVersion < '0' || extp->MinorVersion > '3')) {
4910 + printk(KERN_WARNING " Unknown %s Extended Query "
4911 + "version %c.%c.\n", name, extp->MajorVersion,
4912 + extp->MinorVersion);
4919 + /* Make sure it's in read mode */
4920 + cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
4921 + cfi_send_gen_cmd(0xff, 0, base, map, cfi, cfi->device_type, NULL);
4926 +EXPORT_SYMBOL(cfi_read_pri);
4928 +void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup *fixups)
4930 + struct map_info *map = mtd->priv;
4931 + struct cfi_private *cfi = map->fldrv_priv;
4932 + struct cfi_fixup *f;
4934 + for (f=fixups; f->fixup; f++) {
4935 + if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) &&
4936 + ((f->id == CFI_ID_ANY) || (f->id == cfi->id))) {
4937 + f->fixup(mtd, f->param);
4942 +EXPORT_SYMBOL(cfi_fixup);
4944 +int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
4945 + loff_t ofs, size_t len, void *thunk)
4947 + struct map_info *map = mtd->priv;
4948 + struct cfi_private *cfi = map->fldrv_priv;
4949 + unsigned long adr;
4950 + int chipnum, ret = 0;
4952 + struct mtd_erase_region_info *regions = mtd->eraseregions;
4954 + if (ofs > mtd->size)
4957 + if ((len + ofs) > mtd->size)
4960 + /* Check that both start and end of the requested erase are
4961 + * aligned with the erasesize at the appropriate addresses.
4966 + /* Skip all erase regions which are ended before the start of
4967 + the requested erase. Actually, to save on the calculations,
4968 + we skip to the first erase region which starts after the
4969 + start of the requested erase, and then go back one.
4972 + while (i < mtd->numeraseregions && ofs >= regions[i].offset)
4976 + /* OK, now i is pointing at the erase region in which this
4977 + erase request starts. Check the start of the requested
4978 + erase range is aligned with the erase size which is in
4982 + if (ofs & (regions[i].erasesize-1))
4985 + /* Remember the erase region we start on */
4988 + /* Next, check that the end of the requested erase is aligned
4989 + * with the erase region at that address.
4992 + while (i<mtd->numeraseregions && (ofs + len) >= regions[i].offset)
4995 + /* As before, drop back one to point at the region in which
4996 + the address actually falls
5000 + if ((ofs + len) & (regions[i].erasesize-1))
5003 + chipnum = ofs >> cfi->chipshift;
5004 + adr = ofs - (chipnum << cfi->chipshift);
5009 + unsigned long chipmask;
5010 + int size = regions[i].erasesize;
5012 + ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk);
5020 + chipmask = (1 << cfi->chipshift) - 1;
5021 + if ((adr & chipmask) == ((regions[i].offset + size * regions[i].numblocks) & chipmask))
5024 + if (adr >> cfi->chipshift) {
5028 + if (chipnum >= cfi->numchips)
5036 +EXPORT_SYMBOL(cfi_varsize_frob);
5038 +MODULE_LICENSE("GPL");
5039 Index: linux-2.6.5/drivers/mtd/chips/chipreg.c
5040 ===================================================================
5041 --- linux-2.6.5.orig/drivers/mtd/chips/chipreg.c 2004-04-03 22:36:56.000000000 -0500
5042 +++ linux-2.6.5/drivers/mtd/chips/chipreg.c 2005-02-01 17:11:17.000000000 -0500
5045 - * $Id: chipreg.c,v 1.15 2003/05/21 15:15:05 dwmw2 Exp $
5046 + * $Id: chipreg.c,v 1.16 2003/05/29 09:36:15 dwmw2 Exp $
5048 * Registration for chip drivers
5050 Index: linux-2.6.5/drivers/mtd/chips/fwh_lock.h
5051 ===================================================================
5052 --- linux-2.6.5.orig/drivers/mtd/chips/fwh_lock.h 1969-12-31 19:00:00.000000000 -0500
5053 +++ linux-2.6.5/drivers/mtd/chips/fwh_lock.h 2005-02-01 17:11:17.000000000 -0500
5059 +enum fwh_lock_state {
5061 + FWH_DENY_WRITE = 1,
5062 + FWH_IMMUTABLE = 2,
5063 + FWH_DENY_READ = 4,
5066 +struct fwh_xxlock_thunk {
5067 + enum fwh_lock_state val;
5072 +#define FWH_XXLOCK_ONEBLOCK_LOCK ((struct fwh_xxlock_thunk){ FWH_DENY_WRITE, FL_LOCKING})
5073 +#define FWH_XXLOCK_ONEBLOCK_UNLOCK ((struct fwh_xxlock_thunk){ FWH_UNLOCKED, FL_UNLOCKING})
5076 + * This locking/unlock is specific to firmware hub parts. Only one
5077 + * is known that supports the Intel command set. Firmware
5078 + * hub parts cannot be interleaved as they are on the LPC bus
5079 + * so this code has not been tested with interleaved chips,
5080 + * and will likely fail in that context.
5082 +static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
5083 + unsigned long adr, int len, void *thunk)
5085 + struct cfi_private *cfi = map->fldrv_priv;
5086 + struct fwh_xxlock_thunk *xxlt = (struct fwh_xxlock_thunk *)thunk;
5089 + /* Refuse the operation if the we cannot look behind the chip */
5090 + if (chip->start < 0x400000) {
5091 + DEBUG( MTD_DEBUG_LEVEL3,
5092 + "MTD %s(): chip->start: %lx wanted >= 0x400000\n",
5093 + __func__, chip->start );
5097 + * lock block registers:
5098 + * - on 64k boundariesand
5099 + * - bit 1 set high
5100 + * - block lock registers are 4MiB lower - overflow subtract (danger)
5102 + * The address manipulation is first done on the logical address
5103 + * which is 0 at the start of the chip, and then the offset of
5104 + * the individual chip is addted to it. Any other order a weird
5105 + * map offset could cause problems.
5107 + adr = (adr & ~0xffffUL) | 0x2;
5108 + adr += chip->start - 0x400000;
5111 + * This is easy because these are writes to registers and not writes
5112 + * to flash memory - that means that we don't have to check status
5115 + cfi_spin_lock(chip->mutex);
5116 + ret = get_chip(map, chip, adr, FL_LOCKING);
5118 + cfi_spin_unlock(chip->mutex);
5122 + chip->state = xxlt->state;
5123 + map_write(map, CMD(xxlt->val), adr);
5125 + /* Done and happy. */
5126 + chip->state = FL_READY;
5127 + put_chip(map, chip, adr);
5128 + cfi_spin_unlock(chip->mutex);
5133 +static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
5137 + ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
5138 + (void *)&FWH_XXLOCK_ONEBLOCK_LOCK);
5144 +static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
5148 + ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
5149 + (void *)&FWH_XXLOCK_ONEBLOCK_UNLOCK);
5154 +static void fixup_use_fwh_lock(struct mtd_info *mtd, void *param)
5156 + printk(KERN_NOTICE "using fwh lock/unlock method\n");
5157 + /* Setup for the chips with the fwh lock method */
5158 + mtd->lock = fwh_lock_varsize;
5159 + mtd->unlock = fwh_unlock_varsize;
5161 +#endif /* FWH_LOCK_H */
5162 Index: linux-2.6.5/drivers/mtd/chips/gen_probe.c
5163 ===================================================================
5164 --- linux-2.6.5.orig/drivers/mtd/chips/gen_probe.c 2005-02-01 16:55:45.000000000 -0500
5165 +++ linux-2.6.5/drivers/mtd/chips/gen_probe.c 2005-02-01 17:11:17.000000000 -0500
5167 * Routines common to all CFI-type probes.
5168 * (C) 2001-2003 Red Hat, Inc.
5170 - * $Id: gen_probe.c,v 1.13 2003/06/25 11:50:37 dwmw2 Exp $
5171 + * $Id: gen_probe.c,v 1.21 2004/08/14 15:14:05 dwmw2 Exp $
5174 #include <linux/kernel.h>
5176 EXPORT_SYMBOL(mtd_do_chip_probe);
5179 -struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)
5180 +static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)
5182 - unsigned long base=0;
5183 struct cfi_private cfi;
5184 struct cfi_private *retcfi;
5185 - struct flchip chip[MAX_CFI_CHIPS];
5187 + unsigned long *chip_map;
5188 + int i, j, mapsize;
5191 memset(&cfi, 0, sizeof(cfi));
5192 - memset(&chip[0], 0, sizeof(chip));
5194 /* Call the probetype-specific code with all permutations of
5195 interleave and device type, etc. */
5196 if (!genprobe_new_chip(map, cp, &cfi)) {
5197 /* The probe didn't like it */
5198 - DEBUG(MTD_DEBUG_LEVEL3,
5199 - "MTD %s(): %s: Found no %s device at location zero\n",
5200 - __func__, cp->name, map->name);
5201 + printk(KERN_DEBUG "%s: Found no %s device at location zero\n",
5202 + cp->name, map->name);
5210 - chip[0].start = 0;
5211 - chip[0].state = FL_READY;
5212 cfi.chipshift = cfi.cfiq->DevSize;
5214 - switch(cfi.interleave) {
5215 -#ifdef CFIDEV_INTERLEAVE_1
5219 -#ifdef CFIDEV_INTERLEAVE_2
5221 + if (cfi_interleave_is_1(&cfi)) {
5223 + } else if (cfi_interleave_is_2(&cfi)) {
5227 -#ifdef CFIDEV_INTERLEAVE_4
5233 + } else if (cfi_interleave_is_4((&cfi))) {
5234 + cfi.chipshift += 2;
5235 + } else if (cfi_interleave_is_8(&cfi)) {
5236 + cfi.chipshift += 3;
5244 + * Allocate memory for bitmap of valid chips.
5245 + * Align bitmap storage size to full byte.
5247 + max_chips = map->size >> cfi.chipshift;
5248 + mapsize = (max_chips / 8) + ((max_chips % 8) ? 1 : 0);
5249 + chip_map = kmalloc(mapsize, GFP_KERNEL);
5251 + printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
5255 + memset (chip_map, 0, mapsize);
5257 + set_bit(0, chip_map); /* Mark first chip valid */
5260 * Now probe for other chips, checking sensibly for aliases while
5261 * we're at it. The new_chip probe above should have let the first
5262 * chip in read mode.
5264 - * NOTE: Here, we're checking if there is room for another chip
5265 - * the same size within the mapping. Therefore,
5266 - * base + chipsize <= map->size is the correct thing to do,
5267 - * because, base + chipsize would be the _first_ byte of the
5268 - * next chip, not the one we're currently pondering.
5271 - for (base = (1<<cfi.chipshift); base + (1<<cfi.chipshift) <= map->size;
5272 - base += (1<<cfi.chipshift))
5273 - cp->probe_chip(map, base, &chip[0], &cfi);
5274 + for (i = 1; i < max_chips; i++) {
5275 + cp->probe_chip(map, i << cfi.chipshift, chip_map, &cfi);
5279 * Now allocate the space for the structures we need to return to
5280 @@ -132,19 +131,26 @@
5282 printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name);
5288 memcpy(retcfi, &cfi, sizeof(cfi));
5289 - memcpy(&retcfi->chips[0], chip, sizeof(struct flchip) * cfi.numchips);
5290 + memset(&retcfi->chips[0], 0, sizeof(struct flchip) * cfi.numchips);
5292 + for (i = 0, j = 0; (j < cfi.numchips) && (i < max_chips); i++) {
5293 + if(test_bit(i, chip_map)) {
5294 + struct flchip *pchip = &retcfi->chips[j++];
5296 - /* Fix up the stuff that breaks when you move it */
5297 - for (i=0; i< retcfi->numchips; i++) {
5298 - init_waitqueue_head(&retcfi->chips[i].wq);
5299 - spin_lock_init(&retcfi->chips[i]._spinlock);
5300 - retcfi->chips[i].mutex = &retcfi->chips[i]._spinlock;
5301 + pchip->start = (i << cfi.chipshift);
5302 + pchip->state = FL_READY;
5303 + init_waitqueue_head(&pchip->wq);
5304 + spin_lock_init(&pchip->_spinlock);
5305 + pchip->mutex = &pchip->_spinlock;
5313 @@ -152,131 +158,31 @@
5314 static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
5315 struct cfi_private *cfi)
5317 - switch (map->buswidth) {
5318 -#ifdef CFIDEV_BUSWIDTH_1
5319 - case CFIDEV_BUSWIDTH_1:
5320 - cfi->interleave = CFIDEV_INTERLEAVE_1;
5322 - cfi->device_type = CFI_DEVICETYPE_X8;
5323 - if (cp->probe_chip(map, 0, NULL, cfi))
5326 - cfi->device_type = CFI_DEVICETYPE_X16;
5327 - if (cp->probe_chip(map, 0, NULL, cfi))
5330 -#endif /* CFIDEV_BUSWITDH_1 */
5332 -#ifdef CFIDEV_BUSWIDTH_2
5333 - case CFIDEV_BUSWIDTH_2:
5334 -#ifdef CFIDEV_INTERLEAVE_1
5335 - cfi->interleave = CFIDEV_INTERLEAVE_1;
5337 - cfi->device_type = CFI_DEVICETYPE_X16;
5338 - if (cp->probe_chip(map, 0, NULL, cfi))
5340 -#endif /* CFIDEV_INTERLEAVE_1 */
5341 -#ifdef CFIDEV_INTERLEAVE_2
5342 - cfi->interleave = CFIDEV_INTERLEAVE_2;
5344 - cfi->device_type = CFI_DEVICETYPE_X8;
5345 - if (cp->probe_chip(map, 0, NULL, cfi))
5348 - cfi->device_type = CFI_DEVICETYPE_X16;
5349 - if (cp->probe_chip(map, 0, NULL, cfi))
5351 -#endif /* CFIDEV_INTERLEAVE_2 */
5353 -#endif /* CFIDEV_BUSWIDTH_2 */
5355 -#ifdef CFIDEV_BUSWIDTH_4
5356 - case CFIDEV_BUSWIDTH_4:
5357 -#if defined(CFIDEV_INTERLEAVE_1) && defined(SOMEONE_ACTUALLY_MAKES_THESE)
5358 - cfi->interleave = CFIDEV_INTERLEAVE_1;
5360 - cfi->device_type = CFI_DEVICETYPE_X32;
5361 - if (cp->probe_chip(map, 0, NULL, cfi))
5363 -#endif /* CFIDEV_INTERLEAVE_1 */
5364 -#ifdef CFIDEV_INTERLEAVE_2
5365 - cfi->interleave = CFIDEV_INTERLEAVE_2;
5367 -#ifdef SOMEONE_ACTUALLY_MAKES_THESE
5368 - cfi->device_type = CFI_DEVICETYPE_X32;
5369 - if (cp->probe_chip(map, 0, NULL, cfi))
5372 - cfi->device_type = CFI_DEVICETYPE_X16;
5373 - if (cp->probe_chip(map, 0, NULL, cfi))
5376 - cfi->device_type = CFI_DEVICETYPE_X8;
5377 - if (cp->probe_chip(map, 0, NULL, cfi))
5379 -#endif /* CFIDEV_INTERLEAVE_2 */
5380 -#ifdef CFIDEV_INTERLEAVE_4
5381 - cfi->interleave = CFIDEV_INTERLEAVE_4;
5383 -#ifdef SOMEONE_ACTUALLY_MAKES_THESE
5384 - cfi->device_type = CFI_DEVICETYPE_X32;
5385 - if (cp->probe_chip(map, 0, NULL, cfi))
5388 - cfi->device_type = CFI_DEVICETYPE_X16;
5389 - if (cp->probe_chip(map, 0, NULL, cfi))
5392 - cfi->device_type = CFI_DEVICETYPE_X8;
5393 - if (cp->probe_chip(map, 0, NULL, cfi))
5395 -#endif /* CFIDEV_INTERLEAVE_4 */
5397 -#endif /* CFIDEV_BUSWIDTH_4 */
5399 -#ifdef CFIDEV_BUSWIDTH_8
5400 - case CFIDEV_BUSWIDTH_8:
5401 -#if defined(CFIDEV_INTERLEAVE_2) && defined(SOMEONE_ACTUALLY_MAKES_THESE)
5402 - cfi->interleave = CFIDEV_INTERLEAVE_2;
5404 - cfi->device_type = CFI_DEVICETYPE_X32;
5405 - if (cp->probe_chip(map, 0, NULL, cfi))
5407 -#endif /* CFIDEV_INTERLEAVE_2 */
5408 -#ifdef CFIDEV_INTERLEAVE_4
5409 - cfi->interleave = CFIDEV_INTERLEAVE_4;
5411 -#ifdef SOMEONE_ACTUALLY_MAKES_THESE
5412 - cfi->device_type = CFI_DEVICETYPE_X32;
5413 - if (cp->probe_chip(map, 0, NULL, cfi))
5416 - cfi->device_type = CFI_DEVICETYPE_X16;
5417 - if (cp->probe_chip(map, 0, NULL, cfi))
5419 -#endif /* CFIDEV_INTERLEAVE_4 */
5420 -#ifdef CFIDEV_INTERLEAVE_8
5421 - cfi->interleave = CFIDEV_INTERLEAVE_8;
5423 - cfi->device_type = CFI_DEVICETYPE_X16;
5424 - if (cp->probe_chip(map, 0, NULL, cfi))
5427 - cfi->device_type = CFI_DEVICETYPE_X8;
5428 - if (cp->probe_chip(map, 0, NULL, cfi))
5430 -#endif /* CFIDEV_INTERLEAVE_8 */
5432 -#endif /* CFIDEV_BUSWIDTH_8 */
5435 - printk(KERN_WARNING "genprobe_new_chip called with unsupported buswidth %d\n", map->buswidth);
5437 + int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */
5438 + int max_chips = map_bankwidth(map); /* And minimum 1 */
5439 + int nr_chips, type;
5441 + for (nr_chips = min_chips; nr_chips <= max_chips; nr_chips <<= 1) {
5443 + if (!cfi_interleave_supported(nr_chips))
5446 + cfi->interleave = nr_chips;
5448 + /* Minimum device size. Don't look for one 8-bit device
5449 + in a 16-bit bus, etc. */
5450 + type = map_bankwidth(map) / nr_chips;
5452 + for (; type <= CFI_DEVICETYPE_X32; type<<=1) {
5453 + cfi->device_type = type;
5455 + if (cp->probe_chip(map, 0, NULL, cfi))
5463 typedef struct mtd_info *cfi_cmdset_fn_t(struct map_info *, int);
5465 extern cfi_cmdset_fn_t cfi_cmdset_0001;
5466 Index: linux-2.6.5/drivers/mtd/chips/jedec.c
5467 ===================================================================
5468 --- linux-2.6.5.orig/drivers/mtd/chips/jedec.c 2004-04-03 22:37:23.000000000 -0500
5469 +++ linux-2.6.5/drivers/mtd/chips/jedec.c 2005-02-01 17:11:17.000000000 -0500
5471 * not going to guess how to send commands to them, plus I expect they will
5474 - * $Id: jedec.c,v 1.19 2003/05/29 09:25:23 dwmw2 Exp $
5475 + * $Id: jedec.c,v 1.21 2004/08/09 13:19:43 dwmw2 Exp $
5478 #include <linux/init.h>
5481 printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n");
5487 for (Base = 0; Base < map->size; Base += my_bank_size)
5489 if (jedec_probe8(map,Base,priv) == 0) {
5490 printk("did recognize jedec chip\n");
5496 if (map->buswidth == 2)
5499 printk("mtd: Failed. Device has incompatible mixed sector sizes\n");
5508 printk("mtd: Internal Error, JEDEC not set\n");
5517 printk("priv->size is zero\n");
5522 if (priv->size/my_bank_size) {
5523 if (priv->size/my_bank_size == 1) {
5526 printk("mtd: Failed. Cannot handle unsymmetric banking\n");
5534 for (I = 0; JEDEC_table[I].jedec != 0; I++)
5535 if (JEDEC_table[I].jedec == Id)
5536 return JEDEC_table + I;
5541 // Look for flash using an 8 bit bus interface
5545 instr->state = MTD_ERASE_DONE;
5546 - if (instr->callback)
5547 - instr->callback(instr);
5548 + mtd_erase_callback(instr);
5552 Index: linux-2.6.5/drivers/mtd/chips/jedec_probe.c
5553 ===================================================================
5554 --- linux-2.6.5.orig/drivers/mtd/chips/jedec_probe.c 2005-02-01 16:55:45.000000000 -0500
5555 +++ linux-2.6.5/drivers/mtd/chips/jedec_probe.c 2005-02-01 17:11:17.000000000 -0500
5558 Common Flash Interface probe code.
5559 (C) 2000 Red Hat. GPL'd.
5560 - $Id: jedec_probe.c,v 1.29 2003/05/28 13:57:46 dwmw2 Exp $
5561 + $Id: jedec_probe.c,v 1.57 2004/09/17 11:45:05 eric Exp $
5562 See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5)
5563 for the standard this probe goes back to.
5565 + Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
5568 #include <linux/config.h>
5570 #define MANUFACTURER_AMD 0x0001
5571 #define MANUFACTURER_ATMEL 0x001f
5572 #define MANUFACTURER_FUJITSU 0x0004
5573 +#define MANUFACTURER_HYUNDAI 0x00AD
5574 #define MANUFACTURER_INTEL 0x0089
5575 #define MANUFACTURER_MACRONIX 0x00C2
5576 #define MANUFACTURER_PMC 0x009D
5581 +#define AM29DL800BB 0x22C8
5582 +#define AM29DL800BT 0x224A
5584 #define AM29F800BB 0x2258
5585 #define AM29F800BT 0x22D6
5586 +#define AM29LV400BB 0x22BA
5587 +#define AM29LV400BT 0x22B9
5588 #define AM29LV800BB 0x225B
5589 #define AM29LV800BT 0x22DA
5590 #define AM29LV160DT 0x22C4
5592 #define AM29F040 0x00A4
5593 #define AM29LV040B 0x004F
5594 #define AM29F032B 0x0041
5595 +#define AM29F002T 0x00B0
5598 #define AT49BV512 0x0003
5600 #define AT49BV32XT 0x00C9
5603 +#define MBM29F040C 0x00A4
5604 #define MBM29LV650UE 0x22D7
5605 #define MBM29LV320TE 0x22F6
5606 #define MBM29LV320BE 0x22F9
5608 #define MBM29LV160BE 0x2249
5609 #define MBM29LV800BA 0x225B
5610 #define MBM29LV800TA 0x22DA
5611 +#define MBM29LV400TC 0x22B9
5612 +#define MBM29LV400BC 0x22BA
5615 +#define HY29F002T 0x00B0
5618 #define I28F004B3T 0x00d4
5620 #define I82802AC 0x00ac
5623 +#define MX29LV040C 0x004F
5624 #define MX29LV160T 0x22C4
5625 #define MX29LV160B 0x2249
5626 #define MX29F016 0x00AD
5627 +#define MX29F002T 0x00B0
5628 #define MX29F004T 0x0045
5629 #define MX29F004B 0x0046
5631 @@ -109,8 +126,14 @@
5632 #define M29W160DT 0x22C4
5633 #define M29W160DB 0x2249
5634 #define M29W040B 0x00E3
5635 +#define M50FW040 0x002C
5636 +#define M50FW080 0x002D
5637 +#define M50FW016 0x002E
5638 +#define M50LPW080 0x002F
5641 +#define SST29EE020 0x0010
5642 +#define SST29LE020 0x0012
5643 #define SST29EE512 0x005d
5644 #define SST29LE512 0x003d
5645 #define SST39LF800 0x2781
5647 #define SST39LF040 0x00D7
5648 #define SST39SF010A 0x00B5
5649 #define SST39SF020A 0x00B6
5650 +#define SST49LF004B 0x0060
5651 +#define SST49LF008A 0x005a
5652 #define SST49LF030A 0x001C
5653 #define SST49LF040A 0x0051
5654 #define SST49LF080A 0x005B
5658 struct unlock_addr {
5666 @@ -211,11 +236,10 @@
5670 - const int InterfaceDesc;
5671 const int NumEraseRegions;
5673 - const __u8 uaddr[3]; /* unlock addrs for 8, 16, 32 modes */
5674 - const ulong regions[4];
5675 + const __u8 uaddr[4]; /* unlock addrs for 8, 16, 32, 64 */
5676 + const ulong regions[6];
5679 #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
5680 @@ -285,6 +309,40 @@
5683 .mfr_id = MANUFACTURER_AMD,
5684 + .dev_id = AM29LV400BB,
5685 + .name = "AMD AM29LV400BB",
5687 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
5688 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
5690 + .DevSize = SIZE_512KiB,
5691 + .CmdSet = P_ID_AMD_STD,
5692 + .NumEraseRegions= 4,
5694 + ERASEINFO(0x04000,1),
5695 + ERASEINFO(0x02000,2),
5696 + ERASEINFO(0x08000,1),
5697 + ERASEINFO(0x10000,7)
5700 + .mfr_id = MANUFACTURER_AMD,
5701 + .dev_id = AM29LV400BT,
5702 + .name = "AMD AM29LV400BT",
5704 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
5705 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
5707 + .DevSize = SIZE_512KiB,
5708 + .CmdSet = P_ID_AMD_STD,
5709 + .NumEraseRegions= 4,
5711 + ERASEINFO(0x10000,7),
5712 + ERASEINFO(0x08000,1),
5713 + ERASEINFO(0x02000,2),
5714 + ERASEINFO(0x04000,1)
5717 + .mfr_id = MANUFACTURER_AMD,
5718 .dev_id = AM29LV800BB,
5719 .name = "AMD AM29LV800BB",
5721 @@ -301,6 +359,45 @@
5722 ERASEINFO(0x10000,15),
5726 + .mfr_id = MANUFACTURER_AMD,
5727 + .dev_id = AM29DL800BB,
5728 + .name = "AMD AM29DL800BB",
5730 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
5731 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
5733 + .DevSize = SIZE_1MiB,
5734 + .CmdSet = P_ID_AMD_STD,
5735 + .NumEraseRegions= 6,
5737 + ERASEINFO(0x04000,1),
5738 + ERASEINFO(0x08000,1),
5739 + ERASEINFO(0x02000,4),
5740 + ERASEINFO(0x08000,1),
5741 + ERASEINFO(0x04000,1),
5742 + ERASEINFO(0x10000,14)
5745 + .mfr_id = MANUFACTURER_AMD,
5746 + .dev_id = AM29DL800BT,
5747 + .name = "AMD AM29DL800BT",
5749 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
5750 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
5752 + .DevSize = SIZE_1MiB,
5753 + .CmdSet = P_ID_AMD_STD,
5754 + .NumEraseRegions= 6,
5756 + ERASEINFO(0x10000,14),
5757 + ERASEINFO(0x04000,1),
5758 + ERASEINFO(0x08000,1),
5759 + ERASEINFO(0x02000,4),
5760 + ERASEINFO(0x08000,1),
5761 + ERASEINFO(0x04000,1)
5764 .mfr_id = MANUFACTURER_AMD,
5765 .dev_id = AM29F800BB,
5766 .name = "AMD AM29F800BB",
5767 @@ -417,6 +514,17 @@
5768 ERASEINFO(0x10000,8),
5771 + mfr_id: MANUFACTURER_AMD,
5772 + dev_id: AM29F002T,
5773 + name: "AMD AM29F002T",
5774 + DevSize: SIZE_256KiB,
5775 + NumEraseRegions: 4,
5776 + regions: {ERASEINFO(0x10000,3),
5777 + ERASEINFO(0x08000,1),
5778 + ERASEINFO(0x02000,2),
5779 + ERASEINFO(0x04000,1)
5782 .mfr_id = MANUFACTURER_ATMEL,
5783 .dev_id = AT49BV512,
5784 .name = "Atmel AT49BV512",
5785 @@ -505,6 +613,19 @@
5788 .mfr_id = MANUFACTURER_FUJITSU,
5789 + .dev_id = MBM29F040C,
5790 + .name = "Fujitsu MBM29F040C",
5792 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
5794 + .DevSize = SIZE_512KiB,
5795 + .CmdSet = P_ID_AMD_STD,
5796 + .NumEraseRegions= 1,
5798 + ERASEINFO(0x10000,8)
5801 + .mfr_id = MANUFACTURER_FUJITSU,
5802 .dev_id = MBM29LV650UE,
5803 .name = "Fujitsu MBM29LV650UE",
5805 @@ -615,6 +736,51 @@
5806 ERASEINFO(0x04000,1)
5809 + .mfr_id = MANUFACTURER_FUJITSU,
5810 + .dev_id = MBM29LV400BC,
5811 + .name = "Fujitsu MBM29LV400BC",
5813 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
5814 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
5816 + .DevSize = SIZE_512KiB,
5817 + .CmdSet = P_ID_AMD_STD,
5818 + .NumEraseRegions= 4,
5820 + ERASEINFO(0x04000,1),
5821 + ERASEINFO(0x02000,2),
5822 + ERASEINFO(0x08000,1),
5823 + ERASEINFO(0x10000,7)
5826 + .mfr_id = MANUFACTURER_FUJITSU,
5827 + .dev_id = MBM29LV400TC,
5828 + .name = "Fujitsu MBM29LV400TC",
5830 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
5831 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
5833 + .DevSize = SIZE_512KiB,
5834 + .CmdSet = P_ID_AMD_STD,
5835 + .NumEraseRegions= 4,
5837 + ERASEINFO(0x10000,7),
5838 + ERASEINFO(0x08000,1),
5839 + ERASEINFO(0x02000,2),
5840 + ERASEINFO(0x04000,1)
5843 + mfr_id: MANUFACTURER_HYUNDAI,
5844 + dev_id: HY29F002T,
5845 + name: "Hyundai HY29F002T",
5846 + DevSize: SIZE_256KiB,
5847 + NumEraseRegions: 4,
5848 + regions: {ERASEINFO(0x10000,3),
5849 + ERASEINFO(0x08000,1),
5850 + ERASEINFO(0x02000,2),
5851 + ERASEINFO(0x04000,1)
5854 .mfr_id = MANUFACTURER_INTEL,
5855 .dev_id = I28F004B3B,
5856 .name = "Intel 28F004B3B",
5857 @@ -920,6 +1086,19 @@
5860 .mfr_id = MANUFACTURER_MACRONIX,
5861 + .dev_id = MX29LV040C,
5862 + .name = "Macronix MX29LV040C",
5864 + [0] = MTD_UADDR_0x0555_0x02AA, /* x8 */
5866 + .DevSize = SIZE_512KiB,
5867 + .CmdSet = P_ID_AMD_STD,
5868 + .NumEraseRegions= 1,
5870 + ERASEINFO(0x10000,8),
5873 + .mfr_id = MANUFACTURER_MACRONIX,
5874 .dev_id = MX29LV160T,
5875 .name = "MXIC MX29LV160T",
5877 @@ -998,6 +1177,17 @@
5878 ERASEINFO(0x10000,7),
5881 + mfr_id: MANUFACTURER_MACRONIX,
5882 + dev_id: MX29F002T,
5883 + name: "Macronix MX29F002T",
5884 + DevSize: SIZE_256KiB,
5885 + NumEraseRegions: 4,
5886 + regions: {ERASEINFO(0x10000,3),
5887 + ERASEINFO(0x08000,1),
5888 + ERASEINFO(0x02000,2),
5889 + ERASEINFO(0x04000,1)
5892 .mfr_id = MANUFACTURER_PMC,
5893 .dev_id = PM49FL002,
5894 .name = "PMC Pm49FL002",
5895 @@ -1064,6 +1254,30 @@
5898 .mfr_id = MANUFACTURER_SST,
5899 + .dev_id = SST29EE020,
5900 + .name = "SST 29EE020",
5902 + [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
5904 + .DevSize = SIZE_256KiB,
5905 + .CmdSet = P_ID_SST_PAGE,
5906 + .NumEraseRegions= 1,
5907 + regions: {ERASEINFO(0x01000,64),
5910 + .mfr_id = MANUFACTURER_SST,
5911 + .dev_id = SST29LE020,
5912 + .name = "SST 29LE020",
5914 + [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
5916 + .DevSize = SIZE_256KiB,
5917 + .CmdSet = P_ID_SST_PAGE,
5918 + .NumEraseRegions= 1,
5919 + regions: {ERASEINFO(0x01000,64),
5922 + .mfr_id = MANUFACTURER_SST,
5923 .dev_id = SST39LF020,
5924 .name = "SST 39LF020",
5926 @@ -1116,6 +1330,32 @@
5929 .mfr_id = MANUFACTURER_SST,
5930 + .dev_id = SST49LF004B,
5931 + .name = "SST 49LF004B",
5933 + [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
5935 + .DevSize = SIZE_512KiB,
5936 + .CmdSet = P_ID_AMD_STD,
5937 + .NumEraseRegions= 1,
5939 + ERASEINFO(0x01000,128),
5942 + .mfr_id = MANUFACTURER_SST,
5943 + .dev_id = SST49LF008A,
5944 + .name = "SST 49LF008A",
5946 + [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
5948 + .DevSize = SIZE_1MiB,
5949 + .CmdSet = P_ID_AMD_STD,
5950 + .NumEraseRegions= 1,
5952 + ERASEINFO(0x01000,256),
5955 + .mfr_id = MANUFACTURER_SST,
5956 .dev_id = SST49LF030A,
5957 .name = "SST 49LF030A",
5959 @@ -1154,6 +1394,22 @@
5960 ERASEINFO(0x01000,256),
5963 + .mfr_id = MANUFACTURER_SST, /* should be CFI */
5964 + .dev_id = SST39LF160,
5965 + .name = "SST 39LF160",
5967 + [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */
5968 + [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */
5970 + .DevSize = SIZE_2MiB,
5971 + .CmdSet = P_ID_AMD_STD,
5972 + .NumEraseRegions= 2,
5974 + ERASEINFO(0x1000,256),
5975 + ERASEINFO(0x1000,256)
5979 .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */
5980 .dev_id = M29W800DT,
5981 .name = "ST M29W800DT",
5982 @@ -1234,6 +1490,58 @@
5984 ERASEINFO(0x10000,8),
5987 + .mfr_id = MANUFACTURER_ST,
5988 + .dev_id = M50FW040,
5989 + .name = "ST M50FW040",
5991 + [0] = MTD_UADDR_UNNECESSARY, /* x8 */
5993 + .DevSize = SIZE_512KiB,
5994 + .CmdSet = P_ID_INTEL_EXT,
5995 + .NumEraseRegions= 1,
5997 + ERASEINFO(0x10000,8),
6000 + .mfr_id = MANUFACTURER_ST,
6001 + .dev_id = M50FW080,
6002 + .name = "ST M50FW080",
6004 + [0] = MTD_UADDR_UNNECESSARY, /* x8 */
6006 + .DevSize = SIZE_1MiB,
6007 + .CmdSet = P_ID_INTEL_EXT,
6008 + .NumEraseRegions= 1,
6010 + ERASEINFO(0x10000,16),
6013 + .mfr_id = MANUFACTURER_ST,
6014 + .dev_id = M50FW016,
6015 + .name = "ST M50FW016",
6017 + [0] = MTD_UADDR_UNNECESSARY, /* x8 */
6019 + .DevSize = SIZE_2MiB,
6020 + .CmdSet = P_ID_INTEL_EXT,
6021 + .NumEraseRegions= 1,
6023 + ERASEINFO(0x10000,32),
6026 + .mfr_id = MANUFACTURER_ST,
6027 + .dev_id = M50LPW080,
6028 + .name = "ST M50LPW080",
6030 + [0] = MTD_UADDR_UNNECESSARY, /* x8 */
6032 + .DevSize = SIZE_1MiB,
6033 + .CmdSet = P_ID_INTEL_EXT,
6034 + .NumEraseRegions= 1,
6036 + ERASEINFO(0x10000,16),
6039 .mfr_id = MANUFACTURER_TOSHIBA,
6040 .dev_id = TC58FVT160,
6041 @@ -1344,44 +1652,59 @@
6042 ERASEINFO(0x02000, 2),
6043 ERASEINFO(0x04000, 1),
6050 static int cfi_jedec_setup(struct cfi_private *p_cfi, int index);
6052 static int jedec_probe_chip(struct map_info *map, __u32 base,
6053 - struct flchip *chips, struct cfi_private *cfi);
6054 + unsigned long *chip_map, struct cfi_private *cfi);
6056 struct mtd_info *jedec_probe(struct map_info *map);
6058 static inline u32 jedec_read_mfr(struct map_info *map, __u32 base,
6059 struct cfi_private *cfi)
6063 + unsigned long mask;
6064 + u32 ofs = cfi_build_cmd_addr(0, cfi_interleave(cfi), cfi->device_type);
6065 mask = (1 << (cfi->device_type * 8)) -1;
6066 - result = cfi_read(map, base);
6069 + result = map_read(map, base + ofs);
6070 + return result.x[0] & mask;
6073 static inline u32 jedec_read_id(struct map_info *map, __u32 base,
6074 struct cfi_private *cfi)
6078 - osf = cfi->interleave *cfi->device_type;
6080 + unsigned long mask;
6081 + u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type);
6082 mask = (1 << (cfi->device_type * 8)) -1;
6083 - result = cfi_read(map, base + osf);
6086 + result = map_read(map, base + ofs);
6087 + return result.x[0] & mask;
6090 static inline void jedec_reset(u32 base, struct map_info *map,
6091 struct cfi_private *cfi)
6094 - cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
6096 + /* after checking the datasheets for SST, MACRONIX and ATMEL
6097 + * (oh and incidentaly the jedec spec - 3.5.3.3) the reset
6098 + * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
6099 + * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips
6100 + * as they will ignore the writes and dont care what address
6101 + * the F0 is written to */
6102 + if(cfi->addr_unlock1) {
6103 + DEBUG( MTD_DEBUG_LEVEL3,
6104 + "reset unlock called %x %x \n",
6105 + cfi->addr_unlock1,cfi->addr_unlock2);
6106 + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
6107 + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
6110 + cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
6111 /* Some misdesigned intel chips do not respond for 0xF0 for a reset,
6112 * so ensure we're in read mode. Send both the Intel and the AMD command
6113 * for this. Intel uses 0xff for this, AMD uses 0xff for NOP, so
6114 @@ -1409,6 +1732,12 @@
6116 uaddr = finfo->uaddr[uaddr_idx];
6118 + if (uaddr != MTD_UADDR_NOT_SUPPORTED ) {
6119 + /* ASSERT("The unlock addresses for non-8-bit mode
6120 + are bollocks. We don't really need an array."); */
6121 + uaddr = finfo->uaddr[0];
6127 @@ -1439,17 +1768,19 @@
6128 for (i=0; i<num_erase_regions; i++){
6129 p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i];
6131 - p_cfi->cmdset_priv = 0;
6132 + p_cfi->cmdset_priv = NULL;
6134 /* This may be redundant for some cases, but it doesn't hurt */
6135 p_cfi->mfr = jedec_table[index].mfr_id;
6136 p_cfi->id = jedec_table[index].dev_id;
6138 uaddr = finfo_uaddr(&jedec_table[index], p_cfi->device_type);
6139 - if ( MTD_UADDR_NOT_SUPPORTED ) {
6140 + if ( uaddr == MTD_UADDR_NOT_SUPPORTED ) {
6141 kfree( p_cfi->cfiq );
6145 + /* Mask out address bits which are smaller than the device type */
6146 p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1;
6147 p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2;
6149 @@ -1473,8 +1804,35 @@
6153 - /* The ID's must match */
6154 - if ( cfi->mfr != finfo->mfr_id || cfi->id != finfo->dev_id ) {
6156 + * The IDs must match. For X16 and X32 devices operating in
6157 + * a lower width ( X8 or X16 ), the device ID's are usually just
6158 + * the lower byte(s) of the larger device ID for wider mode. If
6159 + * a part is found that doesn't fit this assumption (device id for
6160 + * smaller width mode is completely unrealated to full-width mode)
6161 + * then the jedec_table[] will have to be augmented with the IDs
6162 + * for different widths.
6164 + switch (cfi->device_type) {
6165 + case CFI_DEVICETYPE_X8:
6166 + mfr = (__u8)finfo->mfr_id;
6167 + id = (__u8)finfo->dev_id;
6169 + case CFI_DEVICETYPE_X16:
6170 + mfr = (__u16)finfo->mfr_id;
6171 + id = (__u16)finfo->dev_id;
6173 + case CFI_DEVICETYPE_X32:
6174 + mfr = (__u16)finfo->mfr_id;
6175 + id = (__u32)finfo->dev_id;
6178 + printk(KERN_WARNING
6179 + "MTD %s(): Unsupported device type %d\n",
6180 + __func__, cfi->device_type);
6183 + if ( cfi->mfr != mfr || cfi->id != id ) {
6187 @@ -1482,7 +1840,7 @@
6188 DEBUG( MTD_DEBUG_LEVEL3,
6189 "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
6190 __func__, base, 1 << finfo->DevSize, base + (1 << finfo->DevSize) );
6191 - if ( base + ( 1 << finfo->DevSize ) > map->size ) {
6192 + if ( base + cfi_interleave(cfi) * ( 1 << finfo->DevSize ) > map->size ) {
6193 DEBUG( MTD_DEBUG_LEVEL3,
6194 "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
6195 __func__, finfo->mfr_id, finfo->dev_id,
6196 @@ -1491,20 +1849,20 @@
6199 uaddr = finfo_uaddr(finfo, cfi->device_type);
6200 - if ( MTD_UADDR_NOT_SUPPORTED ) {
6201 + if ( uaddr == MTD_UADDR_NOT_SUPPORTED ) {
6205 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
6206 __func__, cfi->addr_unlock1, cfi->addr_unlock2 );
6207 if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
6208 - && ( unlock_addrs[uaddr].addr1 != cfi->addr_unlock1
6209 - || unlock_addrs[uaddr].addr2 != cfi->addr_unlock2 ) ) {
6210 + && ( unlock_addrs[uaddr].addr1 != cfi->addr_unlock1 ||
6211 + unlock_addrs[uaddr].addr2 != cfi->addr_unlock2 ) ) {
6212 DEBUG( MTD_DEBUG_LEVEL3,
6213 - "MTD %s(): 0x%.4x 0x%.4x did not match\n",
6215 - unlock_addrs[uaddr].addr1,
6216 - unlock_addrs[uaddr].addr2 );
6217 + "MTD %s(): 0x%.4x 0x%.4x did not match\n",
6219 + unlock_addrs[uaddr].addr1,
6220 + unlock_addrs[uaddr].addr2);
6224 @@ -1540,10 +1898,10 @@
6226 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ );
6227 if(cfi->addr_unlock1) {
6228 - cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
6229 - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
6230 + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
6231 + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
6233 - cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
6234 + cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
6235 /* FIXME - should have a delay before continuing */
6238 @@ -1552,41 +1910,24 @@
6241 static int jedec_probe_chip(struct map_info *map, __u32 base,
6242 - struct flchip *chips, struct cfi_private *cfi)
6243 + unsigned long *chip_map, struct cfi_private *cfi)
6246 - int unlockpass = 0;
6247 + enum uaddr uaddr_idx = MTD_UADDR_NOT_SUPPORTED;
6248 + u32 probe_offset1, probe_offset2;
6251 - * FIXME - eventually replace these unlock address seeds with
6252 - * information from unlock_addrs[].
6255 if (!cfi->numchips) {
6256 - switch (cfi->device_type) {
6257 - case CFI_DEVICETYPE_X8:
6258 - cfi->addr_unlock1 = 0x555;
6259 - cfi->addr_unlock2 = 0x2aa;
6261 - case CFI_DEVICETYPE_X16:
6262 - cfi->addr_unlock1 = 0xaaa;
6263 - if (map->buswidth == cfi->interleave) {
6264 - /* X16 chip(s) in X8 mode */
6265 - cfi->addr_unlock2 = 0x555;
6267 - cfi->addr_unlock2 = 0x554;
6270 - case CFI_DEVICETYPE_X32:
6271 - cfi->addr_unlock1 = 0x1555;
6272 - cfi->addr_unlock2 = 0xaaa;
6275 - printk(KERN_NOTICE "Eep. Unknown jedec_probe device type %d\n", cfi->device_type);
6280 + if (MTD_UADDR_UNNECESSARY == uaddr_idx)
6283 + /* Mask out address bits which are smaller than the device type */
6284 + cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1;
6285 + cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2;
6289 /* Make certain we aren't probing past the end of map */
6290 if (base >= map->size) {
6292 @@ -1595,30 +1936,30 @@
6296 - if ((base + cfi->addr_unlock1) >= map->size) {
6297 - printk(KERN_NOTICE
6298 - "Probe at addr_unlock1(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n",
6299 - base, cfi->addr_unlock1, map->size -1);
6302 + /* Ensure the unlock addresses we try stay inside the map */
6303 + probe_offset1 = cfi_build_cmd_addr(
6304 + cfi->addr_unlock1,
6305 + cfi_interleave(cfi),
6306 + cfi->device_type);
6307 + probe_offset2 = cfi_build_cmd_addr(
6308 + cfi->addr_unlock1,
6309 + cfi_interleave(cfi),
6310 + cfi->device_type);
6311 + if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) ||
6312 + ((base + probe_offset2 + map_bankwidth(map)) >= map->size))
6316 - if ((base + cfi->addr_unlock2) >= map->size) {
6317 - printk(KERN_NOTICE
6318 - "Probe at addr_unlock2(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n",
6319 - base, cfi->addr_unlock2, map->size -1);
6325 jedec_reset(base, map, cfi);
6327 /* Autoselect Mode */
6328 if(cfi->addr_unlock1) {
6329 - cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
6330 - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
6331 + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
6332 + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
6334 - cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
6335 + cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
6336 /* FIXME - should have a delay before continuing */
6338 if (!cfi->numchips) {
6339 @@ -1628,9 +1969,8 @@
6340 cfi->mfr = jedec_read_mfr(map, base, cfi);
6341 cfi->id = jedec_read_id(map, base, cfi);
6342 DEBUG(MTD_DEBUG_LEVEL3,
6343 - "MTD %s(): Search for id:(%02x %02x) interleave(%d) type(%d)\n",
6344 - __func__, cfi->mfr, cfi->id, cfi->interleave,
6345 - cfi->device_type);
6346 + "Search for id:(%02x %02x) interleave(%d) type(%d)\n",
6347 + cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
6348 for (i=0; i<sizeof(jedec_table)/sizeof(jedec_table[0]); i++) {
6349 if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
6350 DEBUG( MTD_DEBUG_LEVEL3,
6351 @@ -1642,16 +1982,7 @@
6355 - switch(unlockpass++) {
6357 - cfi->addr_unlock1 |= cfi->addr_unlock1 << 4;
6358 - cfi->addr_unlock2 |= cfi->addr_unlock2 << 4;
6361 - cfi->addr_unlock1 = cfi->addr_unlock2 = 0;
6369 @@ -1668,21 +1999,24 @@
6373 - /* Check each previous chip to see if it's an alias */
6374 - for (i=0; i<cfi->numchips; i++) {
6375 - /* This chip should be in read mode if it's one
6376 - we've already touched. */
6377 - if (jedec_read_mfr(map, chips[i].start, cfi) == cfi->mfr &&
6378 - jedec_read_id(map, chips[i].start, cfi) == cfi->id) {
6379 + /* Check each previous chip locations to see if it's an alias */
6380 + for (i=0; i < (base >> cfi->chipshift); i++) {
6381 + unsigned long start;
6382 + if(!test_bit(i, chip_map)) {
6383 + continue; /* Skip location; no valid chip at this address */
6385 + start = i << cfi->chipshift;
6386 + if (jedec_read_mfr(map, start, cfi) == cfi->mfr &&
6387 + jedec_read_id(map, start, cfi) == cfi->id) {
6388 /* Eep. This chip also looks like it's in autoselect mode.
6389 Is it an alias for the new one? */
6390 - jedec_reset(chips[i].start, map, cfi);
6391 + jedec_reset(start, map, cfi);
6393 /* If the device IDs go away, it's an alias */
6394 if (jedec_read_mfr(map, base, cfi) != cfi->mfr ||
6395 jedec_read_id(map, base, cfi) != cfi->id) {
6396 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
6397 - map->name, base, chips[i].start);
6398 + map->name, base, start);
6402 @@ -1694,7 +2028,7 @@
6403 if (jedec_read_mfr(map, base, cfi) == cfi->mfr &&
6404 jedec_read_id(map, base, cfi) == cfi->id) {
6405 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
6406 - map->name, base, chips[i].start);
6407 + map->name, base, start);
6411 @@ -1702,22 +2036,16 @@
6413 /* OK, if we got to here, then none of the previous chips appear to
6414 be aliases for the current one. */
6415 - if (cfi->numchips == MAX_CFI_CHIPS) {
6416 - printk(KERN_WARNING"%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS);
6417 - /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */
6420 - chips[cfi->numchips].start = base;
6421 - chips[cfi->numchips].state = FL_READY;
6422 + set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
6426 /* Put it back into Read Mode */
6427 jedec_reset(base, map, cfi);
6429 - printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n",
6430 - map->name, cfi->interleave, cfi->device_type*8, base,
6432 + printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
6433 + map->name, cfi_interleave(cfi), cfi->device_type*8, base,
6434 + map->bankwidth*8);
6438 Index: linux-2.6.5/drivers/mtd/chips/map_ram.c
6439 ===================================================================
6440 --- linux-2.6.5.orig/drivers/mtd/chips/map_ram.c 2004-04-03 22:36:55.000000000 -0500
6441 +++ linux-2.6.5/drivers/mtd/chips/map_ram.c 2005-02-01 17:11:17.000000000 -0500
6444 * Common code to handle map devices which are simple RAM
6445 * (C) 2000 Red Hat. GPL'd.
6446 - * $Id: map_ram.c,v 1.17 2003/05/28 12:51:49 dwmw2 Exp $
6447 + * $Id: map_ram.c,v 1.20 2004/08/09 13:19:43 dwmw2 Exp $
6450 #include <linux/module.h>
6451 @@ -104,13 +104,17 @@
6452 /* Yeah, it's inefficient. Who cares? It's faster than a _real_
6454 struct map_info *map = (struct map_info *)mtd->priv;
6458 - for (i=0; i<instr->len; i++)
6459 - map_write8(map, 0xFF, instr->addr + i);
6460 + allff = map_word_ff(map);
6462 - if (instr->callback)
6463 - instr->callback(instr);
6464 + for (i=0; i<instr->len; i += map_bankwidth(map))
6465 + map_write(map, allff, instr->addr + i);
6467 + instr->state = MTD_ERASE_DONE;
6469 + mtd_erase_callback(instr);
6473 Index: linux-2.6.5/drivers/mtd/chips/map_rom.c
6474 ===================================================================
6475 --- linux-2.6.5.orig/drivers/mtd/chips/map_rom.c 2004-04-03 22:37:25.000000000 -0500
6476 +++ linux-2.6.5/drivers/mtd/chips/map_rom.c 2005-02-01 17:11:17.000000000 -0500
6479 * Common code to handle map devices which are simple ROM
6480 * (C) 2000 Red Hat. GPL'd.
6481 - * $Id: map_rom.c,v 1.20 2003/05/28 12:51:49 dwmw2 Exp $
6482 + * $Id: map_rom.c,v 1.21 2004/07/12 14:06:01 dwmw2 Exp $
6485 #include <linux/module.h>
6486 Index: linux-2.6.5/drivers/mtd/chips/sharp.c
6487 ===================================================================
6488 --- linux-2.6.5.orig/drivers/mtd/chips/sharp.c 2004-04-03 22:37:23.000000000 -0500
6489 +++ linux-2.6.5/drivers/mtd/chips/sharp.c 2005-02-01 17:11:17.000000000 -0500
6491 * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
6492 * 2000,2001 Lineo, Inc.
6494 - * $Id: sharp.c,v 1.12 2003/05/28 15:39:52 dwmw2 Exp $
6495 + * $Id: sharp.c,v 1.14 2004/08/09 13:19:43 dwmw2 Exp $
6497 * Devices supported:
6498 * LH28F016SCT Symmetrical block flash memory, 2Mx8
6500 #include <linux/mtd/mtd.h>
6501 #include <linux/mtd/cfi.h>
6502 #include <linux/delay.h>
6503 +#include <linux/init.h>
6505 #define CMD_RESET 0xffffffff
6506 #define CMD_READ_ID 0x90909090
6508 map->fldrv = &sharp_chipdrv;
6509 map->fldrv_priv = sharp;
6511 - MOD_INC_USE_COUNT;
6512 + __module_get(THIS_MODULE);
6519 instr->state = MTD_ERASE_DONE;
6520 - if(instr->callback)
6521 - instr->callback(instr);
6522 + mtd_erase_callback(instr);
6526 Index: linux-2.6.5/drivers/mtd/cmdlinepart.c
6527 ===================================================================
6528 --- linux-2.6.5.orig/drivers/mtd/cmdlinepart.c 2004-04-03 22:37:37.000000000 -0500
6529 +++ linux-2.6.5/drivers/mtd/cmdlinepart.c 2005-02-01 17:11:17.000000000 -0500
6532 - * $Id: cmdlinepart.c,v 1.9 2003/05/16 17:08:24 dwmw2 Exp $
6533 + * $Id: cmdlinepart.c,v 1.14 2004/07/12 12:34:23 dwmw2 Exp $
6535 * Read flash partition table from command line
6538 * mtdparts=<mtddef>[;<mtddef]
6539 * <mtddef> := <mtd-id>:<partdef>[,<partdef>]
6540 * <partdef> := <size>[@offset][<name>][ro]
6541 - * <mtd-id> := unique id used in mapping driver/device
6542 + * <mtd-id> := unique name used in mapping driver/device (mtd->name)
6543 * <size> := standard linux memsize OR "-" to denote all remaining space
6544 * <name> := '(' NAME ')'
6547 if (size < PAGE_SIZE)
6549 printk(KERN_ERR ERRP "partition size too small (%lx)\n", size);
6556 if ((p = strchr(name, delim)) == 0)
6558 printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
6562 name_len = p - name;
6564 @@ -148,12 +148,12 @@
6565 if (size == SIZE_REMAINING)
6567 printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n");
6571 /* more partitions follow, parse them */
6572 if ((parts = newpart(s + 1, &s, num_parts,
6573 this_part + 1, &extra_mem, extra_mem_size)) == 0)
6578 { /* this is the last partition: allocate space for all */
6582 printk(KERN_ERR ERRP "out of memory\n");
6586 memset(parts, 0, alloc_size);
6587 extra_mem = (unsigned char *)(parts + *num_parts);
6588 @@ -358,14 +358,7 @@
6589 return register_mtd_parser(&cmdline_parser);
6592 -static void __exit cmdline_parser_exit(void)
6594 - deregister_mtd_parser(&cmdline_parser);
6597 module_init(cmdline_parser_init);
6598 -module_exit(cmdline_parser_exit);
6601 MODULE_LICENSE("GPL");
6602 MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
6603 Index: linux-2.6.5/drivers/mtd/devices/Kconfig
6604 ===================================================================
6605 --- linux-2.6.5.orig/drivers/mtd/devices/Kconfig 2004-04-03 22:38:28.000000000 -0500
6606 +++ linux-2.6.5/drivers/mtd/devices/Kconfig 2005-02-01 17:11:17.000000000 -0500
6608 # drivers/mtd/maps/Kconfig
6609 -# $Id: Kconfig,v 1.4 2003/05/28 15:18:54 dwmw2 Exp $
6610 +# $Id: Kconfig,v 1.12 2004/08/10 13:12:18 dwmw2 Exp $
6612 menu "Self-contained MTD device drivers"
6617 tristate "DEC MS02-NV NVRAM module support"
6618 - depends on CONFIG_DECSTATION
6619 + depends on MTD && MACH_DECSTATION
6621 - Support for NVRAM module on DECstation.
6622 + This is an MTD driver for the DEC's MS02-NV (54-20948-01) battery
6623 + backed-up NVRAM module. The module was originally meant as an NFS
6624 + accelerator. Say Y here if you have a DECstation 5000/2x0 or a
6625 + DECsystem 5900 equipped with such a module.
6628 tristate "Uncached system RAM"
6630 you can still use it for storage or swap by using this driver to
6631 present it to the system as a Memory Technology Device.
6634 + tristate "Physical system RAM"
6637 + This is a re-implementation of the slram driver above.
6639 + Use this driver to access physical memory that the kernel proper
6640 + doesn't have access to, memory beyond the mem=xxx limit, nvram,
6641 + memory on the video card, etc...
6644 tristate "28F160xx flash driver for LART"
6645 depends on SA1100_LART && MTD
6647 comment "Disk-On-Chip Device Drivers"
6650 - tristate "M-Systems Disk-On-Chip 2000 and Millennium"
6651 + tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)"
6654 This provides an MTD device driver for the M-Systems DiskOnChip
6655 @@ -131,8 +144,12 @@
6656 emulate a block device by using a kind of file system on the flash
6659 + NOTE: This driver is deprecated and will probably be removed soon.
6660 + Please try the new DiskOnChip driver under "NAND Flash Device
6664 - tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (see help)"
6665 + tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (DEPRECATED)"
6668 This provides an alternative MTD device driver for the M-Systems
6669 @@ -147,6 +164,10 @@
6670 emulate a block device by using a kind of file system on the flash
6673 + NOTE: This driver is deprecated and will probably be removed soon.
6674 + Please try the new DiskOnChip driver under "NAND Flash Device
6677 config MTD_DOC2001PLUS
6678 tristate "M-Systems Disk-On-Chip Millennium Plus"
6680 @@ -159,12 +180,23 @@
6681 to emulate a block device by using a kind of file system on the
6684 + NOTE: This driver will soon be replaced by the new DiskOnChip driver
6685 + under "NAND Flash Device Drivers" (currently that driver does not
6686 + support all Millennium Plus devices).
6690 - default m if MTD_DOC2001!=y && MTD_DOC2000!=y && MTD_DOC2001PLUS!=y && (MTD_DOC2001=m || MTD_DOC2000=m || MOD_DOC2001PLUS=m)
6691 + default m if MTD_DOC2001!=y && MTD_DOC2000!=y && MTD_DOC2001PLUS!=y && (MTD_DOC2001=m || MTD_DOC2000=m || MTD_DOC2001PLUS=m)
6692 default y if MTD_DOC2001=y || MTD_DOC2000=y || MTD_DOC2001PLUS=y
6694 - This isn't a real config option, it's derived.
6695 + This isn't a real config option; it's derived.
6699 + default m if MTD_DOCPROBE!=y && MTD_NAND_DISKONCHIP!=y && (MTD_DOCPROBE=m || MTD_NAND_DISKONCHIP=m)
6700 + default y if MTD_DOCPROBE=y || MTD_NAND_DISKONCHIP=y
6702 + This isn't a real config option; it's derived.
6704 config MTD_DOCPROBE_ADVANCED
6705 bool "Advanced detection options for DiskOnChip"
6706 Index: linux-2.6.5/drivers/mtd/devices/Makefile
6707 ===================================================================
6708 --- linux-2.6.5.orig/drivers/mtd/devices/Makefile 2004-04-03 22:36:13.000000000 -0500
6709 +++ linux-2.6.5/drivers/mtd/devices/Makefile 2005-02-01 17:11:17.000000000 -0500
6712 # linux/drivers/devices/Makefile
6714 -# $Id: Makefile.common,v 1.3 2003/05/28 10:54:23 dwmw2 Exp $
6715 +# $Id: Makefile.common,v 1.6 2004/07/12 16:07:30 dwmw2 Exp $
6717 # *** BIG UGLY NOTE ***
6720 obj-$(CONFIG_MTD_DOC2000) += doc2000.o
6721 obj-$(CONFIG_MTD_DOC2001) += doc2001.o
6722 obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o
6723 -obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o docecc.o
6724 +obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o
6725 +obj-$(CONFIG_MTD_DOCECC) += docecc.o
6726 obj-$(CONFIG_MTD_SLRAM) += slram.o
6727 +obj-$(CONFIG_MTD_PHRAM) += phram.o
6728 obj-$(CONFIG_MTD_PMC551) += pmc551.o
6729 obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o
6730 obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
6731 Index: linux-2.6.5/drivers/mtd/devices/blkmtd-24.c
6732 ===================================================================
6733 --- linux-2.6.5.orig/drivers/mtd/devices/blkmtd-24.c 1969-12-31 19:00:00.000000000 -0500
6734 +++ linux-2.6.5/drivers/mtd/devices/blkmtd-24.c 2005-02-01 17:11:17.000000000 -0500
6737 + * $Id: blkmtd-24.c,v 1.23 2004/08/09 18:49:42 dmarlin Exp $
6739 + * blkmtd.c - use a block device as a fake MTD
6741 + * Author: Simon Evans <spse@secret.org.uk>
6743 + * Copyright (C) 2001,2002 Simon Evans
6748 + * The driver uses raw/io to read/write the device and the page
6749 + * cache to cache access. Writes update the page cache with the
6750 + * new data and mark it dirty and add the page into a kiobuf.
6751 + * When the kiobuf becomes full or the next extry is to an earlier
6752 + * block in the kiobuf then it is flushed to disk. This allows
6753 + * writes to remained ordered and gives a small and simple outgoing
6756 + * It can be loaded Read-Only to prevent erases and writes to the
6761 +#include <linux/config.h>
6762 +#include <linux/module.h>
6763 +#include <linux/fs.h>
6764 +#include <linux/blkdev.h>
6765 +#include <linux/iobuf.h>
6766 +#include <linux/slab.h>
6767 +#include <linux/pagemap.h>
6768 +#include <linux/list.h>
6769 +#include <linux/mtd/mtd.h>
6771 +#ifdef CONFIG_MTD_DEBUG
6772 +#ifdef CONFIG_PROC_FS
6773 +# include <linux/proc_fs.h>
6774 +# define BLKMTD_PROC_DEBUG
6775 + static struct proc_dir_entry *blkmtd_proc;
6780 +#define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg)
6781 +#define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg)
6782 +#define warn(format, arg...) printk(KERN_WARNING "blkmtd: " format "\n" , ## arg)
6783 +#define crit(format, arg...) printk(KERN_CRIT "blkmtd: " format "\n" , ## arg)
6786 +/* Default erase size in KiB, always make it a multiple of PAGE_SIZE */
6787 +#define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */
6788 +#define VERSION "1.10"
6790 +/* Info for the block device */
6791 +struct blkmtd_dev {
6792 + struct list_head list;
6793 + struct block_device *binding;
6794 + struct mtd_info mtd_info;
6795 + struct kiobuf *rd_buf, *wr_buf;
6797 + struct semaphore wrbuf_mutex;
6801 +/* Static info about the MTD, used in cleanup_module */
6802 +static LIST_HEAD(blkmtd_device_list);
6805 +static void blkmtd_sync(struct mtd_info *mtd);
6807 +#define MAX_DEVICES 4
6809 +/* Module parameters passed by insmod/modprobe */
6810 +char *device[MAX_DEVICES]; /* the block device to use */
6811 +int erasesz[MAX_DEVICES]; /* optional default erase size */
6812 +int ro[MAX_DEVICES]; /* optional read only flag */
6816 +MODULE_LICENSE("GPL");
6817 +MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
6818 +MODULE_DESCRIPTION("Emulate an MTD using a block device");
6819 +MODULE_PARM(device, "1-4s");
6820 +MODULE_PARM_DESC(device, "block device to use");
6821 +MODULE_PARM(erasesz, "1-4i");
6822 +MODULE_PARM_DESC(erasesz, "optional erase size to use in KiB. eg 4=4KiB.");
6823 +MODULE_PARM(ro, "1-4i");
6824 +MODULE_PARM_DESC(ro, "1=Read only, writes and erases cause errors");
6825 +MODULE_PARM(sync, "i");
6826 +MODULE_PARM_DESC(sync, "1=Synchronous writes");
6830 + * read_pages - read in pages via the page cache
6831 + * @dev: device to read from
6832 + * @pagenrs: list of page numbers wanted
6833 + * @pagelst: storage for struce page * pointers
6834 + * @pages: count of pages wanted
6836 + * Read pages, getting them from the page cache if available
6837 + * else reading them in from disk if not. pagelst must be preallocated
6838 + * to hold the page count.
6840 +static int read_pages(struct blkmtd_dev *dev, int pagenrs[], struct page **pagelst, int pages)
6843 + struct page *page;
6845 + struct kiobuf *iobuf;
6849 + err("read_pages: PANIC dev == NULL");
6852 + kdev = to_kdev_t(dev->binding->bd_dev);
6854 + DEBUG(2, "read_pages: reading %d pages\n", pages);
6855 + if(test_and_set_bit(0, &dev->iobuf_locks)) {
6856 + err = alloc_kiovec(1, &iobuf);
6858 + crit("cant allocate kiobuf");
6861 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
6862 + iobuf->blocks = kmalloc(KIO_MAX_SECTORS * sizeof(unsigned long), GFP_KERNEL);
6863 + if(iobuf->blocks == NULL) {
6864 + crit("cant allocate iobuf blocks");
6865 + free_kiovec(1, &iobuf);
6870 + iobuf = dev->rd_buf;
6873 + iobuf->nr_pages = 0;
6874 + iobuf->length = 0;
6875 + iobuf->offset = 0;
6876 + iobuf->locked = 1;
6878 + for(cnt = 0; cnt < pages; cnt++) {
6879 + page = grab_cache_page(dev->binding->bd_inode->i_mapping, pagenrs[cnt]);
6880 + pagelst[cnt] = page;
6881 + if(!Page_Uptodate(page)) {
6882 + iobuf->blocks[iobuf->nr_pages] = pagenrs[cnt];
6883 + iobuf->maplist[iobuf->nr_pages++] = page;
6887 + if(iobuf->nr_pages) {
6888 + iobuf->length = iobuf->nr_pages << PAGE_SHIFT;
6889 + err = brw_kiovec(READ, 1, &iobuf, kdev, iobuf->blocks, PAGE_SIZE);
6890 + DEBUG(3, "blkmtd: read_pages: finished, err = %d\n", err);
6893 + ClearPageUptodate(pagelst[pages]);
6894 + unlock_page(pagelst[pages]);
6895 + page_cache_release(pagelst[pages]);
6898 + while(iobuf->nr_pages--) {
6899 + SetPageUptodate(iobuf->maplist[iobuf->nr_pages]);
6906 + if(iobuf != dev->rd_buf) {
6907 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
6908 + kfree(iobuf->blocks);
6910 + free_kiovec(1, &iobuf);
6912 + clear_bit(0, &dev->iobuf_locks);
6914 + DEBUG(2, "read_pages: done, err = %d\n", err);
6920 + * commit_pages - commit pages in the writeout kiobuf to disk
6921 + * @dev: device to write to
6923 + * If the current dev has pages in the dev->wr_buf kiobuf,
6924 + * they are written to disk using brw_kiovec()
6926 +static int commit_pages(struct blkmtd_dev *dev)
6928 + struct kiobuf *iobuf = dev->wr_buf;
6929 + kdev_t kdev = to_kdev_t(dev->binding->bd_dev);
6932 + iobuf->length = iobuf->nr_pages << PAGE_SHIFT;
6933 + iobuf->locked = 1;
6934 + if(iobuf->length) {
6936 + DEBUG(2, "blkmtd: commit_pages: nrpages = %d\n", iobuf->nr_pages);
6937 + /* Check all the pages are dirty and lock them */
6938 + for(i = 0; i < iobuf->nr_pages; i++) {
6939 + struct page *page = iobuf->maplist[i];
6940 + BUG_ON(!PageDirty(page));
6943 + err = brw_kiovec(WRITE, 1, &iobuf, kdev, iobuf->blocks, PAGE_SIZE);
6944 + DEBUG(3, "commit_write: committed %d pages err = %d\n", iobuf->nr_pages, err);
6945 + while(iobuf->nr_pages) {
6946 + struct page *page = iobuf->maplist[--iobuf->nr_pages];
6947 + ClearPageDirty(page);
6948 + SetPageUptodate(page);
6949 + unlock_page(page);
6950 + page_cache_release(page);
6954 + DEBUG(2, "blkmtd: sync: end, err = %d\n", err);
6955 + iobuf->offset = 0;
6956 + iobuf->nr_pages = 0;
6957 + iobuf->length = 0;
6963 + * write_pages - write block of data to device via the page cache
6964 + * @dev: device to write to
6965 + * @buf: data source or NULL if erase (output is set to 0xff)
6966 + * @to: offset into output device
6967 + * @len: amount to data to write
6968 + * @retlen: amount of data written
6970 + * Grab pages from the page cache and fill them with the source data.
6971 + * Non page aligned start and end result in a readin of the page and
6972 + * part of the page being modified. Pages are added to the wr_buf kiobuf
6973 + * until this becomes full or the next page written to has a lower pagenr
6974 + * then the current max pagenr in the kiobuf.
6976 +static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to,
6977 + size_t len, int *retlen)
6979 + int pagenr, offset;
6980 + size_t start_len = 0, end_len;
6982 + struct kiobuf *iobuf = dev->wr_buf;
6984 + struct page *pagelst[2];
6986 + int readpages = 0;
6987 + int ignorepage = -1;
6989 + pagenr = to >> PAGE_SHIFT;
6990 + offset = to & ~PAGE_MASK;
6992 + DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %zd pagenr = %d offset = %d\n",
6993 + buf, (long)to, len, pagenr, offset);
6996 + /* see if we have to do a partial write at the start */
6998 + start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len;
7002 + /* calculate the length of the other two regions */
7003 + end_len = len & ~PAGE_MASK;
7007 + pagenrs[0] = pagenr;
7012 + pagecnt += len >> PAGE_SHIFT;
7014 + pagenrs[readpages] = pagenr + pagecnt;
7019 + DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n",
7020 + start_len, len, end_len, pagecnt);
7022 + down(&dev->wrbuf_mutex);
7024 + if(iobuf->nr_pages && ((pagenr <= iobuf->blocks[iobuf->nr_pages-1])
7025 + || (iobuf->nr_pages + pagecnt) >= KIO_STATIC_PAGES)) {
7027 + if((pagenr == iobuf->blocks[iobuf->nr_pages-1])
7028 + && ((iobuf->nr_pages + pagecnt) < KIO_STATIC_PAGES)) {
7029 + iobuf->nr_pages--;
7030 + ignorepage = pagenr;
7032 + DEBUG(3, "blkmtd: doing writeout pagenr = %d max_pagenr = %ld pagecnt = %d idx = %d\n",
7033 + pagenr, iobuf->blocks[iobuf->nr_pages-1],
7034 + pagecnt, iobuf->nr_pages);
7035 + commit_pages(dev);
7040 + err = read_pages(dev, pagenrs, pagelst, readpages);
7046 + /* do partial start region */
7047 + struct page *page;
7049 + DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %zd offset = %d\n",
7050 + pagenr, start_len, offset);
7051 + page = pagelst[0];
7053 + if(PageDirty(page) && pagenr != ignorepage) {
7054 + err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d ignorepage = %d\n",
7055 + to, start_len, len, end_len, pagenr, ignorepage);
7058 + memcpy(page_address(page)+offset, buf, start_len);
7059 + SetPageDirty(page);
7060 + SetPageUptodate(page);
7061 + unlock_page(page);
7063 + *retlen = start_len;
7065 + iobuf->blocks[iobuf->nr_pages] = pagenr++;
7066 + iobuf->maplist[iobuf->nr_pages] = page;
7067 + iobuf->nr_pages++;
7070 + /* Now do the main loop to a page aligned, n page sized output */
7072 + int pagesc = len >> PAGE_SHIFT;
7073 + DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n",
7076 + struct page *page;
7078 + /* see if page is in the page cache */
7079 + DEBUG(3, "blkmtd: write: grabbing page %d from page cache\n", pagenr);
7080 + page = grab_cache_page(dev->binding->bd_inode->i_mapping, pagenr);
7081 + if(PageDirty(page) && pagenr != ignorepage) {
7085 + warn("write: cant grab cache page %d", pagenr);
7090 + memset(page_address(page), 0xff, PAGE_SIZE);
7092 + memcpy(page_address(page), buf, PAGE_SIZE);
7095 + iobuf->blocks[iobuf->nr_pages] = pagenr++;
7096 + iobuf->maplist[iobuf->nr_pages] = page;
7097 + iobuf->nr_pages++;
7098 + SetPageDirty(page);
7099 + SetPageUptodate(page);
7100 + unlock_page(page);
7102 + *retlen += PAGE_SIZE;
7107 + /* do the third region */
7108 + struct page *page;
7109 + DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %zd\n",
7111 + page = pagelst[readpages-1];
7113 + if(PageDirty(page) && pagenr != ignorepage) {
7114 + err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d ignorepage = %d\n",
7115 + to, start_len, len, end_len, pagenr, ignorepage);
7118 + memcpy(page_address(page), buf, end_len);
7119 + SetPageDirty(page);
7120 + SetPageUptodate(page);
7121 + unlock_page(page);
7122 + DEBUG(3, "blkmtd: write: writing out partial end\n");
7123 + *retlen += end_len;
7125 + iobuf->blocks[iobuf->nr_pages] = pagenr;
7126 + iobuf->maplist[iobuf->nr_pages] = page;
7127 + iobuf->nr_pages++;
7130 + DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err);
7134 + commit_pages(dev);
7138 + up(&dev->wrbuf_mutex);
7143 +/* erase a specified part of the device */
7144 +static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr)
7146 + struct blkmtd_dev *dev = mtd->priv;
7147 + struct mtd_erase_region_info *einfo = mtd->eraseregions;
7148 + int numregions = mtd->numeraseregions;
7154 + /* check readonly */
7155 + if(!dev->wr_buf) {
7156 + err("error: mtd%d trying to erase readonly device %s",
7157 + mtd->index, mtd->name);
7158 + instr->state = MTD_ERASE_FAILED;
7159 + goto erase_callback;
7162 + instr->state = MTD_ERASING;
7163 + from = instr->addr;
7166 + /* check erase region has valid start and length */
7167 + DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%zx len = 0x%lx\n",
7168 + bdevname(dev->binding->bd_dev), from, len);
7169 + while(numregions) {
7170 + DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n",
7171 + einfo->offset, einfo->erasesize, einfo->numblocks);
7172 + if(from >= einfo->offset
7173 + && from < einfo->offset + (einfo->erasesize * einfo->numblocks)) {
7174 + if(len == einfo->erasesize
7175 + && ( (from - einfo->offset) % einfo->erasesize == 0))
7183 + /* Not a valid erase block */
7184 + err("erase: invalid erase request 0x%lX @ 0x%08zX", len, from);
7185 + instr->state = MTD_ERASE_FAILED;
7189 + if(instr->state != MTD_ERASE_FAILED) {
7190 + /* do the erase */
7191 + DEBUG(3, "Doing erase from = %zd len = %ld\n", from, len);
7192 + err = write_pages(dev, NULL, from, len, &retlen);
7194 + err("erase failed err = %d", err);
7195 + instr->state = MTD_ERASE_FAILED;
7197 + instr->state = MTD_ERASE_DONE;
7202 + DEBUG(3, "blkmtd: erase: checking callback\n");
7204 + mtd_erase_callback(instr);
7205 + DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
7210 +/* read a range of the data via the page cache */
7211 +static int blkmtd_read(struct mtd_info *mtd, loff_t from, size_t len,
7212 + size_t *retlen, u_char *buf)
7214 + struct blkmtd_dev *dev = mtd->priv;
7217 + int pagenr, pages;
7218 + struct page **pagelst;
7224 + DEBUG(2, "blkmtd: read: dev = `%s' from = %lld len = %zd buf = %p\n",
7225 + bdevname(dev->binding->bd_dev), from, len, buf);
7227 + pagenr = from >> PAGE_SHIFT;
7228 + offset = from - (pagenr << PAGE_SHIFT);
7230 + pages = (offset+len+PAGE_SIZE-1) >> PAGE_SHIFT;
7231 + DEBUG(3, "blkmtd: read: pagenr = %d offset = %d, pages = %d\n",
7232 + pagenr, offset, pages);
7234 + pagelst = kmalloc(sizeof(struct page *) * pages, GFP_KERNEL);
7237 + pagenrs = kmalloc(sizeof(int) * pages, GFP_KERNEL);
7242 + for(i = 0; i < pages; i++)
7243 + pagenrs[i] = pagenr+i;
7245 + err = read_pages(dev, pagenrs, pagelst, pages);
7251 + struct page *page;
7254 + DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr);
7255 + page = pagelst[pagenr];
7257 + cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE;
7258 + if(offset+cpylen > PAGE_SIZE)
7259 + cpylen = PAGE_SIZE-offset;
7261 + memcpy(buf + *retlen, page_address(page) + offset, cpylen);
7264 + *retlen += cpylen;
7267 + unlock_page(page);
7268 + if(!PageDirty(page))
7269 + page_cache_release(page);
7275 + DEBUG(2, "blkmtd: end read: retlen = %zd, err = %d\n", *retlen, err);
7280 +/* write data to the underlying device */
7281 +static int blkmtd_write(struct mtd_info *mtd, loff_t to, size_t len,
7282 + size_t *retlen, const u_char *buf)
7284 + struct blkmtd_dev *dev = mtd->priv;
7291 + DEBUG(2, "blkmtd: write: dev = `%s' to = %lld len = %zd buf = %p\n",
7292 + bdevname(dev->binding->bd_dev), to, len, buf);
7294 + /* handle readonly and out of range numbers */
7296 + if(!dev->wr_buf) {
7297 + err("error: trying to write to a readonly device %s", mtd->name);
7301 + if(to >= mtd->size) {
7305 + if(to + len > mtd->size) {
7306 + len = (mtd->size - to);
7309 + err = write_pages(dev, buf, to, len, retlen);
7314 + DEBUG(2, "blkmtd: write: end, err = %d\n", err);
7319 +/* sync the device - wait until the write queue is empty */
7320 +static void blkmtd_sync(struct mtd_info *mtd)
7322 + struct blkmtd_dev *dev = mtd->priv;
7323 + struct kiobuf *iobuf = dev->wr_buf;
7325 + DEBUG(2, "blkmtd: sync: called\n");
7329 + DEBUG(3, "blkmtd: kiovec: length = %d nr_pages = %d\n",
7330 + iobuf->length, iobuf->nr_pages);
7331 + down(&dev->wrbuf_mutex);
7332 + if(iobuf->nr_pages)
7333 + commit_pages(dev);
7334 + up(&dev->wrbuf_mutex);
7338 +#ifdef BLKMTD_PROC_DEBUG
7340 +static int blkmtd_proc_read(char *page, char **start, off_t off,
7341 + int count, int *eof, void *data)
7344 + struct list_head *temp1, *temp2;
7346 + MOD_INC_USE_COUNT;
7348 + /* Count the size of the page lists */
7350 + len = sprintf(page, "dev\twr_idx\tmax_idx\tnrpages\tclean\tdirty\tlocked\tlru\n");
7351 + list_for_each_safe(temp1, temp2, &blkmtd_device_list) {
7352 + struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev,
7354 + struct list_head *temp;
7355 + struct page *pagei;
7357 + int clean = 0, dirty = 0, locked = 0, lru = 0;
7358 + /* Count the size of the page lists */
7359 + list_for_each(temp, &dev->binding->bd_inode->i_mapping->clean_pages) {
7360 + pagei = list_entry(temp, struct page, list);
7362 + if(PageLocked(pagei))
7364 + if(PageDirty(pagei))
7366 + if(PageLRU(pagei))
7369 + list_for_each(temp, &dev->binding->bd_inode->i_mapping->dirty_pages) {
7370 + pagei = list_entry(temp, struct page, list);
7371 + if(PageLocked(pagei))
7373 + if(PageDirty(pagei))
7375 + if(PageLRU(pagei))
7378 + list_for_each(temp, &dev->binding->bd_inode->i_mapping->locked_pages) {
7379 + pagei = list_entry(temp, struct page, list);
7380 + if(PageLocked(pagei))
7382 + if(PageDirty(pagei))
7384 + if(PageLRU(pagei))
7388 + len += sprintf(page+len, "mtd%d:\t%ld\t%d\t%ld\t%d\t%d\t%d\t%d\n",
7389 + dev->mtd_info.index,
7390 + (dev->wr_buf && dev->wr_buf->nr_pages) ?
7391 + dev->wr_buf->blocks[dev->wr_buf->nr_pages-1] : 0,
7392 + (dev->wr_buf) ? dev->wr_buf->nr_pages : 0,
7393 + dev->binding->bd_inode->i_mapping->nrpages,
7394 + clean, dirty, locked, lru);
7400 + MOD_DEC_USE_COUNT;
7406 +static void free_device(struct blkmtd_dev *dev)
7408 + DEBUG(2, "blkmtd: free_device() dev = %p\n", dev);
7410 + del_mtd_device(&dev->mtd_info);
7411 + info("mtd%d: [%s] removed", dev->mtd_info.index,
7412 + dev->mtd_info.name + strlen("blkmtd: "));
7413 + if(dev->mtd_info.eraseregions)
7414 + kfree(dev->mtd_info.eraseregions);
7415 + if(dev->mtd_info.name)
7416 + kfree(dev->mtd_info.name);
7419 + dev->rd_buf->locked = 0;
7420 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
7421 + if(dev->rd_buf->blocks)
7422 + kfree(dev->rd_buf->blocks);
7424 + free_kiovec(1, &dev->rd_buf);
7427 + dev->wr_buf->locked = 0;
7428 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
7429 + if(dev->wr_buf->blocks)
7430 + kfree(dev->rw_buf->blocks);
7432 + free_kiovec(1, &dev->wr_buf);
7435 + if(dev->binding) {
7436 + kdev_t kdev = to_kdev_t(dev->binding->bd_dev);
7437 + invalidate_inode_pages(dev->binding->bd_inode);
7438 + set_blocksize(kdev, 1 << 10);
7439 + blkdev_put(dev->binding, BDEV_RAW);
7446 +/* For a given size and initial erase size, calculate the number
7447 + * and size of each erase region. Goes round the loop twice,
7448 + * once to find out how many regions, then allocates space,
7449 + * then round the loop again to fill it in.
7451 +static struct mtd_erase_region_info *calc_erase_regions(
7452 + size_t erase_size, size_t total_size, int *regions)
7454 + struct mtd_erase_region_info *info = NULL;
7456 + DEBUG(2, "calc_erase_regions, es = %zd size = %zd regions = %d\n",
7457 + erase_size, total_size, *regions);
7458 + /* Make any user specified erasesize be a power of 2
7459 + and at least PAGE_SIZE */
7461 + int es = erase_size;
7467 + if(erase_size < PAGE_SIZE)
7468 + erase_size = PAGE_SIZE;
7470 + erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
7476 + int tot_size = total_size;
7477 + int er_size = erase_size;
7478 + int count = 0, offset = 0, regcnt = 0;
7481 + count = tot_size / er_size;
7483 + tot_size = tot_size % er_size;
7485 + DEBUG(2, "adding to erase info off=%d er=%d cnt=%d\n",
7486 + offset, er_size, count);
7487 + (info+regcnt)->offset = offset;
7488 + (info+regcnt)->erasesize = er_size;
7489 + (info+regcnt)->numblocks = count;
7493 + offset += (count * er_size);
7495 + while(er_size > tot_size)
7498 + if(info == NULL) {
7499 + info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL);
7503 + } while(!(*regions));
7504 + DEBUG(2, "calc_erase_regions done, es = %zd size = %zd regions = %d\n",
7505 + erase_size, total_size, *regions);
7510 +extern kdev_t name_to_kdev_t(char *line) __init;
7513 +static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size)
7518 + struct blkmtd_dev *dev;
7521 + struct file *file = NULL;
7522 + struct inode *inode;
7528 + /* Get a handle on the device */
7529 + mode = (readonly) ? O_RDONLY : O_RDWR;
7533 + file = filp_open(devname, mode, 0);
7534 + if(IS_ERR(file)) {
7535 + err("error: cant open device %s", devname);
7536 + DEBUG(2, "blkmtd: filp_open returned %ld\n", PTR_ERR(file));
7540 + /* determine is this is a block device and
7541 + * if so get its major and minor numbers
7543 + inode = file->f_dentry->d_inode;
7544 + if(!S_ISBLK(inode->i_mode)) {
7545 + err("%s not a block device", devname);
7546 + filp_close(file, NULL);
7549 + kdev = inode->i_rdev;
7550 + filp_close(file, NULL);
7552 + kdev = name_to_kdev_t(devname);
7553 +#endif /* MODULE */
7556 + err("bad block device: `%s'", devname);
7560 + maj = MAJOR(kdev);
7561 + min = MINOR(kdev);
7562 + DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n",
7565 + if(maj == MTD_BLOCK_MAJOR) {
7566 + err("attempting to use an MTD device as a block device");
7570 + DEBUG(1, "blkmtd: devname = %s\n", bdevname(kdev));
7572 + dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL);
7576 + memset(dev, 0, sizeof(struct blkmtd_dev));
7577 + if(alloc_kiovec(1, &dev->rd_buf)) {
7578 + err("cant allocate read iobuf");
7581 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
7582 + dev->rd_buf->blocks = kmalloc(KIO_MAX_SECTORS * sizeof(unsigned long), GFP_KERNEL);
7583 + if(dev->rd_buf->blocks == NULL) {
7584 + crit("cant allocate rd_buf blocks");
7590 + if(alloc_kiovec(1, &dev->wr_buf)) {
7591 + err("cant allocate kiobuf - readonly enabled");
7593 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
7595 + dev->wr_buf->blocks = kmalloc(KIO_MAX_SECTORS * sizeof(unsigned long), GFP_KERNEL);
7596 + if(dev->wr_buf->blocks == NULL) {
7597 + crit("cant allocate wr_buf blocks - readonly enabled");
7598 + free_kiovec(1, &iobuf);
7603 + init_MUTEX(&dev->wrbuf_mutex);
7606 + /* get the block device */
7607 + dev->binding = bdget(kdev_t_to_nr(MKDEV(maj, min)));
7608 + if(blkdev_get(dev->binding, mode, 0, BDEV_RAW))
7611 + if(set_blocksize(kdev, PAGE_SIZE)) {
7612 + err("cant set block size to PAGE_SIZE on %s", bdevname(kdev));
7616 + dev->mtd_info.size = dev->binding->bd_inode->i_size & PAGE_MASK;
7618 + /* Setup the MTD structure */
7619 + /* make the name contain the block device in */
7620 + dev->mtd_info.name = kmalloc(sizeof("blkmtd: ") + strlen(devname), GFP_KERNEL);
7621 + if(dev->mtd_info.name == NULL)
7624 + sprintf(dev->mtd_info.name, "blkmtd: %s", devname);
7625 + dev->mtd_info.eraseregions = calc_erase_regions(erase_size, dev->mtd_info.size,
7626 + &dev->mtd_info.numeraseregions);
7627 + if(dev->mtd_info.eraseregions == NULL)
7630 + dev->mtd_info.erasesize = dev->mtd_info.eraseregions->erasesize;
7631 + DEBUG(1, "blkmtd: init: found %d erase regions\n",
7632 + dev->mtd_info.numeraseregions);
7635 + dev->mtd_info.type = MTD_ROM;
7636 + dev->mtd_info.flags = MTD_CAP_ROM;
7638 + dev->mtd_info.type = MTD_RAM;
7639 + dev->mtd_info.flags = MTD_CAP_RAM;
7641 + dev->mtd_info.erase = blkmtd_erase;
7642 + dev->mtd_info.read = blkmtd_read;
7643 + dev->mtd_info.write = blkmtd_write;
7644 + dev->mtd_info.sync = blkmtd_sync;
7645 + dev->mtd_info.point = 0;
7646 + dev->mtd_info.unpoint = 0;
7647 + dev->mtd_info.priv = dev;
7648 + dev->mtd_info.owner = THIS_MODULE;
7650 + list_add(&dev->list, &blkmtd_device_list);
7651 + if (add_mtd_device(&dev->mtd_info)) {
7652 + /* Device didnt get added, so free the entry */
7653 + list_del(&dev->list);
7657 + info("mtd%d: [%s] erase_size = %dKiB %s",
7658 + dev->mtd_info.index, dev->mtd_info.name + strlen("blkmtd: "),
7659 + dev->mtd_info.erasesize >> 10,
7660 + (dev->wr_buf) ? "" : "(read-only)");
7671 +/* Cleanup and exit - sync the device and kill of the kernel thread */
7672 +static void __devexit cleanup_blkmtd(void)
7674 + struct list_head *temp1, *temp2;
7675 +#ifdef BLKMTD_PROC_DEBUG
7677 + remove_proc_entry("blkmtd_debug", NULL);
7681 + /* Remove the MTD devices */
7682 + list_for_each_safe(temp1, temp2, &blkmtd_device_list) {
7683 + struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev,
7685 + blkmtd_sync(&dev->mtd_info);
7692 +/* Handle kernel boot params */
7695 +static int __init param_blkmtd_device(char *str)
7699 + for(i = 0; i < MAX_DEVICES; i++) {
7701 + DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]);
7702 + strsep(&str, ",");
7708 +static int __init param_blkmtd_erasesz(char *str)
7711 + for(i = 0; i < MAX_DEVICES; i++) {
7712 + char *val = strsep(&str, ",");
7714 + erasesz[i] = simple_strtoul(val, NULL, 0);
7715 + DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]);
7722 +static int __init param_blkmtd_ro(char *str)
7725 + for(i = 0; i < MAX_DEVICES; i++) {
7726 + char *val = strsep(&str, ",");
7728 + ro[i] = simple_strtoul(val, NULL, 0);
7729 + DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]);
7736 +static int __init param_blkmtd_sync(char *str)
7743 +__setup("blkmtd_device=", param_blkmtd_device);
7744 +__setup("blkmtd_erasesz=", param_blkmtd_erasesz);
7745 +__setup("blkmtd_ro=", param_blkmtd_ro);
7746 +__setup("blkmtd_sync=", param_blkmtd_sync);
7752 +static int __init init_blkmtd(void)
7756 + /* Check args - device[0] is the bare minimum*/
7758 + err("error: missing `device' name\n");
7762 + for(i = 0; i < MAX_DEVICES; i++)
7763 + add_device(device[i], ro[i], erasesz[i] << 10);
7765 + if(list_empty(&blkmtd_device_list))
7768 + info("version " VERSION);
7770 +#ifdef BLKMTD_PROC_DEBUG
7771 + /* create proc entry */
7772 + DEBUG(2, "Creating /proc/blkmtd_debug\n");
7773 + blkmtd_proc = create_proc_read_entry("blkmtd_debug", 0444,
7774 + NULL, blkmtd_proc_read, NULL);
7775 + if(blkmtd_proc == NULL) {
7776 + err("Cant create /proc/blkmtd_debug");
7778 + blkmtd_proc->owner = THIS_MODULE;
7782 + if(!list_empty(&blkmtd_device_list))
7783 + /* Everything is ok if we got here */
7790 +module_init(init_blkmtd);
7791 +module_exit(cleanup_blkmtd);
7792 Index: linux-2.6.5/drivers/mtd/devices/blkmtd.c
7793 ===================================================================
7794 --- linux-2.6.5.orig/drivers/mtd/devices/blkmtd.c 2005-02-01 16:55:31.000000000 -0500
7795 +++ linux-2.6.5/drivers/mtd/devices/blkmtd.c 2005-02-01 17:11:17.000000000 -0500
7798 - * $Id: blkmtd-25.c,v 1.5 2003/07/16 06:48:27 spse Exp $
7799 + * $Id: blkmtd.c,v 1.23 2004/08/09 14:03:19 dwmw2 Exp $
7801 * blkmtd.c - use a block device as a fake MTD
7805 /* Default erase size in K, always make it a multiple of PAGE_SIZE */
7806 #define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */
7807 -#define VERSION "$Revision: 1.5 $"
7808 +#define VERSION "$Revision: 1.23 $"
7810 /* Info for the block device */
7813 pagenr = to >> PAGE_SHIFT;
7814 offset = to & ~PAGE_MASK;
7816 - DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %d pagenr = %d offset = %d\n",
7817 + DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %zd pagenr = %d offset = %d\n",
7818 buf, (long)to, len, pagenr, offset);
7820 /* see if we have to do a partial write at the start */
7821 @@ -270,21 +270,21 @@
7823 down(&dev->wrbuf_mutex);
7825 - DEBUG(3, "blkmtd: write: start_len = %d len = %d end_len = %d pagecnt = %d\n",
7826 + DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n",
7827 start_len, len, end_len, pagecnt);
7830 /* do partial start region */
7833 - DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %d offset = %d\n",
7834 + DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %zd offset = %d\n",
7835 pagenr, start_len, offset);
7838 page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
7840 if(PageDirty(page)) {
7841 - err("to = %lld start_len = %d len = %d end_len = %d pagenr = %d\n",
7842 + err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
7843 to, start_len, len, end_len, pagenr);
7846 @@ -346,13 +346,13 @@
7848 /* do the third region */
7850 - DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %d\n",
7851 + DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %zd\n",
7854 page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
7856 if(PageDirty(page)) {
7857 - err("to = %lld start_len = %d len = %d end_len = %d pagenr = %d\n",
7858 + err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
7859 to, start_len, len, end_len, pagenr);
7864 blkmtd_write_out(bio);
7866 - DEBUG(2, "blkmtd: write: end, retlen = %d, err = %d\n", *retlen, err);
7867 + DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err);
7868 up(&dev->wrbuf_mutex);
7871 @@ -393,14 +393,14 @@
7878 instr->state = MTD_ERASING;
7882 /* check erase region has valid start and length */
7883 - DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%x len = 0x%lx\n",
7884 + DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%zx len = 0x%lx\n",
7885 mtd->name+9, from, len);
7887 DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n",
7888 @@ -417,14 +417,14 @@
7891 /* Not a valid erase block */
7892 - err("erase: invalid erase request 0x%lX @ 0x%08X", len, from);
7893 + err("erase: invalid erase request 0x%lX @ 0x%08zX", len, from);
7894 instr->state = MTD_ERASE_FAILED;
7898 if(instr->state != MTD_ERASE_FAILED) {
7900 - DEBUG(3, "Doing erase from = %d len = %ld\n", from, len);
7901 + DEBUG(3, "Doing erase from = %zd len = %ld\n", from, len);
7902 err = write_pages(dev, NULL, from, len, &retlen);
7903 if(err || retlen != len) {
7904 err("erase failed err = %d", err);
7908 DEBUG(3, "blkmtd: erase: checking callback\n");
7909 - if (instr->callback) {
7910 - (*(instr->callback))(instr);
7912 + mtd_erase_callback(instr);
7913 DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
7920 - DEBUG(2, "blkmtd: read: dev = `%s' from = %ld len = %d buf = %p\n",
7921 - mtd->name+9, (long int)from, len, buf);
7922 + DEBUG(2, "blkmtd: read: dev = `%s' from = %lld len = %zd buf = %p\n",
7923 + mtd->name+9, from, len, buf);
7925 if(from > mtd->size)
7931 - DEBUG(2, "blkmtd: end read: retlen = %d, err = %d\n", thislen, err);
7932 + DEBUG(2, "blkmtd: end read: retlen = %zd, err = %d\n", thislen, err);
7940 - DEBUG(2, "blkmtd: write: dev = `%s' to = %ld len = %d buf = %p\n",
7941 - mtd->name+9, (long int)to, len, buf);
7942 + DEBUG(2, "blkmtd: write: dev = `%s' to = %lld len = %zd buf = %p\n",
7943 + mtd->name+9, to, len, buf);
7945 if(to >= mtd->size) {
7949 struct mtd_erase_region_info *info = NULL;
7951 - DEBUG(2, "calc_erase_regions, es = %d size = %d regions = %d\n",
7952 + DEBUG(2, "calc_erase_regions, es = %zd size = %zd regions = %d\n",
7953 erase_size, total_size, *regions);
7954 /* Make any user specified erasesize be a power of 2
7955 and at least PAGE_SIZE */
7959 } while(!(*regions));
7960 - DEBUG(2, "calc_erase_regions done, es = %d size = %d regions = %d\n",
7961 + DEBUG(2, "calc_erase_regions done, es = %zd size = %zd regions = %d\n",
7962 erase_size, total_size, *regions);
7965 Index: linux-2.6.5/drivers/mtd/devices/doc2000.c
7966 ===================================================================
7967 --- linux-2.6.5.orig/drivers/mtd/devices/doc2000.c 2004-04-03 22:36:12.000000000 -0500
7968 +++ linux-2.6.5/drivers/mtd/devices/doc2000.c 2005-02-01 17:11:17.000000000 -0500
7970 * (c) 1999 Machine Vision Holdings, Inc.
7971 * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
7973 - * $Id: doc2000.c,v 1.53 2003/06/11 09:45:19 dwmw2 Exp $
7974 + * $Id: doc2000.c,v 1.63 2004/09/16 23:51:56 gleixner Exp $
7977 #include <linux/kernel.h>
7979 #include <linux/sched.h>
7980 #include <linux/init.h>
7981 #include <linux/types.h>
7982 +#include <linux/bitops.h>
7984 #include <linux/mtd/mtd.h>
7985 #include <linux/mtd/nand.h>
7986 #include <linux/mtd/doc2000.h>
7988 #define DOC_SUPPORT_2000
7989 +#define DOC_SUPPORT_2000TSOP
7990 #define DOC_SUPPORT_MILLENNIUM
7992 #ifdef DOC_SUPPORT_2000
7994 #define DoC_is_2000(doc) (0)
7997 -#ifdef DOC_SUPPORT_MILLENNIUM
7998 +#if defined(DOC_SUPPORT_2000TSOP) || defined(DOC_SUPPORT_MILLENNIUM)
7999 #define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil)
8001 #define DoC_is_Millennium(doc) (0)
8003 static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
8004 size_t *retlen, const u_char *buf);
8005 static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
8006 - size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel);
8007 + size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
8008 static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
8009 - size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel);
8010 + size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
8011 +static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
8012 + unsigned long count, loff_t to, size_t *retlen,
8013 + u_char *eccbuf, struct nand_oobinfo *oobsel);
8014 static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
8015 size_t *retlen, u_char *buf);
8016 static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
8018 /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
8019 static int _DoC_WaitReady(struct DiskOnChip *doc)
8021 - unsigned long docptr = doc->virtadr;
8022 + void __iomem *docptr = doc->virtadr;
8023 unsigned long timeo = jiffies + (HZ * 10);
8025 DEBUG(MTD_DEBUG_LEVEL3,
8028 /* Out-of-line routine to wait for chip response */
8029 while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
8030 + /* issue 2 read from NOP register after reading from CDSNControl register
8031 + see Software Requirement 11.4 item 2. */
8032 + DoC_Delay(doc, 2);
8034 if (time_after(jiffies, timeo)) {
8035 DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
8039 static inline int DoC_WaitReady(struct DiskOnChip *doc)
8041 - unsigned long docptr = doc->virtadr;
8042 + void __iomem *docptr = doc->virtadr;
8044 /* This is inline, to optimise the common case, where it's ready instantly */
8048 static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command,
8049 unsigned char xtraflags)
8051 - unsigned long docptr = doc->virtadr;
8052 + void __iomem *docptr = doc->virtadr;
8054 if (DoC_is_2000(doc))
8055 xtraflags |= CDSN_CTRL_FLASH_IO;
8058 /* Send the command */
8059 WriteDOC_(command, docptr, doc->ioreg);
8060 + if (DoC_is_Millennium(doc))
8061 + WriteDOC(command, docptr, WritePipeTerm);
8063 /* Lower the CLE line */
8064 WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
8065 @@ -161,10 +173,8 @@
8066 static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs,
8067 unsigned char xtraflags1, unsigned char xtraflags2)
8069 - unsigned long docptr;
8072 - docptr = doc->virtadr;
8073 + void __iomem *docptr = doc->virtadr;
8075 if (DoC_is_2000(doc))
8076 xtraflags1 |= CDSN_CTRL_FLASH_IO;
8081 + if (DoC_is_Millennium(doc))
8082 + WriteDOC(ofs & 0xff, docptr, WritePipeTerm);
8084 DoC_Delay(doc, 2); /* Needed for some slow flash chips. mf. */
8086 /* FIXME: The SlowIO's for millennium could be replaced by
8087 @@ -226,11 +239,9 @@
8090 int modulus = 0xffff;
8091 - unsigned long docptr;
8092 + void __iomem *docptr = doc->virtadr;
8095 - docptr = doc->virtadr;
8100 @@ -257,11 +268,9 @@
8101 /* Write a buffer to DoC, taking care of Millennium odditys */
8102 static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len)
8104 - unsigned long docptr;
8105 + void __iomem *docptr = doc->virtadr;
8108 - docptr = doc->virtadr;
8115 static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip)
8117 - unsigned long docptr = doc->virtadr;
8118 + void __iomem *docptr = doc->virtadr;
8120 /* Software requirement 11.4.4 before writing DeviceSelect */
8121 /* Deassert the CE line to eliminate glitches on the FCE# outputs */
8124 static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor)
8126 - unsigned long docptr = doc->virtadr;
8127 + void __iomem *docptr = doc->virtadr;
8129 /* Select the floor (bank) of chips required */
8130 WriteDOC(floor, docptr, FloorSelect);
8131 @@ -344,15 +353,25 @@
8133 /* Read the manufacturer and device id codes from the device */
8135 - /* CDSN Slow IO register see Software Requirement 11.4 item 5. */
8136 - dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
8137 - DoC_Delay(doc, 2);
8138 - mfr = ReadDOC_(doc->virtadr, doc->ioreg);
8140 - /* CDSN Slow IO register see Software Requirement 11.4 item 5. */
8141 - dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
8142 - DoC_Delay(doc, 2);
8143 - id = ReadDOC_(doc->virtadr, doc->ioreg);
8144 + if (DoC_is_Millennium(doc)) {
8145 + DoC_Delay(doc, 2);
8146 + dummy = ReadDOC(doc->virtadr, ReadPipeInit);
8147 + mfr = ReadDOC(doc->virtadr, LastDataRead);
8149 + DoC_Delay(doc, 2);
8150 + dummy = ReadDOC(doc->virtadr, ReadPipeInit);
8151 + id = ReadDOC(doc->virtadr, LastDataRead);
8153 + /* CDSN Slow IO register see Software Req 11.4 item 5. */
8154 + dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
8155 + DoC_Delay(doc, 2);
8156 + mfr = ReadDOC_(doc->virtadr, doc->ioreg);
8158 + /* CDSN Slow IO register see Software Req 11.4 item 5. */
8159 + dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
8160 + DoC_Delay(doc, 2);
8161 + id = ReadDOC_(doc->virtadr, doc->ioreg);
8164 /* No response - return failure */
8165 if (mfr == 0xff || mfr == 0)
8166 @@ -386,11 +405,10 @@
8171 - nand_flash_ids[i].chipshift;
8172 - doc->page256 = nand_flash_ids[i].page256;
8174 - nand_flash_ids[i].chipshift > 25 ? 3 : 2;
8176 + ffs((nand_flash_ids[i].chipsize << 20)) - 1;
8177 + doc->page256 = (nand_flash_ids[i].pagesize == 256) ? 1 : 0;
8178 + doc->pageadrlen = doc->chipshift > 25 ? 3 : 2;
8180 nand_flash_ids[i].erasesize;
8182 @@ -410,20 +428,16 @@
8184 /* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
8186 -static void DoC_ScanChips(struct DiskOnChip *this)
8187 +static void DoC_ScanChips(struct DiskOnChip *this, int maxchips)
8190 int numchips[MAX_FLOORS];
8191 - int maxchips = MAX_CHIPS;
8198 - if (DoC_is_Millennium(this))
8199 - maxchips = MAX_CHIPS_MIL;
8201 /* For each floor, find the number of valid chips it contains */
8202 for (floor = 0; floor < MAX_FLOORS; floor++) {
8206 struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
8207 struct DiskOnChip *old = NULL;
8210 /* We must avoid being called twice for the same device. */
8212 @@ -538,14 +553,28 @@
8215 switch (this->ChipID) {
8216 + case DOC_ChipID_Doc2kTSOP:
8217 + mtd->name = "DiskOnChip 2000 TSOP";
8218 + this->ioreg = DoC_Mil_CDSN_IO;
8219 + /* Pretend it's a Millennium */
8220 + this->ChipID = DOC_ChipID_DocMil;
8221 + maxchips = MAX_CHIPS;
8223 case DOC_ChipID_Doc2k:
8224 mtd->name = "DiskOnChip 2000";
8225 this->ioreg = DoC_2k_CDSN_IO;
8226 + maxchips = MAX_CHIPS;
8228 case DOC_ChipID_DocMil:
8229 mtd->name = "DiskOnChip Millennium";
8230 this->ioreg = DoC_Mil_CDSN_IO;
8231 + maxchips = MAX_CHIPS_MIL;
8234 + printk("Unknown ChipID 0x%02x\n", this->ChipID);
8236 + iounmap((void *) this->virtadr);
8240 printk(KERN_NOTICE "%s found at address 0x%lX\n", mtd->name,
8242 mtd->write = doc_write;
8243 mtd->read_ecc = doc_read_ecc;
8244 mtd->write_ecc = doc_write_ecc;
8245 + mtd->writev_ecc = doc_writev_ecc;
8246 mtd->read_oob = doc_read_oob;
8247 mtd->write_oob = doc_write_oob;
8250 init_MUTEX(&this->lock);
8252 /* Ident all the chips present. */
8253 - DoC_ScanChips(this);
8254 + DoC_ScanChips(this, maxchips);
8256 if (!this->totlen) {
8258 @@ -597,20 +627,19 @@
8259 size_t * retlen, u_char * buf)
8261 /* Just a special case of doc_read_ecc */
8262 - return doc_read_ecc(mtd, from, len, retlen, buf, NULL, 0);
8263 + return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
8266 static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
8267 - size_t * retlen, u_char * buf, u_char * eccbuf, int oobsel)
8268 + size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel)
8270 struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
8271 - unsigned long docptr;
8272 + void __iomem *docptr = this->virtadr;
8273 struct Nand *mychip;
8274 unsigned char syndrome[6];
8275 volatile char dummy;
8276 int i, len256 = 0, ret=0;
8278 - docptr = this->virtadr;
8279 + size_t left = len;
8281 /* Don't allow read past end of device */
8282 if (from >= this->totlen)
8283 @@ -618,122 +647,131 @@
8287 - /* Don't allow a single read to cross a 512-byte block boundary */
8288 - if (from + len > ((from | 0x1ff) + 1))
8289 - len = ((from | 0x1ff) + 1) - from;
8291 - /* The ECC will not be calculated correctly if less than 512 is read */
8292 - if (len != 0x200 && eccbuf)
8293 - printk(KERN_WARNING
8294 - "ECC needs a full sector read (adr: %lx size %lx)\n",
8295 - (long) from, (long) len);
8300 + /* Don't allow a single read to cross a 512-byte block boundary */
8301 + if (from + len > ((from | 0x1ff) + 1))
8302 + len = ((from | 0x1ff) + 1) - from;
8304 - /* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */
8305 + /* The ECC will not be calculated correctly if less than 512 is read */
8306 + if (len != 0x200 && eccbuf)
8307 + printk(KERN_WARNING
8308 + "ECC needs a full sector read (adr: %lx size %lx)\n",
8309 + (long) from, (long) len);
8311 + /* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */
8313 - /* Find the chip which is to be used and select it */
8314 - mychip = &this->chips[from >> (this->chipshift)];
8316 - if (this->curfloor != mychip->floor) {
8317 - DoC_SelectFloor(this, mychip->floor);
8318 - DoC_SelectChip(this, mychip->chip);
8319 - } else if (this->curchip != mychip->chip) {
8320 - DoC_SelectChip(this, mychip->chip);
8322 + /* Find the chip which is to be used and select it */
8323 + mychip = &this->chips[from >> (this->chipshift)];
8325 - this->curfloor = mychip->floor;
8326 - this->curchip = mychip->chip;
8327 + if (this->curfloor != mychip->floor) {
8328 + DoC_SelectFloor(this, mychip->floor);
8329 + DoC_SelectChip(this, mychip->chip);
8330 + } else if (this->curchip != mychip->chip) {
8331 + DoC_SelectChip(this, mychip->chip);
8336 - && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
8338 - DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
8339 - CDSN_CTRL_ECC_IO);
8342 - /* Prime the ECC engine */
8343 - WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8344 - WriteDOC(DOC_ECC_EN, docptr, ECCConf);
8346 - /* disable the ECC engine */
8347 - WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8348 - WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8350 + this->curfloor = mychip->floor;
8351 + this->curchip = mychip->chip;
8353 - /* treat crossing 256-byte sector for 2M x 8bits devices */
8354 - if (this->page256 && from + len > (from | 0xff) + 1) {
8355 - len256 = (from | 0xff) + 1 - from;
8356 - DoC_ReadBuf(this, buf, len256);
8359 + && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
8361 + DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
8362 + CDSN_CTRL_ECC_IO);
8364 - DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP);
8365 - DoC_Address(this, ADDR_COLUMN_PAGE, from + len256,
8366 - CDSN_CTRL_WP, CDSN_CTRL_ECC_IO);
8369 + /* Prime the ECC engine */
8370 + WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8371 + WriteDOC(DOC_ECC_EN, docptr, ECCConf);
8373 + /* disable the ECC engine */
8374 + WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8375 + WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8378 - DoC_ReadBuf(this, &buf[len256], len - len256);
8379 + /* treat crossing 256-byte sector for 2M x 8bits devices */
8380 + if (this->page256 && from + len > (from | 0xff) + 1) {
8381 + len256 = (from | 0xff) + 1 - from;
8382 + DoC_ReadBuf(this, buf, len256);
8384 + DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP);
8385 + DoC_Address(this, ADDR_COLUMN_PAGE, from + len256,
8386 + CDSN_CTRL_WP, CDSN_CTRL_ECC_IO);
8389 - /* Let the caller know we completed it */
8391 + DoC_ReadBuf(this, &buf[len256], len - len256);
8394 - /* Read the ECC data through the DiskOnChip ECC logic */
8395 - /* Note: this will work even with 2M x 8bit devices as */
8396 - /* they have 8 bytes of OOB per 256 page. mf. */
8397 - DoC_ReadBuf(this, eccbuf, 6);
8398 + /* Let the caller know we completed it */
8401 - /* Flush the pipeline */
8402 - if (DoC_is_Millennium(this)) {
8403 - dummy = ReadDOC(docptr, ECCConf);
8404 - dummy = ReadDOC(docptr, ECCConf);
8405 - i = ReadDOC(docptr, ECCConf);
8407 - dummy = ReadDOC(docptr, 2k_ECCStatus);
8408 - dummy = ReadDOC(docptr, 2k_ECCStatus);
8409 - i = ReadDOC(docptr, 2k_ECCStatus);
8412 + /* Read the ECC data through the DiskOnChip ECC logic */
8413 + /* Note: this will work even with 2M x 8bit devices as */
8414 + /* they have 8 bytes of OOB per 256 page. mf. */
8415 + DoC_ReadBuf(this, eccbuf, 6);
8417 + /* Flush the pipeline */
8418 + if (DoC_is_Millennium(this)) {
8419 + dummy = ReadDOC(docptr, ECCConf);
8420 + dummy = ReadDOC(docptr, ECCConf);
8421 + i = ReadDOC(docptr, ECCConf);
8423 + dummy = ReadDOC(docptr, 2k_ECCStatus);
8424 + dummy = ReadDOC(docptr, 2k_ECCStatus);
8425 + i = ReadDOC(docptr, 2k_ECCStatus);
8428 - /* Check the ECC Status */
8431 - /* There was an ECC error */
8432 + /* Check the ECC Status */
8435 + /* There was an ECC error */
8437 - printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
8438 + printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
8440 - /* Read the ECC syndrom through the DiskOnChip ECC logic.
8441 - These syndrome will be all ZERO when there is no error */
8442 - for (i = 0; i < 6; i++) {
8444 - ReadDOC(docptr, ECCSyndrome0 + i);
8446 - nb_errors = doc_decode_ecc(buf, syndrome);
8447 + /* Read the ECC syndrom through the DiskOnChip ECC logic.
8448 + These syndrome will be all ZERO when there is no error */
8449 + for (i = 0; i < 6; i++) {
8451 + ReadDOC(docptr, ECCSyndrome0 + i);
8453 + nb_errors = doc_decode_ecc(buf, syndrome);
8456 - printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
8457 + printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
8459 - if (nb_errors < 0) {
8460 - /* We return error, but have actually done the read. Not that
8461 - this can be told to user-space, via sys_read(), but at least
8462 - MTD-aware stuff can know about it by checking *retlen */
8466 + if (nb_errors < 0) {
8467 + /* We return error, but have actually done the read. Not that
8468 + this can be told to user-space, via sys_read(), but at least
8469 + MTD-aware stuff can know about it by checking *retlen */
8475 - printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
8476 - (long)from, eccbuf[0], eccbuf[1], eccbuf[2],
8477 - eccbuf[3], eccbuf[4], eccbuf[5]);
8478 + printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
8479 + (long)from, eccbuf[0], eccbuf[1], eccbuf[2],
8480 + eccbuf[3], eccbuf[4], eccbuf[5]);
8483 - /* disable the ECC engine */
8484 - WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
8486 + /* disable the ECC engine */
8487 + WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
8490 - /* according to 11.4.1, we need to wait for the busy line
8491 - * drop if we read to the end of the page. */
8492 - if(0 == ((from + *retlen) & 0x1ff))
8494 - DoC_WaitReady(this);
8495 + /* according to 11.4.1, we need to wait for the busy line
8496 + * drop if we read to the end of the page. */
8497 + if(0 == ((from + len) & 0x1ff))
8499 + DoC_WaitReady(this);
8508 @@ -745,21 +783,21 @@
8509 size_t * retlen, const u_char * buf)
8512 - return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, 0);
8513 + return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
8516 static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
8517 size_t * retlen, const u_char * buf,
8518 - u_char * eccbuf, int oobsel)
8519 + u_char * eccbuf, struct nand_oobinfo *oobsel)
8521 struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
8522 int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */
8523 - unsigned long docptr;
8524 + void __iomem *docptr = this->virtadr;
8525 volatile char dummy;
8527 struct Nand *mychip;
8529 - docptr = this->virtadr;
8530 + size_t left = len;
8533 /* Don't allow write past end of device */
8534 if (to >= this->totlen)
8535 @@ -767,65 +805,133 @@
8539 - /* Don't allow a single write to cross a 512-byte block boundary */
8540 - if (to + len > ((to | 0x1ff) + 1))
8541 - len = ((to | 0x1ff) + 1) - to;
8543 - /* The ECC will not be calculated correctly if less than 512 is written */
8544 - if (len != 0x200 && eccbuf)
8545 - printk(KERN_WARNING
8546 - "ECC needs a full sector write (adr: %lx size %lx)\n",
8547 - (long) to, (long) len);
8552 + /* Don't allow a single write to cross a 512-byte block boundary */
8553 + if (to + len > ((to | 0x1ff) + 1))
8554 + len = ((to | 0x1ff) + 1) - to;
8556 + /* The ECC will not be calculated correctly if less than 512 is written */
8558 + if (len != 0x200 && eccbuf)
8559 + printk(KERN_WARNING
8560 + "ECC needs a full sector write (adr: %lx size %lx)\n",
8561 + (long) to, (long) len);
8564 - /* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */
8565 + /* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */
8567 - /* Find the chip which is to be used and select it */
8568 - mychip = &this->chips[to >> (this->chipshift)];
8569 + /* Find the chip which is to be used and select it */
8570 + mychip = &this->chips[to >> (this->chipshift)];
8572 - if (this->curfloor != mychip->floor) {
8573 - DoC_SelectFloor(this, mychip->floor);
8574 - DoC_SelectChip(this, mychip->chip);
8575 - } else if (this->curchip != mychip->chip) {
8576 - DoC_SelectChip(this, mychip->chip);
8578 + if (this->curfloor != mychip->floor) {
8579 + DoC_SelectFloor(this, mychip->floor);
8580 + DoC_SelectChip(this, mychip->chip);
8581 + } else if (this->curchip != mychip->chip) {
8582 + DoC_SelectChip(this, mychip->chip);
8585 - this->curfloor = mychip->floor;
8586 - this->curchip = mychip->chip;
8587 + this->curfloor = mychip->floor;
8588 + this->curchip = mychip->chip;
8590 - /* Set device to main plane of flash */
8591 - DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
8594 - && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
8596 + /* Set device to main plane of flash */
8597 + DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
8600 + && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
8603 - DoC_Command(this, NAND_CMD_SEQIN, 0);
8604 - DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
8605 + DoC_Command(this, NAND_CMD_SEQIN, 0);
8606 + DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
8609 - /* Prime the ECC engine */
8610 - WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8611 - WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
8613 - /* disable the ECC engine */
8614 - WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8615 - WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8618 + /* Prime the ECC engine */
8619 + WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8620 + WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
8622 + /* disable the ECC engine */
8623 + WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8624 + WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8627 - /* treat crossing 256-byte sector for 2M x 8bits devices */
8628 - if (this->page256 && to + len > (to | 0xff) + 1) {
8629 - len256 = (to | 0xff) + 1 - to;
8630 - DoC_WriteBuf(this, buf, len256);
8631 + /* treat crossing 256-byte sector for 2M x 8bits devices */
8632 + if (this->page256 && to + len > (to | 0xff) + 1) {
8633 + len256 = (to | 0xff) + 1 - to;
8634 + DoC_WriteBuf(this, buf, len256);
8636 + DoC_Command(this, NAND_CMD_PAGEPROG, 0);
8638 + DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
8639 + /* There's an implicit DoC_WaitReady() in DoC_Command */
8641 + dummy = ReadDOC(docptr, CDSNSlowIO);
8642 + DoC_Delay(this, 2);
8644 + if (ReadDOC_(docptr, this->ioreg) & 1) {
8645 + printk(KERN_ERR "Error programming flash\n");
8646 + /* Error in programming */
8652 + DoC_Command(this, NAND_CMD_SEQIN, 0);
8653 + DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0,
8654 + CDSN_CTRL_ECC_IO);
8657 + DoC_WriteBuf(this, &buf[len256], len - len256);
8660 + WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
8663 + if (DoC_is_Millennium(this)) {
8664 + WriteDOC(0, docptr, NOP);
8665 + WriteDOC(0, docptr, NOP);
8666 + WriteDOC(0, docptr, NOP);
8668 + WriteDOC_(0, docptr, this->ioreg);
8669 + WriteDOC_(0, docptr, this->ioreg);
8670 + WriteDOC_(0, docptr, this->ioreg);
8673 + WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr,
8676 + /* Read the ECC data through the DiskOnChip ECC logic */
8677 + for (di = 0; di < 6; di++) {
8678 + eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
8681 + /* Reset the ECC engine */
8682 + WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8684 +#ifdef PSYCHO_DEBUG
8686 + ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
8687 + (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
8688 + eccbuf[4], eccbuf[5]);
8692 DoC_Command(this, NAND_CMD_PAGEPROG, 0);
8694 DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
8695 /* There's an implicit DoC_WaitReady() in DoC_Command */
8697 - dummy = ReadDOC(docptr, CDSNSlowIO);
8698 - DoC_Delay(this, 2);
8699 + if (DoC_is_Millennium(this)) {
8700 + ReadDOC(docptr, ReadPipeInit);
8701 + status = ReadDOC(docptr, LastDataRead);
8703 + dummy = ReadDOC(docptr, CDSNSlowIO);
8704 + DoC_Delay(this, 2);
8705 + status = ReadDOC_(docptr, this->ioreg);
8708 - if (ReadDOC_(docptr, this->ioreg) & 1) {
8710 printk(KERN_ERR "Error programming flash\n");
8711 /* Error in programming */
8713 @@ -833,94 +939,106 @@
8717 - DoC_Command(this, NAND_CMD_SEQIN, 0);
8718 - DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0,
8719 - CDSN_CTRL_ECC_IO);
8720 + /* Let the caller know we completed it */
8724 + unsigned char x[8];
8728 + /* Write the ECC data to flash */
8729 + for (di=0; di<6; di++)
8730 + x[di] = eccbuf[di];
8735 + ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x);
8747 - DoC_WriteBuf(this, &buf[len256], len - len256);
8753 - WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
8755 +static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
8756 + unsigned long count, loff_t to, size_t *retlen,
8757 + u_char *eccbuf, struct nand_oobinfo *oobsel)
8759 + static char static_buf[512];
8760 + static DECLARE_MUTEX(writev_buf_sem);
8762 - if (DoC_is_Millennium(this)) {
8763 - WriteDOC(0, docptr, NOP);
8764 - WriteDOC(0, docptr, NOP);
8765 - WriteDOC(0, docptr, NOP);
8767 - WriteDOC_(0, docptr, this->ioreg);
8768 - WriteDOC_(0, docptr, this->ioreg);
8769 - WriteDOC_(0, docptr, this->ioreg);
8771 + size_t totretlen = 0;
8772 + size_t thisvecofs = 0;
8775 - /* Read the ECC data through the DiskOnChip ECC logic */
8776 - for (di = 0; di < 6; di++) {
8777 - eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
8779 + down(&writev_buf_sem);
8781 - /* Reset the ECC engine */
8782 - WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8784 + size_t thislen, thisretlen;
8785 + unsigned char *buf;
8787 -#ifdef PSYCHO_DEBUG
8789 - ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
8790 - (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
8791 - eccbuf[4], eccbuf[5]);
8794 + buf = vecs->iov_base + thisvecofs;
8795 + thislen = vecs->iov_len - thisvecofs;
8797 - DoC_Command(this, NAND_CMD_PAGEPROG, 0);
8799 - DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
8800 - /* There's an implicit DoC_WaitReady() in DoC_Command */
8801 + if (thislen >= 512) {
8802 + thislen = thislen & ~(512-1);
8803 + thisvecofs += thislen;
8805 + /* Not enough to fill a page. Copy into buf */
8806 + memcpy(static_buf, buf, thislen);
8807 + buf = &static_buf[thislen];
8809 + while(count && thislen < 512) {
8812 + thisvecofs = min((512-thislen), vecs->iov_len);
8813 + memcpy(buf, vecs->iov_base, thisvecofs);
8814 + thislen += thisvecofs;
8815 + buf += thisvecofs;
8819 + if (count && thisvecofs == vecs->iov_len) {
8824 + ret = doc_write_ecc(mtd, to, thislen, &thisretlen, buf, eccbuf, oobsel);
8826 - dummy = ReadDOC(docptr, CDSNSlowIO);
8827 - DoC_Delay(this, 2);
8828 + totretlen += thisretlen;
8830 - if (ReadDOC_(docptr, this->ioreg) & 1) {
8831 - printk(KERN_ERR "Error programming flash\n");
8832 - /* Error in programming */
8837 + if (ret || thisretlen != thislen)
8840 - /* Let the caller know we completed it */
8844 - unsigned char x[8];
8848 - /* Write the ECC data to flash */
8849 - for (di=0; di<6; di++)
8850 - x[di] = eccbuf[di];
8855 - ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x);
8864 + up(&writev_buf_sem);
8865 + *retlen = totretlen;
8870 static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
8871 size_t * retlen, u_char * buf)
8873 struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
8874 int len256 = 0, ret;
8875 - unsigned long docptr;
8876 struct Nand *mychip;
8880 - docptr = this->virtadr;
8882 mychip = &this->chips[ofs >> this->chipshift];
8884 if (this->curfloor != mychip->floor) {
8885 @@ -975,9 +1093,10 @@
8887 struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
8889 - unsigned long docptr = this->virtadr;
8890 + void __iomem *docptr = this->virtadr;
8891 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
8895 // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len,
8896 // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]);
8897 @@ -1026,10 +1145,16 @@
8898 DoC_Command(this, NAND_CMD_STATUS, 0);
8899 /* DoC_WaitReady() is implicit in DoC_Command */
8901 - dummy = ReadDOC(docptr, CDSNSlowIO);
8902 - DoC_Delay(this, 2);
8903 + if (DoC_is_Millennium(this)) {
8904 + ReadDOC(docptr, ReadPipeInit);
8905 + status = ReadDOC(docptr, LastDataRead);
8907 + dummy = ReadDOC(docptr, CDSNSlowIO);
8908 + DoC_Delay(this, 2);
8909 + status = ReadDOC_(docptr, this->ioreg);
8912 - if (ReadDOC_(docptr, this->ioreg) & 1) {
8914 printk(KERN_ERR "Error programming oob data\n");
8915 /* There was an error */
8917 @@ -1045,10 +1170,16 @@
8918 DoC_Command(this, NAND_CMD_STATUS, 0);
8919 /* DoC_WaitReady() is implicit in DoC_Command */
8921 - dummy = ReadDOC(docptr, CDSNSlowIO);
8922 - DoC_Delay(this, 2);
8923 + if (DoC_is_Millennium(this)) {
8924 + ReadDOC(docptr, ReadPipeInit);
8925 + status = ReadDOC(docptr, LastDataRead);
8927 + dummy = ReadDOC(docptr, CDSNSlowIO);
8928 + DoC_Delay(this, 2);
8929 + status = ReadDOC_(docptr, this->ioreg);
8932 - if (ReadDOC_(docptr, this->ioreg) & 1) {
8934 printk(KERN_ERR "Error programming oob data\n");
8935 /* There was an error */
8937 @@ -1079,8 +1210,9 @@
8938 __u32 ofs = instr->addr;
8939 __u32 len = instr->len;
8941 - unsigned long docptr;
8942 + void __iomem *docptr = this->virtadr;
8943 struct Nand *mychip;
8948 @@ -1091,8 +1223,6 @@
8950 instr->state = MTD_ERASING;
8952 - docptr = this->virtadr;
8954 /* FIXME: Do this in the background. Use timers or schedule_task() */
8956 mychip = &this->chips[ofs >> this->chipshift];
8957 @@ -1112,10 +1242,16 @@
8959 DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
8961 - dummy = ReadDOC(docptr, CDSNSlowIO);
8962 - DoC_Delay(this, 2);
8964 - if (ReadDOC_(docptr, this->ioreg) & 1) {
8965 + if (DoC_is_Millennium(this)) {
8966 + ReadDOC(docptr, ReadPipeInit);
8967 + status = ReadDOC(docptr, LastDataRead);
8969 + dummy = ReadDOC(docptr, CDSNSlowIO);
8970 + DoC_Delay(this, 2);
8971 + status = ReadDOC_(docptr, this->ioreg);
8975 printk(KERN_ERR "Error erasing at 0x%x\n", ofs);
8976 /* There was an error */
8977 instr->state = MTD_ERASE_FAILED;
8978 @@ -1127,8 +1263,7 @@
8979 instr->state = MTD_ERASE_DONE;
8982 - if (instr->callback)
8983 - instr->callback(instr);
8984 + mtd_erase_callback(instr);
8988 Index: linux-2.6.5/drivers/mtd/devices/doc2001.c
8989 ===================================================================
8990 --- linux-2.6.5.orig/drivers/mtd/devices/doc2001.c 2004-04-03 22:36:54.000000000 -0500
8991 +++ linux-2.6.5/drivers/mtd/devices/doc2001.c 2005-02-01 17:11:17.000000000 -0500
8993 * (c) 1999 Machine Vision Holdings, Inc.
8994 * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
8996 - * $Id: doc2001.c,v 1.41 2003/06/11 09:45:19 dwmw2 Exp $
8997 + * $Id: doc2001.c,v 1.45 2004/09/16 23:51:57 gleixner Exp $
9000 #include <linux/kernel.h>
9002 #include <linux/sched.h>
9003 #include <linux/init.h>
9004 #include <linux/types.h>
9005 +#include <linux/bitops.h>
9007 #include <linux/mtd/mtd.h>
9008 #include <linux/mtd/nand.h>
9010 static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
9011 size_t *retlen, const u_char *buf);
9012 static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
9013 - size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel);
9014 + size_t *retlen, u_char *buf, u_char *eccbuf,
9015 + struct nand_oobinfo *oobsel);
9016 static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
9017 - size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel);
9018 + size_t *retlen, const u_char *buf, u_char *eccbuf,
9019 + struct nand_oobinfo *oobsel);
9020 static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
9021 size_t *retlen, u_char *buf);
9022 static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
9024 static struct mtd_info *docmillist = NULL;
9026 /* Perform the required delay cycles by reading from the NOP register */
9027 -static void DoC_Delay(unsigned long docptr, unsigned short cycles)
9028 +static void DoC_Delay(void __iomem * docptr, unsigned short cycles)
9030 volatile char dummy;
9035 /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
9036 -static int _DoC_WaitReady(unsigned long docptr)
9037 +static int _DoC_WaitReady(void __iomem * docptr)
9039 unsigned short c = 0xffff;
9045 -static inline int DoC_WaitReady(unsigned long docptr)
9046 +static inline int DoC_WaitReady(void __iomem * docptr)
9048 /* This is inline, to optimise the common case, where it's ready instantly */
9051 with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
9052 required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
9054 -static inline void DoC_Command(unsigned long docptr, unsigned char command,
9055 +static inline void DoC_Command(void __iomem * docptr, unsigned char command,
9056 unsigned char xtraflags)
9058 /* Assert the CLE (Command Latch Enable) line to the flash chip */
9060 with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
9061 required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
9063 -static inline void DoC_Address(unsigned long docptr, int numbytes, unsigned long ofs,
9064 +static inline void DoC_Address(void __iomem * docptr, int numbytes, unsigned long ofs,
9065 unsigned char xtraflags1, unsigned char xtraflags2)
9067 /* Assert the ALE (Address Latch Enable) line to the flash chip */
9071 /* DoC_SelectChip: Select a given flash chip within the current floor */
9072 -static int DoC_SelectChip(unsigned long docptr, int chip)
9073 +static int DoC_SelectChip(void __iomem * docptr, int chip)
9075 /* Select the individual flash chip requested */
9076 WriteDOC(chip, docptr, CDSNDeviceSelect);
9080 /* DoC_SelectFloor: Select a given floor (bank of flash chips) */
9081 -static int DoC_SelectFloor(unsigned long docptr, int floor)
9082 +static int DoC_SelectFloor(void __iomem * docptr, int floor)
9084 /* Select the floor (bank) of chips required */
9085 WriteDOC(floor, docptr, FloorSelect);
9087 mfr, id, nand_manuf_ids[j].name, nand_flash_ids[i].name);
9090 - doc->chipshift = nand_flash_ids[i].chipshift;
9091 + doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1;
9095 @@ -403,17 +406,18 @@
9096 size_t *retlen, u_char *buf)
9098 /* Just a special case of doc_read_ecc */
9099 - return doc_read_ecc(mtd, from, len, retlen, buf, NULL, 0);
9100 + return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
9103 static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
9104 - size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel)
9105 + size_t *retlen, u_char *buf, u_char *eccbuf,
9106 + struct nand_oobinfo *oobsel)
9109 volatile char dummy;
9110 unsigned char syndrome[6];
9111 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9112 - unsigned long docptr = this->virtadr;
9113 + void __iomem *docptr = this->virtadr;
9114 struct Nand *mychip = &this->chips[from >> (this->chipshift)];
9116 /* Don't allow read past end of device */
9117 @@ -529,16 +533,17 @@
9118 size_t *retlen, const u_char *buf)
9121 - return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, 0);
9122 + return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
9125 static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
9126 - size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel)
9127 + size_t *retlen, const u_char *buf, u_char *eccbuf,
9128 + struct nand_oobinfo *oobsel)
9131 volatile char dummy;
9132 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9133 - unsigned long docptr = this->virtadr;
9134 + void __iomem *docptr = this->virtadr;
9135 struct Nand *mychip = &this->chips[to >> (this->chipshift)];
9137 /* Don't allow write past end of device */
9140 volatile char dummy;
9141 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9142 - unsigned long docptr = this->virtadr;
9143 + void __iomem *docptr = this->virtadr;
9144 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
9146 /* Find the chip which is to be used and select it */
9148 volatile char dummy;
9150 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9151 - unsigned long docptr = this->virtadr;
9152 + void __iomem *docptr = this->virtadr;
9153 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
9155 /* Find the chip which is to be used and select it */
9157 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9158 __u32 ofs = instr->addr;
9159 __u32 len = instr->len;
9160 - unsigned long docptr = this->virtadr;
9161 + void __iomem *docptr = this->virtadr;
9162 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
9164 if (len != mtd->erasesize)
9166 instr->state = MTD_ERASE_DONE;
9167 dummy = ReadDOC(docptr, LastDataRead);
9169 - if (instr->callback)
9170 - instr->callback(instr);
9171 + mtd_erase_callback(instr);
9175 Index: linux-2.6.5/drivers/mtd/devices/doc2001plus.c
9176 ===================================================================
9177 --- linux-2.6.5.orig/drivers/mtd/devices/doc2001plus.c 2004-04-03 22:36:12.000000000 -0500
9178 +++ linux-2.6.5/drivers/mtd/devices/doc2001plus.c 2005-02-01 17:11:17.000000000 -0500
9180 * (c) 1999 Machine Vision Holdings, Inc.
9181 * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
9183 - * $Id: doc2001plus.c,v 1.5 2003/06/11 09:45:19 dwmw2 Exp $
9184 + * $Id: doc2001plus.c,v 1.10 2004/09/16 23:51:57 gleixner Exp $
9186 + * Released under GPL
9189 #include <linux/kernel.h>
9191 #include <linux/sched.h>
9192 #include <linux/init.h>
9193 #include <linux/types.h>
9194 +#include <linux/bitops.h>
9196 #include <linux/mtd/mtd.h>
9197 #include <linux/mtd/nand.h>
9201 /* Perform the required delay cycles by writing to the NOP register */
9202 -static void DoC_Delay(unsigned long docptr, int cycles)
9203 +static void DoC_Delay(void __iomem * docptr, int cycles)
9208 #define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)
9210 /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
9211 -static int _DoC_WaitReady(unsigned long docptr)
9212 +static int _DoC_WaitReady(void __iomem * docptr)
9214 unsigned int c = 0xffff;
9220 -static inline int DoC_WaitReady(unsigned long docptr)
9221 +static inline int DoC_WaitReady(void __iomem * docptr)
9223 /* This is inline, to optimise the common case, where it's ready instantly */
9226 * can detect. M-systems suggest always check this on any block level
9227 * operation and setting to normal mode if in reset mode.
9229 -static inline void DoC_CheckASIC(unsigned long docptr)
9230 +static inline void DoC_CheckASIC(void __iomem * docptr)
9232 /* Make sure the DoC is in normal mode */
9233 if ((ReadDOC(docptr, Mplus_DOCControl) & DOC_MODE_NORMAL) == 0) {
9235 /* DoC_Command: Send a flash command to the flash chip through the Flash
9236 * command register. Need 2 Write Pipeline Terminates to complete send.
9238 -static inline void DoC_Command(unsigned long docptr, unsigned char command,
9239 +static inline void DoC_Command(void __iomem * docptr, unsigned char command,
9240 unsigned char xtraflags)
9242 WriteDOC(command, docptr, Mplus_FlashCmd);
9244 unsigned long ofs, unsigned char xtraflags1,
9245 unsigned char xtraflags2)
9247 - unsigned long docptr = doc->virtadr;
9248 + void __iomem * docptr = doc->virtadr;
9250 /* Allow for possible Mill Plus internal flash interleaving */
9251 ofs >>= doc->interleave;
9252 @@ -160,14 +163,14 @@
9255 /* DoC_SelectChip: Select a given flash chip within the current floor */
9256 -static int DoC_SelectChip(unsigned long docptr, int chip)
9257 +static int DoC_SelectChip(void __iomem * docptr, int chip)
9259 /* No choice for flash chip on Millennium Plus */
9263 /* DoC_SelectFloor: Select a given floor (bank of flash chips) */
9264 -static int DoC_SelectFloor(unsigned long docptr, int floor)
9265 +static int DoC_SelectFloor(void __iomem * docptr, int floor)
9267 WriteDOC((floor & 0x3), docptr, Mplus_DeviceSelect);
9269 @@ -183,24 +186,35 @@
9270 * | Data 0 | ECC 0 |Flags0 |Flags1 | Data 1 |ECC 1 | OOB 1 + 2 |
9271 * +-----------+-------+-------+-------+--------------+---------+-----------+
9273 +/* FIXME: This lives in INFTL not here. Other users of flash devices
9274 + may not want it */
9275 static unsigned int DoC_GetDataOffset(struct mtd_info *mtd, loff_t *from)
9277 - unsigned int ofs = *from & 0x3ff;
9279 + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9282 - cmd = NAND_CMD_READ0;
9284 - } else if (ofs < 1014) {
9285 - cmd = NAND_CMD_READ1;
9286 - ofs = (ofs & 0x1ff) + 10;
9287 + if (this->interleave) {
9288 + unsigned int ofs = *from & 0x3ff;
9292 + cmd = NAND_CMD_READ0;
9294 + } else if (ofs < 1014) {
9295 + cmd = NAND_CMD_READ1;
9296 + ofs = (ofs & 0x1ff) + 10;
9298 + cmd = NAND_CMD_READOOB;
9302 + *from = (*from & ~0x3ff) | ofs;
9305 - cmd = NAND_CMD_READOOB;
9307 + /* No interleave */
9308 + if ((*from) & 0x100)
9309 + return NAND_CMD_READ1;
9310 + return NAND_CMD_READ0;
9313 - *from = (*from & ~0x3ff) | ofs;
9317 static unsigned int DoC_GetECCOffset(struct mtd_info *mtd, loff_t *from)
9322 -static inline void MemReadDOC(unsigned long docptr, unsigned char *buf, int len)
9323 +static inline void MemReadDOC(void __iomem * docptr, unsigned char *buf, int len)
9331 -static inline void MemWriteDOC(unsigned long docptr, unsigned char *buf, int len)
9332 +static inline void MemWriteDOC(void __iomem * docptr, unsigned char *buf, int len)
9339 volatile char dummy;
9340 - unsigned long docptr = doc->virtadr;
9341 + void __iomem * docptr = doc->virtadr;
9343 /* Page in the required floor/chip */
9344 DoC_SelectFloor(docptr, floor);
9345 @@ -294,10 +308,12 @@
9346 dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
9348 mfr = ReadDOC(docptr, Mil_CDSN_IO);
9349 - dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */
9350 + if (doc->interleave)
9351 + dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */
9353 id = ReadDOC(docptr, Mil_CDSN_IO);
9354 - dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */
9355 + if (doc->interleave)
9356 + dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */
9358 dummy = ReadDOC(docptr, Mplus_LastDataRead);
9359 dummy = ReadDOC(docptr, Mplus_LastDataRead);
9360 @@ -321,10 +337,7 @@
9361 nand_manuf_ids[j].name, nand_flash_ids[i].name);
9364 - doc->interleave = 0;
9365 - if (doc->ChipID == DOC_ChipID_DocMilPlus32)
9366 - doc->interleave = 1;
9367 - doc->chipshift = nand_flash_ids[i].chipshift;
9368 + doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1;
9369 doc->erasesize = nand_flash_ids[i].erasesize << doc->interleave;
9372 @@ -346,6 +359,21 @@
9376 + /* Work out the intended interleave setting */
9377 + this->interleave = 0;
9378 + if (this->ChipID == DOC_ChipID_DocMilPlus32)
9379 + this->interleave = 1;
9381 + /* Check the ASIC agrees */
9382 + if ( (this->interleave << 2) !=
9383 + (ReadDOC(this->virtadr, Mplus_Configuration) & 4)) {
9384 + u_char conf = ReadDOC(this->virtadr, Mplus_Configuration);
9385 + printk(KERN_NOTICE "Setting DiskOnChip Millennium Plus interleave to %s\n",
9386 + this->interleave?"on (16-bit)":"off (8-bit)");
9388 + WriteDOC(conf, this->virtadr, Mplus_Configuration);
9391 /* For each floor, find the number of valid chips it contains */
9392 for (floor = 0,ret = 1; floor < MAX_FLOORS_MPLUS; floor++) {
9393 numchips[floor] = 0;
9397 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9398 - unsigned long docptr = this->virtadr;
9399 + void __iomem * docptr = this->virtadr;
9400 struct Nand *mychip = &this->chips[from >> (this->chipshift)];
9401 unsigned char *bp, buf[1056];
9405 unsigned char syndrome[6];
9406 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9407 - unsigned long docptr = this->virtadr;
9408 + void __iomem * docptr = this->virtadr;
9409 struct Nand *mychip = &this->chips[from >> (this->chipshift)];
9411 /* Don't allow read past end of device */
9414 volatile char dummy;
9415 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9416 - unsigned long docptr = this->virtadr;
9417 + void __iomem * docptr = this->virtadr;
9418 struct Nand *mychip = &this->chips[to >> (this->chipshift)];
9420 /* Don't allow write past end of device */
9424 /* Determine position of OOB flags, before or after data */
9425 - before = to & 0x200;
9426 + before = (this->interleave && (to & 0x200));
9428 DoC_CheckASIC(docptr);
9433 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9434 - unsigned long docptr = this->virtadr;
9435 + void __iomem * docptr = this->virtadr;
9436 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
9437 size_t i, size, got, want;
9439 @@ -886,7 +914,10 @@
9440 /* Figure out which region we are accessing... */
9444 + if (!this->interleave) {
9445 + DoC_Command(docptr, NAND_CMD_READOOB, 0);
9447 + } else if (base < 6) {
9448 DoC_Command(docptr, DoC_GetECCOffset(mtd, &fofs), 0);
9450 } else if (base < 8) {
9452 volatile char dummy;
9454 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9455 - unsigned long docptr = this->virtadr;
9456 + void __iomem * docptr = this->virtadr;
9457 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
9458 size_t i, size, got, want;
9460 @@ -963,7 +994,10 @@
9461 /* Figure out which region we are accessing... */
9465 + if (!this->interleave) {
9466 + WriteDOC(NAND_CMD_READOOB, docptr, Mplus_FlashCmd);
9468 + } else if (base < 6) {
9469 WriteDOC(DoC_GetECCOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
9471 } else if (base < 8) {
9472 @@ -1027,7 +1061,7 @@
9473 struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9474 __u32 ofs = instr->addr;
9475 __u32 len = instr->len;
9476 - unsigned long docptr = this->virtadr;
9477 + void __iomem * docptr = this->virtadr;
9478 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
9480 DoC_CheckASIC(docptr);
9481 @@ -1077,8 +1111,7 @@
9482 /* Disable flash internally */
9483 WriteDOC(0, docptr, Mplus_FlashSelect);
9485 - if (instr->callback)
9486 - instr->callback(instr);
9487 + mtd_erase_callback(instr);
9491 Index: linux-2.6.5/drivers/mtd/devices/docprobe.c
9492 ===================================================================
9493 --- linux-2.6.5.orig/drivers/mtd/devices/docprobe.c 2004-04-03 22:37:37.000000000 -0500
9494 +++ linux-2.6.5/drivers/mtd/devices/docprobe.c 2005-02-01 17:11:17.000000000 -0500
9496 /* (C) 1999 Machine Vision Holdings, Inc. */
9497 /* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> */
9499 -/* $Id: docprobe.c,v 1.36 2003/05/23 11:29:34 dwmw2 Exp $ */
9500 +/* $Id: docprobe.c,v 1.42 2004/09/16 23:51:57 gleixner Exp $ */
9505 window, DOCControl);
9506 #endif /* !DOC_PASSIVE_PROBE */
9508 + /* We need to read the ChipID register four times. For some
9509 + newer DiskOnChip 2000 units, the first three reads will
9510 + return the DiskOnChip Millennium ident. Don't ask. */
9511 ChipID = ReadDOC(window, ChipID);
9514 @@ -148,6 +151,12 @@
9517 case DOC_ChipID_DocMil:
9518 + /* Check for the new 2000 with Millennium ASIC */
9519 + ReadDOC(window, ChipID);
9520 + ReadDOC(window, ChipID);
9521 + if (ReadDOC(window, ChipID) != DOC_ChipID_DocMil)
9522 + ChipID = DOC_ChipID_Doc2kTSOP;
9524 /* Check the TOGGLE bit in the ECC register */
9525 tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
9526 tmpb = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
9528 tmpc = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
9529 if (tmp != tmpb && tmp == tmpc)
9539 -#ifndef CONFIG_MTD_DOCPROBE_55AA
9540 - printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
9541 +#ifdef CONFIG_MTD_DOCPROBE_55AA
9542 + printk(KERN_DEBUG "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
9545 #ifndef DOC_PASSIVE_PROBE
9546 @@ -241,6 +249,12 @@
9549 if ((ChipID = doccheck(docptr, physadr))) {
9550 + if (ChipID == DOC_ChipID_Doc2kTSOP) {
9551 + /* Remove this at your own peril. The hardware driver works but nothing prevents you from erasing bad blocks */
9552 + printk(KERN_NOTICE "Refusing to drive DiskOnChip 2000 TSOP until Bad Block Table is correctly supported by INFTL\n");
9553 + iounmap((void *)docptr);
9557 mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL);
9559 @@ -256,12 +270,18 @@
9560 memset((char *)this, 0, sizeof(struct DiskOnChip));
9563 - this->virtadr = docptr;
9564 + this->virtadr = (void __iomem *)docptr;
9565 this->physadr = physadr;
9566 this->ChipID = ChipID;
9567 sprintf(namebuf, "with ChipID %2.2X", ChipID);
9570 + case DOC_ChipID_Doc2kTSOP:
9572 + im_funcname = "DoC2k_init";
9573 + im_modname = "doc2000";
9576 case DOC_ChipID_Doc2k:
9578 im_funcname = "DoC2k_init";
9579 Index: linux-2.6.5/drivers/mtd/devices/lart.c
9580 ===================================================================
9581 --- linux-2.6.5.orig/drivers/mtd/devices/lart.c 2004-04-03 22:36:57.000000000 -0500
9582 +++ linux-2.6.5/drivers/mtd/devices/lart.c 2005-02-01 17:11:17.000000000 -0500
9585 * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART.
9587 - * $Id: lart.c,v 1.5 2003/05/20 21:03:07 dwmw2 Exp $
9588 + * $Id: lart.c,v 1.7 2004/08/09 13:19:44 dwmw2 Exp $
9590 * Author: Abraham vd Merwe <abraham@2d3d.co.za>
9595 instr->state = MTD_ERASE_DONE;
9596 - if (instr->callback) instr->callback (instr);
9597 + mtd_erase_callback(instr);
9601 Index: linux-2.6.5/drivers/mtd/devices/ms02-nv.c
9602 ===================================================================
9603 --- linux-2.6.5.orig/drivers/mtd/devices/ms02-nv.c 2004-04-03 22:36:15.000000000 -0500
9604 +++ linux-2.6.5/drivers/mtd/devices/ms02-nv.c 2005-02-01 17:11:17.000000000 -0500
9607 - * Copyright (c) 2001 Maciej W. Rozycki
9608 + * Copyright (c) 2001 Maciej W. Rozycki
9610 - * This program is free software; you can redistribute it and/or
9611 - * modify it under the terms of the GNU General Public License
9612 - * as published by the Free Software Foundation; either version
9613 - * 2 of the License, or (at your option) any later version.
9614 + * This program is free software; you can redistribute it and/or
9615 + * modify it under the terms of the GNU General Public License
9616 + * as published by the Free Software Foundation; either version
9617 + * 2 of the License, or (at your option) any later version.
9619 - * $Id: ms02-nv.c,v 1.4 2003/05/20 21:03:07 dwmw2 Exp $
9620 + * $Id: ms02-nv.c,v 1.7 2004/07/29 14:16:45 macro Exp $
9623 #include <linux/init.h>
9627 static char version[] __initdata =
9628 - "ms02-nv.c: v.1.0.0 13 Aug 2001 Maciej W. Rozycki.\n";
9629 + "ms02-nv.c: v.1.0.0 13 Aug 2001 Maciej W. Rozycki.\n";
9631 -MODULE_AUTHOR("Maciej W. Rozycki <macro@ds2.pg.gda.pl>");
9632 +MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
9633 MODULE_DESCRIPTION("DEC MS02-NV NVRAM module driver");
9634 MODULE_LICENSE("GPL");
9638 * Addresses we probe for an MS02-NV at. Modules may be located
9639 - * at any 8MB boundary within a 0MB up to 112MB range or at any 32MB
9640 - * boundary within a 0MB up to 448MB range. We don't support a module
9642 + * at any 8MiB boundary within a 0MiB up to 112MiB range or at any 32MiB
9643 + * boundary within a 0MiB up to 448MiB range. We don't support a module
9644 + * at 0MiB, though.
9646 static ulong ms02nv_addrs[] __initdata = {
9647 0x07000000, 0x06800000, 0x06000000, 0x05800000, 0x05000000,
9652 - /* The module decodes 8MB of address space. */
9653 + /* The module decodes 8MiB of address space. */
9654 mod_res = kmalloc(sizeof(*mod_res), GFP_KERNEL);
9658 goto err_out_csr_res;
9661 - printk(KERN_INFO "mtd%d: %s at 0x%08lx, size %uMB.\n",
9662 + printk(KERN_INFO "mtd%d: %s at 0x%08lx, size %uMiB.\n",
9663 mtd->index, ms02nv_name, addr, size >> 20);
9665 mp->next = root_ms02nv_mtd;
9666 @@ -293,12 +293,12 @@
9668 switch (mips_machtype) {
9669 case MACH_DS5000_200:
9670 - csr = (volatile u32 *)KN02_CSR_ADDR;
9671 + csr = (volatile u32 *)KN02_CSR_BASE;
9672 if (*csr & KN02_CSR_BNK32M)
9675 case MACH_DS5000_2X0:
9678 csr = (volatile u32 *)KN03_MCR_BASE;
9679 if (*csr & KN03_MCR_BNK32M)
9681 Index: linux-2.6.5/drivers/mtd/devices/ms02-nv.h
9682 ===================================================================
9683 --- linux-2.6.5.orig/drivers/mtd/devices/ms02-nv.h 2004-04-03 22:37:07.000000000 -0500
9684 +++ linux-2.6.5/drivers/mtd/devices/ms02-nv.h 2005-02-01 17:11:17.000000000 -0500
9687 - * Copyright (c) 2001 Maciej W. Rozycki
9688 + * Copyright (c) 2001, 2003 Maciej W. Rozycki
9690 - * This program is free software; you can redistribute it and/or
9691 - * modify it under the terms of the GNU General Public License
9692 - * as published by the Free Software Foundation; either version
9693 - * 2 of the License, or (at your option) any later version.
9694 + * DEC MS02-NV (54-20948-01) battery backed-up NVRAM module for
9695 + * DECstation/DECsystem 5000/2x0 and DECsystem 5900 and 5900/260
9698 - * $Id: ms02-nv.h,v 1.1 2002/09/13 13:46:55 dwmw2 Exp $
9699 + * This program is free software; you can redistribute it and/or
9700 + * modify it under the terms of the GNU General Public License
9701 + * as published by the Free Software Foundation; either version
9702 + * 2 of the License, or (at your option) any later version.
9704 + * $Id: ms02-nv.h,v 1.3 2003/08/19 09:25:36 dwmw2 Exp $
9707 #include <linux/ioport.h>
9708 #include <linux/mtd/mtd.h>
9711 + * Addresses are decoded as follows:
9713 + * 0x000000 - 0x3fffff SRAM
9714 + * 0x400000 - 0x7fffff CSR
9716 + * Within the SRAM area the following ranges are forced by the system
9719 + * 0x000000 - 0x0003ff diagnostic area, destroyed upon a reboot
9720 + * 0x000400 - ENDofRAM storage area, available to operating systems
9722 + * but we can't really use the available area right from 0x000400 as
9723 + * the first word is used by the firmware as a status flag passed
9724 + * from an operating system. If anything but the valid data magic
9725 + * ID value is found, the firmware considers the SRAM clean, i.e.
9726 + * containing no valid data, and disables the battery resulting in
9727 + * data being erased as soon as power is switched off. So the choice
9728 + * for the start address of the user-available is 0x001000 which is
9729 + * nicely page aligned. The area between 0x000404 and 0x000fff may
9730 + * be used by the driver for own needs.
9732 + * The diagnostic area defines two status words to be read by an
9733 + * operating system, a magic ID to distinguish a MS02-NV board from
9734 + * anything else and a status information providing results of tests
9735 + * as well as the size of SRAM available, which can be 1MiB or 2MiB
9736 + * (that's what the firmware handles; no idea if 2MiB modules ever
9739 + * The firmware only handles the MS02-NV board if installed in the
9740 + * last (15th) slot, so for any other location the status information
9741 + * stored in the SRAM cannot be relied upon. But from the hardware
9742 + * point of view there is no problem using up to 14 such boards in a
9743 + * system -- only the 1st slot needs to be filled with a DRAM module.
9744 + * The MS02-NV board is ECC-protected, like other MS02 memory boards.
9746 + * The state of the battery as provided by the CSR is reflected on
9747 + * the two onboard LEDs. When facing the battery side of the board,
9748 + * with the LEDs at the top left and the battery at the bottom right
9749 + * (i.e. looking from the back side of the system box), their meaning
9750 + * is as follows (the system has to be powered on):
9752 + * left LED battery disable status: lit = enabled
9753 + * right LED battery condition status: lit = OK
9756 /* MS02-NV iomem register offsets. */
9757 #define MS02NV_CSR 0x400000 /* control & status register */
9759 +/* MS02-NV CSR status bits. */
9760 +#define MS02NV_CSR_BATT_OK 0x01 /* battery OK */
9761 +#define MS02NV_CSR_BATT_OFF 0x02 /* battery disabled */
9764 /* MS02-NV memory offsets. */
9765 #define MS02NV_DIAG 0x0003f8 /* diagnostic status */
9766 #define MS02NV_MAGIC 0x0003fc /* MS02-NV magic ID */
9767 -#define MS02NV_RAM 0x000400 /* general-purpose RAM start */
9768 +#define MS02NV_VALID 0x000400 /* valid data magic ID */
9769 +#define MS02NV_RAM 0x001000 /* user-exposed RAM start */
9771 -/* MS02-NV diagnostic status constants. */
9772 -#define MS02NV_DIAG_SIZE_MASK 0xf0 /* RAM size mask */
9773 -#define MS02NV_DIAG_SIZE_SHIFT 0x10 /* RAM size shift (left) */
9774 +/* MS02-NV diagnostic status bits. */
9775 +#define MS02NV_DIAG_TEST 0x01 /* SRAM test done (?) */
9776 +#define MS02NV_DIAG_RO 0x02 /* SRAM r/o test done */
9777 +#define MS02NV_DIAG_RW 0x04 /* SRAM r/w test done */
9778 +#define MS02NV_DIAG_FAIL 0x08 /* SRAM test failed */
9779 +#define MS02NV_DIAG_SIZE_MASK 0xf0 /* SRAM size mask */
9780 +#define MS02NV_DIAG_SIZE_SHIFT 0x10 /* SRAM size shift (left) */
9782 /* MS02-NV general constants. */
9783 #define MS02NV_ID 0x03021966 /* MS02-NV magic ID value */
9784 +#define MS02NV_VALID_ID 0xbd100248 /* valid data magic ID value */
9785 #define MS02NV_SLOT_SIZE 0x800000 /* size of the address space
9786 decoded by the module */
9789 typedef volatile u32 ms02nv_uint;
9791 struct ms02nv_private {
9792 Index: linux-2.6.5/drivers/mtd/devices/mtdram.c
9793 ===================================================================
9794 --- linux-2.6.5.orig/drivers/mtd/devices/mtdram.c 2004-04-03 22:36:15.000000000 -0500
9795 +++ linux-2.6.5/drivers/mtd/devices/mtdram.c 2005-02-01 17:11:17.000000000 -0500
9798 * mtdram - a test mtd device
9799 - * $Id: mtdram.c,v 1.32 2003/05/21 15:15:07 dwmw2 Exp $
9800 + * $Id: mtdram.c,v 1.33 2004/08/09 13:19:44 dwmw2 Exp $
9801 * Author: Alexander Larsson <alex@cendio.se>
9803 * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
9805 memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
9807 instr->state = MTD_ERASE_DONE;
9808 + mtd_erase_callback(instr);
9810 - if (instr->callback)
9811 - (*(instr->callback))(instr);
9815 Index: linux-2.6.5/drivers/mtd/devices/phram.c
9816 ===================================================================
9817 --- linux-2.6.5.orig/drivers/mtd/devices/phram.c 1969-12-31 19:00:00.000000000 -0500
9818 +++ linux-2.6.5/drivers/mtd/devices/phram.c 2005-02-01 17:11:17.000000000 -0500
9822 + * $Id: phram.c,v 1.2 2004/08/09 13:19:44 dwmw2 Exp $
9824 + * Copyright (c) Jochen Schaeuble <psionic@psionic.de>
9825 + * 07/2003 rewritten by Joern Engel <joern@wh.fh-wedel.de>
9827 + * DISCLAIMER: This driver makes use of Rusty's excellent module code,
9828 + * so it will not work for 2.4 without changes and it wont work for 2.4
9829 + * as a module without major changes. Oh well!
9833 + * one commend line parameter per device, each in the form:
9834 + * phram=<name>,<start>,<len>
9835 + * <name> may be up to 63 characters.
9836 + * <start> and <len> can be octal, decimal or hexadecimal. If followed
9837 + * by "k", "M" or "G", the numbers will be interpreted as kilo, mega or
9842 +#include <asm/io.h>
9843 +#include <linux/init.h>
9844 +#include <linux/kernel.h>
9845 +#include <linux/list.h>
9846 +#include <linux/module.h>
9847 +#include <linux/moduleparam.h>
9848 +#include <linux/mtd/mtd.h>
9850 +#define ERROR(fmt, args...) printk(KERN_ERR "phram: " fmt , ## args)
9852 +struct phram_mtd_list {
9853 + struct list_head list;
9854 + struct mtd_info *mtdinfo;
9857 +static LIST_HEAD(phram_list);
9861 +int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
9863 + u_char *start = (u_char *)mtd->priv;
9865 + if (instr->addr + instr->len > mtd->size)
9868 + memset(start + instr->addr, 0xff, instr->len);
9870 + /* This'll catch a few races. Free the thing before returning :)
9871 + * I don't feel at all ashamed. This kind of thing is possible anyway
9872 + * with flash, but unlikely.
9875 + instr->state = MTD_ERASE_DONE;
9877 + mtd_erase_callback(instr);
9882 +int phram_point(struct mtd_info *mtd, loff_t from, size_t len,
9883 + size_t *retlen, u_char **mtdbuf)
9885 + u_char *start = (u_char *)mtd->priv;
9887 + if (from + len > mtd->size)
9890 + *mtdbuf = start + from;
9895 +void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
9899 +int phram_read(struct mtd_info *mtd, loff_t from, size_t len,
9900 + size_t *retlen, u_char *buf)
9902 + u_char *start = (u_char *)mtd->priv;
9904 + if (from + len > mtd->size)
9907 + memcpy(buf, start + from, len);
9913 +int phram_write(struct mtd_info *mtd, loff_t to, size_t len,
9914 + size_t *retlen, const u_char *buf)
9916 + u_char *start = (u_char *)mtd->priv;
9918 + if (to + len > mtd->size)
9921 + memcpy(start + to, buf, len);
9929 +static void unregister_devices(void)
9931 + struct phram_mtd_list *this;
9933 + list_for_each_entry(this, &phram_list, list) {
9934 + del_mtd_device(this->mtdinfo);
9935 + iounmap(this->mtdinfo->priv);
9936 + kfree(this->mtdinfo);
9941 +static int register_device(char *name, unsigned long start, unsigned long len)
9943 + struct phram_mtd_list *new;
9944 + int ret = -ENOMEM;
9946 + new = kmalloc(sizeof(*new), GFP_KERNEL);
9950 + new->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
9951 + if (!new->mtdinfo)
9954 + memset(new->mtdinfo, 0, sizeof(struct mtd_info));
9957 + new->mtdinfo->priv = ioremap(start, len);
9958 + if (!new->mtdinfo->priv) {
9959 + ERROR("ioremap failed\n");
9964 + new->mtdinfo->name = name;
9965 + new->mtdinfo->size = len;
9966 + new->mtdinfo->flags = MTD_CAP_RAM | MTD_ERASEABLE | MTD_VOLATILE;
9967 + new->mtdinfo->erase = phram_erase;
9968 + new->mtdinfo->point = phram_point;
9969 + new->mtdinfo->unpoint = phram_unpoint;
9970 + new->mtdinfo->read = phram_read;
9971 + new->mtdinfo->write = phram_write;
9972 + new->mtdinfo->owner = THIS_MODULE;
9973 + new->mtdinfo->type = MTD_RAM;
9974 + new->mtdinfo->erasesize = 0x0;
9977 + if (add_mtd_device(new->mtdinfo)) {
9978 + ERROR("Failed to register new device\n");
9982 + list_add_tail(&new->list, &phram_list);
9986 + iounmap(new->mtdinfo->priv);
9988 + kfree(new->mtdinfo);
9995 +static int ustrtoul(const char *cp, char **endp, unsigned int base)
9997 + unsigned long result = simple_strtoul(cp, endp, base);
10011 +static int parse_num32(uint32_t *num32, const char *token)
10016 + n = ustrtoul(token, &endp, 0);
10024 +static int parse_name(char **pname, const char *token)
10029 + len = strlen(token) + 1;
10033 + name = kmalloc(len, GFP_KERNEL);
10037 + strcpy(name, token);
10043 +#define parse_err(fmt, args...) do { \
10044 + ERROR(fmt , ## args); \
10048 +static int phram_setup(const char *val, struct kernel_param *kp)
10050 + char buf[64+12+12], *str = buf;
10057 + if (strnlen(val, sizeof(str)) >= sizeof(str))
10058 + parse_err("parameter too long\n");
10060 + strcpy(str, val);
10062 + for (i=0; i<3; i++)
10063 + token[i] = strsep(&str, ",");
10066 + parse_err("too many arguments\n");
10069 + parse_err("not enough arguments\n");
10071 + ret = parse_name(&name, token[0]);
10072 + if (ret == -ENOMEM)
10073 + parse_err("out of memory\n");
10074 + if (ret == -ENOSPC)
10075 + parse_err("name too long\n");
10079 + ret = parse_num32(&start, token[1]);
10081 + parse_err("illegal start address\n");
10083 + ret = parse_num32(&len, token[2]);
10085 + parse_err("illegal device length\n");
10087 + register_device(name, start, len);
10092 +module_param_call(phram, phram_setup, NULL, NULL, 000);
10093 +MODULE_PARM_DESC(phram, "Memory region to map. \"map=<name>,<start><length>\"");
10096 + * Just for compatibility with slram, this is horrible and should go someday.
10098 +static int __init slram_setup(const char *val, struct kernel_param *kp)
10100 + char buf[256], *str = buf;
10102 + if (!val || !val[0])
10103 + parse_err("no arguments to \"slram=\"\n");
10105 + if (strnlen(val, sizeof(str)) >= sizeof(str))
10106 + parse_err("parameter too long\n");
10108 + strcpy(str, val);
10117 + for (i=0; i<3; i++) {
10118 + token[i] = strsep(&str, ",");
10121 + parse_err("wrong number of arguments to \"slram=\"\n");
10125 + ret = parse_name(&name, token[0]);
10126 + if (ret == -ENOMEM)
10127 + parse_err("of memory\n");
10128 + if (ret == -ENOSPC)
10129 + parse_err("too long\n");
10134 + ret = parse_num32(&start, token[1]);
10136 + parse_err("illegal start address\n");
10139 + if (token[2][0] == '+')
10140 + ret = parse_num32(&len, token[2] + 1);
10142 + ret = parse_num32(&len, token[2]);
10145 + parse_err("illegal device length\n");
10147 + if (token[2][0] != '+') {
10149 + parse_err("end < start\n");
10153 + register_device(name, start, len);
10158 +module_param_call(slram, slram_setup, NULL, NULL, 000);
10159 +MODULE_PARM_DESC(slram, "List of memory regions to map. \"map=<name>,<start><length/end>\"");
10162 +int __init init_phram(void)
10164 + printk(KERN_ERR "phram loaded\n");
10168 +static void __exit cleanup_phram(void)
10170 + unregister_devices();
10173 +module_init(init_phram);
10174 +module_exit(cleanup_phram);
10176 +MODULE_LICENSE("GPL");
10177 +MODULE_AUTHOR("Jörn Engel <joern@wh.fh-wedel.de>");
10178 +MODULE_DESCRIPTION("MTD driver for physical RAM");
10179 Index: linux-2.6.5/drivers/mtd/devices/pmc551.c
10180 ===================================================================
10181 --- linux-2.6.5.orig/drivers/mtd/devices/pmc551.c 2004-04-03 22:37:41.000000000 -0500
10182 +++ linux-2.6.5/drivers/mtd/devices/pmc551.c 2005-02-01 17:11:17.000000000 -0500
10185 - * $Id: pmc551.c,v 1.24 2003/05/20 21:03:08 dwmw2 Exp $
10186 + * $Id: pmc551.c,v 1.28 2004/08/09 13:19:44 dwmw2 Exp $
10188 * PMC551 PCI Mezzanine Ram Device
10190 @@ -109,12 +109,6 @@
10191 #include <linux/mtd/pmc551.h>
10192 #include <linux/mtd/compatmac.h>
10194 -#if LINUX_VERSION_CODE > 0x20300
10195 -#define PCI_BASE_ADDRESS(dev) (dev->resource[0].start)
10197 -#define PCI_BASE_ADDRESS(dev) (dev->base_address[0])
10200 static struct mtd_info *pmc551list;
10202 static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr)
10203 @@ -175,9 +169,7 @@
10204 printk(KERN_DEBUG "pmc551_erase() done\n");
10207 - if (instr->callback) {
10208 - (*(instr->callback))(instr);
10210 + mtd_erase_callback(instr);
10214 @@ -564,7 +556,7 @@
10215 (size<1024)?size:(size<1048576)?size>>10:size>>20,
10216 (size<1024)?'B':(size<1048576)?'K':'M',
10217 size, ((dcmd&(0x1<<3)) == 0)?"non-":"",
10218 - PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK );
10219 + (dev->resource[0].start)&PCI_BASE_ADDRESS_MEM_MASK );
10222 * Check to see the state of the memory
10223 @@ -694,7 +686,7 @@
10226 printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%lX\n",
10227 - PCI_BASE_ADDRESS(PCI_Device));
10228 + PCI_Device->resource[0].start);
10231 * The PMC551 device acts VERY weird if you don't init it
10232 @@ -748,7 +740,7 @@
10233 printk(KERN_NOTICE "pmc551: Using specified aperture size %dM\n", asize>>20);
10234 priv->asize = asize;
10236 - priv->start = ioremap((PCI_BASE_ADDRESS(PCI_Device)
10237 + priv->start = ioremap(((PCI_Device->resource[0].start)
10238 & PCI_BASE_ADDRESS_MEM_MASK),
10241 Index: linux-2.6.5/drivers/mtd/devices/slram.c
10242 ===================================================================
10243 --- linux-2.6.5.orig/drivers/mtd/devices/slram.c 2004-04-03 22:36:12.000000000 -0500
10244 +++ linux-2.6.5/drivers/mtd/devices/slram.c 2005-02-01 17:11:17.000000000 -0500
10246 /*======================================================================
10248 - $Id: slram.c,v 1.30 2003/05/20 21:03:08 dwmw2 Exp $
10249 + $Id: slram.c,v 1.31 2004/08/09 13:19:44 dwmw2 Exp $
10251 This driver provides a method to access memory not used by the kernel
10252 itself (i.e. if the kernel commandline mem=xxx is used). To actually
10255 instr->state = MTD_ERASE_DONE;
10257 - if (instr->callback) {
10258 - (*(instr->callback))(instr);
10263 + mtd_erase_callback(instr);
10267 Index: linux-2.6.5/drivers/mtd/ftl.c
10268 ===================================================================
10269 --- linux-2.6.5.orig/drivers/mtd/ftl.c 2004-04-03 22:37:45.000000000 -0500
10270 +++ linux-2.6.5/drivers/mtd/ftl.c 2005-02-01 17:11:29.000000000 -0500
10272 /* This version ported to the Linux-MTD system by dwmw2@infradead.org
10273 - * $Id: ftl.c,v 1.51 2003/06/23 12:00:08 dwmw2 Exp $
10274 + * $Id: ftl.c,v 1.53 2004/08/09 13:55:43 dwmw2 Exp $
10276 * Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
10277 * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups
10278 @@ -167,7 +167,8 @@
10280 erase_unit_header_t header;
10281 loff_t offset, max_offset;
10285 part->header.FormattedSize = 0;
10286 max_offset = (0x100000<part->mbd.mtd->size)?0x100000:part->mbd.mtd->size;
10287 /* Search first megabyte for a valid FTL header */
10288 @@ -175,11 +176,11 @@
10289 (offset + sizeof(header)) < max_offset;
10290 offset += part->mbd.mtd->erasesize ? : 0x2000) {
10292 - ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret,
10293 + err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret,
10294 (unsigned char *)&header);
10301 if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;
10303 @@ -958,7 +959,7 @@
10305 printk(KERN_NOTICE "ftl_cs: block write failed!\n");
10306 printk(KERN_NOTICE "ftl_cs: log_addr = 0x%x, virt_addr"
10307 - " = 0x%x, Offset = 0x%x\n", log_addr, virt_addr,
10308 + " = 0x%x, Offset = 0x%zx\n", log_addr, virt_addr,
10312 @@ -1093,7 +1094,7 @@
10316 - DEBUG(0, "$Id: ftl.c,v 1.51 2003/06/23 12:00:08 dwmw2 Exp $\n");
10317 + DEBUG(0, "$Id: ftl.c,v 1.53 2004/08/09 13:55:43 dwmw2 Exp $\n");
10319 return register_mtd_blktrans(&ftl_tr);
10321 Index: linux-2.6.5/drivers/mtd/inftlcore.c
10322 ===================================================================
10323 --- linux-2.6.5.orig/drivers/mtd/inftlcore.c 2004-04-03 22:36:18.000000000 -0500
10324 +++ linux-2.6.5/drivers/mtd/inftlcore.c 2005-02-01 17:11:29.000000000 -0500
10326 * (c) 1999 Machine Vision Holdings, Inc.
10327 * Author: David Woodhouse <dwmw2@infradead.org>
10329 - * $Id: inftlcore.c,v 1.14 2003/06/26 08:28:26 dwmw2 Exp $
10330 + * $Id: inftlcore.c,v 1.17 2004/08/09 13:56:48 dwmw2 Exp $
10332 * This program is free software; you can redistribute it and/or modify
10333 * it under the terms of the GNU General Public License as published by
10335 struct INFTLrecord *inftl;
10336 unsigned long temp;
10338 - if (mtd->ecctype != MTD_ECC_RS_DiskOnChip)
10339 + if (mtd->type != MTD_NANDFLASH)
10341 + /* OK, this is moderately ugly. But probably safe. Alternatives? */
10342 + if (memcmp(mtd->name, "DiskOnChip", 10))
10345 + if (!mtd->block_isbad) {
10347 +"INFTL no longer supports the old DiskOnChip drivers loaded via docprobe.\n"
10348 +"Please use the new diskonchip driver under the NAND subsystem.\n");
10352 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name);
10354 inftl = kmalloc(sizeof(*inftl), GFP_KERNEL);
10356 inftl->mbd.devnum = -1;
10357 inftl->mbd.blksize = 512;
10358 inftl->mbd.tr = tr;
10359 + memcpy(&inftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
10360 + inftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
10362 if (INFTL_mount(inftl) < 0) {
10363 printk(KERN_WARNING "INFTL: could not mount device\n");
10364 @@ -155,8 +167,8 @@
10365 u16 pot = inftl->LastFreeEUN;
10366 int silly = inftl->nb_blocks;
10368 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=0x%x,"
10369 - "desperate=%d)\n", (int)inftl, desperate);
10370 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=%p,"
10371 + "desperate=%d)\n", inftl, desperate);
10374 * Normally, we force a fold to happen before we run out of free
10375 @@ -198,8 +210,8 @@
10376 struct inftl_oob oob;
10379 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=0x%x,thisVUC=%d,"
10380 - "pending=%d)\n", (int)inftl, thisVUC, pendingblock);
10381 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,"
10382 + "pending=%d)\n", inftl, thisVUC, pendingblock);
10384 memset(BlockMap, 0xff, sizeof(BlockMap));
10385 memset(BlockDeleted, 0, sizeof(BlockDeleted));
10386 @@ -284,21 +296,22 @@
10387 if (BlockMap[block] == BLOCK_NIL)
10390 - ret = MTD_READECC(inftl->mbd.mtd, (inftl->EraseSize *
10391 + ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
10392 BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE,
10393 - &retlen, movebuf, (char *)&oob, NULL);
10394 + &retlen, movebuf);
10396 - ret = MTD_READECC(inftl->mbd.mtd, (inftl->EraseSize *
10397 + ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
10398 BlockMap[block]) + (block * SECTORSIZE),
10399 - SECTORSIZE, &retlen, movebuf, (char *)&oob,
10401 + SECTORSIZE, &retlen, movebuf);
10403 DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
10404 "away on retry?\n");
10406 + memset(&oob, 0xff, sizeof(struct inftl_oob));
10407 + oob.b.Status = oob.b.Status1 = SECTOR_USED;
10408 MTD_WRITEECC(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) +
10409 (block * SECTORSIZE), SECTORSIZE, &retlen,
10410 - movebuf, (char *)&oob, NULL);
10411 + movebuf, (char *)&oob, &inftl->oobinfo);
10415 @@ -326,7 +339,6 @@
10416 if (INFTL_formatblock(inftl, thisEUN) < 0) {
10418 * Could not erase : mark block as reserved.
10419 - * FixMe: Update Bad Unit Table on disk.
10421 inftl->PUtable[thisEUN] = BLOCK_RESERVED;
10423 @@ -354,8 +366,8 @@
10424 u16 ChainLength = 0, thislen;
10427 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=0x%x,"
10428 - "pending=%d)\n", (int)inftl, pendingblock);
10429 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=%p,"
10430 + "pending=%d)\n", inftl, pendingblock);
10432 for (chain = 0; chain < inftl->nb_blocks; chain++) {
10433 EUN = inftl->VUtable[chain];
10434 @@ -416,8 +428,8 @@
10436 int silly, silly2 = 3;
10438 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=0x%x,"
10439 - "block=%d)\n", (int)inftl, block);
10440 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=%p,"
10441 + "block=%d)\n", inftl, block);
10445 @@ -578,8 +590,8 @@
10446 struct inftl_bci bci;
10449 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=0x%x,"
10450 - "thisVUC=%d)\n", (int)inftl, thisVUC);
10451 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=%p,"
10452 + "thisVUC=%d)\n", inftl, thisVUC);
10454 memset(BlockUsed, 0, sizeof(BlockUsed));
10455 memset(BlockDeleted, 0, sizeof(BlockDeleted));
10456 @@ -668,7 +680,6 @@
10457 if (INFTL_formatblock(inftl, thisEUN) < 0) {
10459 * Could not erase : mark block as reserved.
10460 - * FixMe: Update Bad Unit Table on medium.
10462 inftl->PUtable[thisEUN] = BLOCK_RESERVED;
10464 @@ -698,8 +709,8 @@
10466 struct inftl_bci bci;
10468 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=0x%x,"
10469 - "block=%d)\n", (int)inftl, block);
10470 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=%p,"
10471 + "block=%d)\n", inftl, block);
10473 while (thisEUN < inftl->nb_blocks) {
10474 if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
10475 @@ -754,11 +765,11 @@
10476 unsigned int writeEUN;
10477 unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
10480 + struct inftl_oob oob;
10483 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=0x%x,block=%ld,"
10484 - "buffer=0x%x)\n", (int)inftl, block, (int)buffer);
10485 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=%p,block=%ld,"
10486 + "buffer=%p)\n", inftl, block, buffer);
10488 /* Is block all zero? */
10489 pend = buffer + SECTORSIZE;
10490 @@ -778,11 +789,13 @@
10494 + memset(&oob, 0xff, sizeof(struct inftl_oob));
10495 + oob.b.Status = oob.b.Status1 = SECTOR_USED;
10496 MTD_WRITEECC(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) +
10497 blockofs, SECTORSIZE, &retlen, (char *)buffer,
10498 - (char *)eccbuf, NULL);
10499 + (char *)&oob, &inftl->oobinfo);
10501 - * No need to write SECTOR_USED flags since they are written
10502 + * need to write SECTOR_USED flags since they are not written
10506 @@ -803,8 +816,8 @@
10507 struct inftl_bci bci;
10510 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=0x%x,block=%ld,"
10511 - "buffer=0x%x)\n", (int)inftl, block, (int)buffer);
10512 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld,"
10513 + "buffer=%p)\n", inftl, block, buffer);
10515 while (thisEUN < inftl->nb_blocks) {
10516 if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
10517 @@ -846,9 +859,8 @@
10520 loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
10521 - u_char eccbuf[6];
10522 - if (MTD_READECC(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen,
10523 - buffer, eccbuf, NULL))
10524 + if (MTD_READ(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen,
10529 @@ -881,7 +893,7 @@
10531 int __init init_inftl(void)
10533 - printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.14 $, "
10534 + printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.17 $, "
10535 "inftlmount.c %s\n", inftlmountrev);
10537 return register_mtd_blktrans(&inftl_tr);
10538 Index: linux-2.6.5/drivers/mtd/inftlmount.c
10539 ===================================================================
10540 --- linux-2.6.5.orig/drivers/mtd/inftlmount.c 2004-04-03 22:36:16.000000000 -0500
10541 +++ linux-2.6.5/drivers/mtd/inftlmount.c 2005-02-01 17:11:29.000000000 -0500
10543 * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
10544 * Copyright (C) 2000 Netgem S.A.
10546 - * $Id: inftlmount.c,v 1.11 2003/06/23 07:39:21 dwmw2 Exp $
10547 + * $Id: inftlmount.c,v 1.14 2004/08/09 13:57:42 dwmw2 Exp $
10549 * This program is free software; you can redistribute it and/or modify
10550 * it under the terms of the GNU General Public License as published by
10552 #include <linux/mtd/inftl.h>
10553 #include <linux/mtd/compatmac.h>
10555 -char inftlmountrev[]="$Revision: 1.11 $";
10556 +char inftlmountrev[]="$Revision: 1.14 $";
10559 * find_boot_record: Find the INFTL Media Header and its Spare copy which
10560 @@ -54,14 +54,13 @@
10562 struct inftl_unittail h1;
10563 //struct inftl_oob oob;
10564 - unsigned int i, block, boot_record_count = 0;
10565 + unsigned int i, block;
10566 u8 buf[SECTORSIZE];
10567 struct INFTLMediaHeader *mh = &inftl->MediaHdr;
10568 struct INFTLPartition *ip;
10572 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=0x%x)\n",
10574 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=%p)\n", inftl);
10577 * Assume logical EraseSize == physical erasesize for starting the
10579 inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
10581 inftl->MediaUnit = BLOCK_NIL;
10582 - inftl->SpareMediaUnit = BLOCK_NIL;
10584 /* Search for a valid boot record */
10585 for (block = 0; block < inftl->nb_blocks; block++) {
10587 * Check for BNAND header first. Then whinge if it's found
10588 * but later checks fail.
10590 - if ((ret = MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize,
10591 - SECTORSIZE, &retlen, buf))) {
10592 + ret = MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize,
10593 + SECTORSIZE, &retlen, buf);
10594 + /* We ignore ret in case the ECC of the MediaHeader is invalid
10595 + (which is apparently acceptable) */
10596 + if (retlen != SECTORSIZE) {
10597 static int warncount = 5;
10600 @@ -114,36 +115,28 @@
10604 - if (boot_record_count) {
10606 - * We've already processed one. So we just check if
10607 - * this one is the same as the first one we found.
10609 - if (memcmp(mh, buf, sizeof(struct INFTLMediaHeader))) {
10610 - printk(KERN_WARNING "INFTL: Media Headers at "
10611 - "0x%x and 0x%x disagree.\n",
10612 - inftl->MediaUnit * inftl->EraseSize,
10613 - block * inftl->EraseSize);
10616 - if (boot_record_count == 1)
10617 - inftl->SpareMediaUnit = block;
10620 - * Mark this boot record (INFTL MediaHeader) block as
10623 - inftl->PUtable[block] = BLOCK_RESERVED;
10625 - boot_record_count++;
10630 * This is the first we've seen.
10631 * Copy the media header structure into place.
10633 memcpy(mh, buf, sizeof(struct INFTLMediaHeader));
10635 + /* Read the spare media header at offset 4096 */
10636 + MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize + 4096,
10637 + SECTORSIZE, &retlen, buf);
10638 + if (retlen != SECTORSIZE) {
10639 + printk(KERN_WARNING "INFTL: Unable to read spare "
10640 + "Media Header\n");
10643 + /* Check if this one is the same as the first one we found. */
10644 + if (memcmp(mh, buf, sizeof(struct INFTLMediaHeader))) {
10645 + printk(KERN_WARNING "INFTL: Primary and spare Media "
10646 + "Headers disagree.\n");
10650 mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
10651 mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
10652 mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions);
10653 @@ -197,8 +190,9 @@
10654 "UnitSizeFactor 0x%02x is experimental\n",
10655 mh->BlockMultiplierBits);
10656 inftl->EraseSize = inftl->mbd.mtd->erasesize <<
10657 - (0xff - mh->BlockMultiplierBits);
10658 + mh->BlockMultiplierBits;
10659 inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
10660 + block >>= mh->BlockMultiplierBits;
10663 /* Scan the partitions */
10664 @@ -293,7 +287,7 @@
10665 inftl->PUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL);
10666 if (!inftl->PUtable) {
10667 printk(KERN_WARNING "INFTL: allocation of PUtable "
10668 - "failed (%d bytes)\n",
10669 + "failed (%zd bytes)\n",
10670 inftl->nb_blocks * sizeof(u16));
10673 @@ -302,7 +296,7 @@
10674 if (!inftl->VUtable) {
10675 kfree(inftl->PUtable);
10676 printk(KERN_WARNING "INFTL: allocation of VUtable "
10677 - "failed (%d bytes)\n",
10678 + "failed (%zd bytes)\n",
10679 inftl->nb_blocks * sizeof(u16));
10682 @@ -317,34 +311,23 @@
10683 /* Mark this boot record (NFTL MediaHeader) block as reserved */
10684 inftl->PUtable[block] = BLOCK_RESERVED;
10687 /* Read Bad Erase Unit Table and modify PUtable[] accordingly */
10688 for (i = 0; i < inftl->nb_blocks; i++) {
10689 - if ((i & (SECTORSIZE - 1)) == 0) {
10690 - /* read one sector for every SECTORSIZE of blocks */
10691 - if ((ret = MTD_READECC(inftl->mbd.mtd,
10692 - block * inftl->EraseSize + i + SECTORSIZE,
10693 - SECTORSIZE, &retlen, buf,
10694 - (char *)&oob, NULL)) < 0) {
10695 - printk(KERN_WARNING "INFTL: read of "
10696 - "bad sector table failed "
10697 - "(err %d)\n", ret);
10698 - kfree(inftl->VUtable);
10699 - kfree(inftl->PUtable);
10703 + /* If any of the physical eraseblocks are bad, don't
10705 + for (physblock = 0; physblock < inftl->EraseSize; physblock += inftl->mbd.mtd->erasesize) {
10706 + if (inftl->mbd.mtd->block_isbad(inftl->mbd.mtd, i * inftl->EraseSize + physblock))
10707 + inftl->PUtable[i] = BLOCK_RESERVED;
10709 - /* Mark the Bad Erase Unit as RESERVED in PUtable */
10710 - if (buf[i & (SECTORSIZE - 1)] != 0xff)
10711 - inftl->PUtable[i] = BLOCK_RESERVED;
10715 inftl->MediaUnit = block;
10716 - boot_record_count++;
10720 - return boot_record_count ? 0 : -1;
10726 static int memcmpb(void *a, int c, int n)
10727 @@ -364,28 +347,22 @@
10728 static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
10729 int len, int check_oob)
10732 - u8 buf[SECTORSIZE];
10733 + u8 buf[SECTORSIZE + inftl->mbd.mtd->oobsize];
10737 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=0x%x,"
10738 - "address=0x%x,len=%d,check_oob=%d)\n", (int)inftl,
10739 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=%p,"
10740 + "address=0x%x,len=%d,check_oob=%d)\n", inftl,
10741 address, len, check_oob);
10743 for (i = 0; i < len; i += SECTORSIZE) {
10745 - * We want to read the sector without ECC check here since a
10746 - * free sector does not have ECC syndrome on it yet.
10748 - if (MTD_READ(inftl->mbd.mtd, address, SECTORSIZE, &retlen, buf) < 0)
10749 + if (MTD_READECC(inftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &inftl->oobinfo) < 0)
10751 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
10755 - if (MTD_READOOB(inftl->mbd.mtd, address,
10756 - inftl->mbd.mtd->oobsize, &retlen, buf) < 0)
10758 - if (memcmpb(buf, 0xff, inftl->mbd.mtd->oobsize) != 0)
10759 + if (memcmpb(buf + SECTORSIZE, 0xff, inftl->mbd.mtd->oobsize) != 0)
10762 address += SECTORSIZE;
10763 @@ -402,52 +379,62 @@
10764 * Return: 0 when succeed, -1 on error.
10766 * ToDo: 1. Is it neceressary to check_free_sector after erasing ??
10767 - * 2. UnitSizeFactor != 0xFF
10769 int INFTL_formatblock(struct INFTLrecord *inftl, int block)
10773 struct inftl_unittail uci;
10774 struct erase_info *instr = &inftl->instr;
10777 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=0x%x,"
10778 - "block=%d)\n", (int)inftl, block);
10779 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p,"
10780 + "block=%d)\n", inftl, block);
10782 memset(instr, 0, sizeof(struct erase_info));
10784 + /* FIXME: Shouldn't we be setting the 'discarded' flag to zero
10787 /* Use async erase interface, test return code */
10788 instr->addr = block * inftl->EraseSize;
10789 - instr->len = inftl->EraseSize;
10790 - MTD_ERASE(inftl->mbd.mtd, instr);
10791 + instr->len = inftl->mbd.mtd->erasesize;
10792 + /* Erase one physical eraseblock at a time, even though the NAND api
10793 + allows us to group them. This way we if we have a failure, we can
10794 + mark only the failed block in the bbt. */
10795 + for (physblock = 0; physblock < inftl->EraseSize; physblock += instr->len, instr->addr += instr->len) {
10796 + MTD_ERASE(inftl->mbd.mtd, instr);
10798 + if (instr->state == MTD_ERASE_FAILED) {
10799 + printk(KERN_WARNING "INFTL: error while formatting block %d\n",
10804 - if (instr->state == MTD_ERASE_FAILED) {
10806 - * Could not format, FixMe: We should update the BadUnitTable
10807 - * both in memory and on disk.
10809 - printk(KERN_WARNING "INFTL: error while formatting block %d\n",
10812 + * Check the "freeness" of Erase Unit before updating metadata.
10813 + * FixMe: is this check really necessary? Since we have check the
10814 + * return code after the erase operation.
10816 + if (check_free_sectors(inftl, instr->addr, instr->len, 1) != 0)
10821 - * Check the "freeness" of Erase Unit before updating metadata.
10822 - * FixMe: is this check really necessary? Since we have check the
10823 - * return code after the erase operation.
10825 - if (check_free_sectors(inftl, instr->addr, inftl->EraseSize, 1) != 0)
10828 uci.EraseMark = cpu_to_le16(ERASE_MARK);
10829 uci.EraseMark1 = cpu_to_le16(ERASE_MARK);
10830 uci.Reserved[0] = 0;
10831 uci.Reserved[1] = 0;
10832 uci.Reserved[2] = 0;
10833 uci.Reserved[3] = 0;
10834 - if (MTD_WRITEOOB(inftl->mbd.mtd, block * inftl->EraseSize + SECTORSIZE * 2 +
10835 + instr->addr = block * inftl->EraseSize + SECTORSIZE * 2;
10836 + if (MTD_WRITEOOB(inftl->mbd.mtd, instr->addr +
10837 8, 8, &retlen, (char *)&uci) < 0)
10842 + /* could not format, update the bad block table (caller is responsible
10843 + for setting the PUtable to BLOCK_RESERVED on failure) */
10844 + inftl->mbd.mtd->block_markbad(inftl->mbd.mtd, instr->addr);
10849 @@ -472,7 +459,6 @@
10850 if (INFTL_formatblock(inftl, block) < 0) {
10852 * Cannot format !!!! Mark it as Bad Unit,
10853 - * FixMe: update the BadUnitTable on disk.
10855 inftl->PUtable[block] = BLOCK_RESERVED;
10857 @@ -565,10 +551,11 @@
10858 int chain_length, do_format_chain;
10859 struct inftl_unithead1 h0;
10860 struct inftl_unittail h1;
10864 u8 *ANACtable, ANAC;
10866 - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=0x%x)\n", (int)s);
10867 + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=%p)\n", s);
10869 /* Search for INFTL MediaHeader and Spare INFTL Media Header */
10870 if (find_boot_record(s) < 0) {
10871 Index: linux-2.6.5/drivers/mtd/maps/Kconfig
10872 ===================================================================
10873 --- linux-2.6.5.orig/drivers/mtd/maps/Kconfig 2004-04-03 22:38:21.000000000 -0500
10874 +++ linux-2.6.5/drivers/mtd/maps/Kconfig 2005-02-01 17:11:17.000000000 -0500
10876 # drivers/mtd/maps/Kconfig
10877 -# $Id: Kconfig,v 1.12 2003/06/23 07:38:11 dwmw2 Exp $
10878 +# $Id: Kconfig,v 1.34 2004/09/02 01:27:07 eric Exp $
10880 menu "Mapping drivers for chip access"
10883 command set driver code to communicate with flash chips which
10884 are mapped physically into the CPU's memory. You will need to
10885 configure the physical address and size of the flash chips on
10886 - your particular board as well as the bus width.
10887 + your particular board as well as the bus width, either statically
10888 + with config options or at run-time.
10890 config MTD_PHYSMAP_START
10891 hex "Physical start address of flash mapping"
10893 are mapped on your particular target board. Refer to the
10894 memory map which should hopefully be in the documentation for
10896 + Ignore this option if you use run-time physmap configuration
10897 + (i.e., run-time calling physmap_configure()).
10899 config MTD_PHYSMAP_LEN
10900 hex "Physical length of flash mapping"
10902 than the total amount of flash present. Refer to the memory
10903 map which should hopefully be in the documentation for your
10905 + Ignore this option if you use run-time physmap configuration
10906 + (i.e., run-time calling physmap_configure()).
10908 -config MTD_PHYSMAP_BUSWIDTH
10909 - int "Bus width in octets"
10910 +config MTD_PHYSMAP_BANKWIDTH
10911 + int "Bank width in octets"
10912 depends on MTD_PHYSMAP
10916 in octets. For example, if you have a data bus width of 32
10917 bits, you would set the bus width octect value to 4. This is
10918 used internally by the CFI drivers.
10919 + Ignore this option if you use run-time physmap configuration
10920 + (i.e., run-time calling physmap_configure()).
10922 config MTD_SUN_UFLASH
10923 tristate "Sun Microsystems userflash support"
10925 By default the flash is split into 3 partitions which are accessed
10926 as separate MTD devices. This board utilizes Intel StrataFlash.
10928 - <http://www.arcomcontrols.com/products/icp/pc104/processors/>.
10929 + <http://www.arcomcontrols.com/products/icp/pc104/processors/SBC_GX1.htm>.
10931 config MTD_ELAN_104NC
10932 tristate "CFI Flash device mapped on Arcom ELAN-104NC"
10933 @@ -104,7 +111,7 @@
10934 System's ELAN-104NC development board. By default the flash
10935 is split into 3 partitions which are accessed as separate MTD
10936 devices. This board utilizes Intel StrataFlash. More info at
10937 - <http://www.arcomcontrols.com/products/icp/pc104/processors/>.
10938 + <http://www.arcomcontrols.com/products/icp/pc104/processors/ELAN104NC.htm>.
10941 tristate "CFI Flash device mapped on Intel Lubbock XScale eval board"
10942 @@ -120,7 +127,7 @@
10943 This provides a 'mapping' driver which supports the way in which
10944 the flash chips are connected in the Octagon-5066 Single Board
10945 Computer. More information on the board is available at
10946 - <http://www.octagonsystems.com/Products/5066/5066.html>.
10947 + <http://www.octagonsystems.com/CPUpages/5066.html>.
10950 tristate "JEDEC Flash device mapped on Tempustech VMAX SBC301"
10951 @@ -129,7 +136,7 @@
10952 This provides a 'mapping' driver which supports the way in which
10953 the flash chips are connected in the Tempustech VMAX SBC301 Single
10954 Board Computer. More information on the board is available at
10955 - <http://www.tempustech.com/tt301.htm>.
10956 + <http://www.tempustech.com/>.
10958 config MTD_SCx200_DOCFLASH
10959 tristate "Flash device mapped with DOCCS on NatSemi SCx200"
10960 @@ -151,11 +158,11 @@
10964 -config MTD_ICH2ROM
10965 - tristate "BIOS flash chip on Intel Hub Controller 2"
10966 - depends on X86 && MTD_JEDECPROBE && MTD_COMPLEX_MAPPINGS
10967 +config MTD_ICHXROM
10968 + tristate "BIOS flash chip on Intel Controller Hub 2/3/4/5"
10969 + depends on X86 && MTD_JEDECPROBE
10971 - Support for treating the BIOS flash chip on ICH2 motherboards
10972 + Support for treating the BIOS flash chip on ICHX motherboards
10973 as an MTD device - with this you can reprogram your BIOS.
10976 @@ -177,7 +184,7 @@
10979 tristate "Flash chips on LASAT board"
10980 - depends on LASAT && MTD_CFI
10983 Support for the flash chips on the Lasat 100 and 200 boards.
10985 @@ -210,13 +217,59 @@
10986 You can say 'Y' to both this and 'MTD_PB1XXX_BOOT' above, to use
10990 + tristate "Flash devices on Alchemy PB1550 board"
10991 + depends on MIPS && MIPS_PB1550
10993 + Flash memory access on Alchemy Pb1550 board
10995 +config MTD_PB1550_BOOT
10996 + bool "PB1550 boot flash device"
10997 + depends on MTD_PB1550
10999 + Use the first of the two 64MiB flash banks on Pb1550 board.
11000 + You can say 'Y' to both this and 'MTD_PB1550_USER' below, to use
11003 +config MTD_PB1550_USER
11004 + bool "PB1550 user flash device"
11005 + depends on MTD_PB1550
11006 + default y if MTD_PB1550_BOOT = n
11008 + Use the second of the two 64MiB flash banks on Pb1550 board.
11009 + You can say 'Y' to both this and 'MTD_PB1550_BOOT' above, to use
11013 + tristate "Flash devices on Alchemy DB1550 board"
11014 + depends on MIPS && MIPS_DB1550
11016 + Flash memory access on Alchemy Db1550 board
11018 +config MTD_DB1550_BOOT
11019 + bool "DB1550 boot flash device"
11020 + depends on MTD_DB1550
11022 + Use the first of the two 64MiB flash banks on Db1550 board.
11023 + You can say 'Y' to both this and 'MTD_DB1550_USER' below, to use
11026 +config MTD_DB1550_USER
11027 + bool "DB1550 user flash device"
11028 + depends on MTD_DB1550
11029 + default y if MTD_DB1550_BOOT = n
11031 + Use the second of the two 64MiB flash banks on Db1550 board.
11032 + You can say 'Y' to both this and 'MTD_DB1550_BOOT' above, to use
11035 config MTD_DILNETPC
11036 tristate "CFI Flash device mapped on DIL/Net PC"
11037 depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT
11039 MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP".
11040 - For details, see http://www.ssv-embedded.de/ssv/pc104/p169.htm
11041 - and http://www.ssv-embedded.de/ssv/pc104/p170.htm
11042 + For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm>
11043 + and <http://www.ssv-embedded.de/ssv/pc104/p170.htm>
11045 config MTD_DILNETPC_BOOTSIZE
11046 hex "Size of DIL/Net PC flash boot partition"
11047 @@ -235,6 +288,13 @@
11051 +config MTD_SBC8240
11052 + tristate "Flash device on SBC8240"
11053 + depends on PPC32 && MTD_JEDECPROBE && 6xx && 8260
11055 + Flash access on the SBC8240 board from Wind River. See
11056 + <http://www.windriver.com/products/sbc8240/>
11059 tristate "CFI Flash device mapped on TQM8XXL"
11060 depends on MTD_CFI && PPC32 && 8xx && TQM8xxL
11061 @@ -253,7 +313,7 @@
11062 a strange sparse mapping. This 'mapping' driver supports that
11063 arrangement, allowing the CFI probe and command set driver code
11064 to communicate with the chips on the RPXLite board. More at
11065 - <http://www.embeddedplanet.com/rpx_lite_specification_sheet.htm>.
11066 + <http://www.embeddedplanet.com/>.
11069 tristate "System flash on MBX860 board"
11070 @@ -265,7 +325,7 @@
11073 tristate "CFI Flash device mapped on D-Box2"
11074 - depends on PPC32 && 8xx && MTD_CFI_INTELSTD && MTD_CFI_INTELEXT && MTD_CFI_AMDSTD
11075 + depends on PPC32 && 8xx && DBOX2 && MTD_CFI_INTELSTD && MTD_CFI_INTELEXT && MTD_CFI_AMDSTD
11077 This enables access routines for the flash chips on the Nokia/Sagem
11078 D-Box 2 board. If you have one of these boards and would like to use
11079 @@ -295,13 +355,21 @@
11080 use the flash chips on it, say 'Y'.
11083 - tristate "CFI Flash device mapped on IBM 440GP Ebony"
11084 - depends on MTD_CFI && PPC32 && 440 && EBONY
11085 + tristate "Flash devices mapped on IBM 440GP Ebony"
11086 + depends on MTD_CFI && PPC32 && 44x && EBONY
11088 This enables access routines for the flash chips on the IBM 440GP
11089 Ebony board. If you have one of these boards and would like to
11090 use the flash chips on it, say 'Y'.
11093 + tristate "Flash devices mapped on IBM 440GX Ocotea"
11094 + depends on MTD_CFI && PPC32 && 44x && OCOTEA
11096 + This enables access routines for the flash chips on the IBM 440GX
11097 + Ocotea board. If you have one of these boards and would like to
11098 + use the flash chips on it, say 'Y'.
11101 tristate "CFI Flash devices mapped on IBM Redwood"
11102 depends on MTD_CFI && PPC32 && 4xx && 40x && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 )
11103 @@ -388,13 +456,19 @@
11104 the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
11105 If you have such a board, say 'Y'.
11108 + tristate "CFI Flash device mapped on Compaq/HP iPAQ"
11109 + depends on ARM && IPAQ_HANDHELD && MTD_CFI
11111 + This provides a driver for the on-board flash of the iPAQ.
11114 tristate "CFI Flash device mapped on DC21285 Footbridge"
11115 depends on ARM && MTD_CFI && ARCH_FOOTBRIDGE && MTD_COMPLEX_MAPPINGS
11117 This provides a driver for the flash accessed using Intel's
11118 21285 bridge used with Intel's StrongARM processors. More info at
11119 - <http://developer.intel.com/design/bridge/quicklist/dsc-21285.htm>.
11120 + <http://www.intel.com/design/bridge/docs/21285_documentation.htm>.
11123 tristate "CFI Flash device mapped on the XScale IQ80310 board"
11124 @@ -404,6 +478,24 @@
11125 IQ80310 evaluation board. If you have one of these boards and would
11126 like to use the flash chips on it, say 'Y'.
11129 + tristate "CFI Flash device mapped on Intel IXP4xx based systems"
11130 + depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX
11132 + This enables MTD access to flash devices on platforms based
11133 + on Intel's IXP4xx family of network processors such as the
11134 + IXDP425 and Coyote. If you have an IXP4xx based board and
11135 + would like to use the flash chips on it, say 'Y'.
11137 +config MTD_IXP2000
11138 + tristate "CFI Flash device mapped on Intel IXP2000 based systems"
11139 + depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000
11141 + This enables MTD access to flash devices on platforms based
11142 + on Intel's IXP2000 family of network processors such as the
11143 + IXDP425 and Coyote. If you have an IXP2000 based board and
11144 + would like to use the flash chips on it, say 'Y'.
11146 config MTD_EPXA10DB
11147 tristate "CFI Flash device mapped on Epxa10db"
11148 depends on ARM && MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT
11149 @@ -448,6 +540,13 @@
11150 PhotoMax Digital Picture Frame.
11151 If you have such a device, say 'Y'.
11153 +config MTD_NOR_TOTO
11154 + tristate "NOR Flash device on TOTO board"
11155 + depends on ARM && ARCH_OMAP && OMAP_TOTO
11157 + This enables access to the NOR flash on the Texas Instruments
11161 tristate "Hynix evaluation board mappings"
11162 depends on ARM && MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
11163 @@ -455,6 +554,13 @@
11164 This enables access to the flash chips on the Hynix evaluation boards.
11165 If you have such a board, say 'Y'.
11167 +config MTD_MPC1211
11168 + tristate "CFI Flash device mapped on Interface MPC-1211"
11169 + depends on SUPERH && SH_MPC1211 && MTD_CFI
11171 + This enables access to the flash chips on the Interface MPC-1211(CTP/PCI/MPC-SH02).
11172 + If you have such a board, say 'Y'.
11174 # This needs CFI or JEDEC, depending on the cards found.
11176 tristate "PCI MTD driver"
11177 @@ -480,5 +586,28 @@
11179 Map driver to support image based filesystems for uClinux.
11181 +config MTD_WRSBC8260
11182 + tristate "Map driver for WindRiver PowerQUICC II MPC82xx board"
11183 + depends on (SBC82xx || SBC8560)
11184 + select MTD_PARTITIONS
11185 + select MTD_MAP_BANK_WIDTH_4
11186 + select MTD_MAP_BANK_WIDTH_1
11187 + select MTD_CFI_I1
11188 + select MTD_CFI_I4
11190 + Map driver for WindRiver PowerQUICC II MPC82xx board. Drives
11191 + all three flash regions on CS0, CS1 and CS6 if they are configured
11192 + correctly by the boot loader.
11195 + tristate "Map driver for Dy-4 SVME/DMV-182 board."
11196 + depends on DMV182
11197 + select MTD_PARTITIONS
11198 + select MTD_MAP_BANK_WIDTH_32
11199 + select MTD_CFI_I8
11200 + select MTD_CFI_AMDSTD
11202 + Map driver for Dy-4 SVME/DMV-182 board.
11206 Index: linux-2.6.5/drivers/mtd/maps/Makefile
11207 ===================================================================
11208 --- linux-2.6.5.orig/drivers/mtd/maps/Makefile 2004-04-03 22:36:12.000000000 -0500
11209 +++ linux-2.6.5/drivers/mtd/maps/Makefile 2005-02-01 17:11:17.000000000 -0500
11212 # linux/drivers/maps/Makefile
11214 -# $Id: Makefile.common,v 1.2 2003/05/28 10:48:41 dwmw2 Exp $
11215 +# $Id: Makefile.common,v 1.17 2004/09/02 00:13:41 dsaxena Exp $
11217 ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y)
11218 obj-$(CONFIG_MTD) += map_funcs.o
11220 obj-$(CONFIG_MTD_IQ80310) += iq80310.o
11221 obj-$(CONFIG_MTD_L440GX) += l440gx.o
11222 obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
11223 -obj-$(CONFIG_MTD_ICH2ROM) += ich2rom.o
11224 +obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o
11225 obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
11226 obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o
11227 obj-$(CONFIG_MTD_MBX860) += mbx860.o
11229 obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
11230 obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
11231 obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
11232 +obj-$(CONFIG_MTD_IPAQ) += ipaq-flash.o
11233 obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
11234 obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o
11235 obj-$(CONFIG_MTD_NETSC520) += netsc520.o
11237 obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
11238 obj-$(CONFIG_MTD_PCI) += pci.o
11239 obj-$(CONFIG_MTD_PB1XXX) += pb1xxx-flash.o
11240 +obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o
11241 +obj-$(CONFIG_MTD_PB1550) += pb1550-flash.o
11242 +obj-$(CONFIG_MTD_DB1550) += db1550-flash.o
11243 obj-$(CONFIG_MTD_LASAT) += lasat.o
11244 obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
11245 obj-$(CONFIG_MTD_EDB7312) += edb7312.o
11247 obj-$(CONFIG_MTD_NETtel) += nettel.o
11248 obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o
11249 obj-$(CONFIG_MTD_EBONY) += ebony.o
11250 +obj-$(CONFIG_MTD_OCOTEA) += ocotea.o
11251 obj-$(CONFIG_MTD_BEECH) += beech-mtd.o
11252 obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o
11253 obj-$(CONFIG_MTD_H720X) += h720x-flash.o
11254 +obj-$(CONFIG_MTD_SBC8240) += sbc8240.o
11255 +obj-$(CONFIG_MTD_NOR_TOTO) += omap-toto-flash.o
11256 +obj-$(CONFIG_MTD_MPC1211) += mpc1211.o
11257 +obj-$(CONFIG_MTD_IXP4XX) += ixp4xx.o
11258 +obj-$(CONFIG_MTD_IXP2000) += ixp2000.o
11259 +obj-$(CONFIG_MTD_WRSBC8260) += wr_sbc82xx_flash.o
11260 +obj-$(CONFIG_MTD_DMV182) += dmv182.o
11261 Index: linux-2.6.5/drivers/mtd/maps/amd76xrom.c
11262 ===================================================================
11263 --- linux-2.6.5.orig/drivers/mtd/maps/amd76xrom.c 2004-04-03 22:36:52.000000000 -0500
11264 +++ linux-2.6.5/drivers/mtd/maps/amd76xrom.c 2005-02-01 17:11:17.000000000 -0500
11268 * Normal mappings of chips in physical memory
11269 - * $Id: amd76xrom.c,v 1.8 2003/05/28 15:44:28 dwmw2 Exp $
11270 + * $Id: amd76xrom.c,v 1.16 2004/09/17 11:45:06 eric Exp $
11273 #include <linux/module.h>
11274 @@ -12,152 +12,265 @@
11275 #include <asm/io.h>
11276 #include <linux/mtd/mtd.h>
11277 #include <linux/mtd/map.h>
11278 +#include <linux/mtd/cfi.h>
11279 +#include <linux/mtd/flashchip.h>
11280 #include <linux/config.h>
11281 #include <linux/pci.h>
11282 #include <linux/pci_ids.h>
11283 +#include <linux/list.h>
11286 +#define xstr(s) str(s)
11288 +#define MOD_NAME xstr(KBUILD_BASENAME)
11290 +#define ADDRESS_NAME_LEN 18
11292 +#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
11294 +struct amd76xrom_window {
11295 + void __iomem *virt;
11296 + unsigned long phys;
11297 + unsigned long size;
11298 + struct list_head maps;
11299 + struct resource rsrc;
11300 + struct pci_dev *pdev;
11303 struct amd76xrom_map_info {
11304 + struct list_head list;
11305 struct map_info map;
11306 struct mtd_info *mtd;
11307 - unsigned long window_addr;
11308 - u32 window_start, window_size;
11309 - struct pci_dev *pdev;
11310 + struct resource rsrc;
11311 + char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
11315 -static struct amd76xrom_map_info amd76xrom_map = {
11317 - .name = "AMD76X rom",
11322 - .window_addr = 0,
11323 +static struct amd76xrom_window amd76xrom_window = {
11324 + .maps = LIST_HEAD_INIT(amd76xrom_window.maps),
11327 +static void amd76xrom_cleanup(struct amd76xrom_window *window)
11329 + struct amd76xrom_map_info *map, *scratch;
11332 + if (window->pdev) {
11333 + /* Disable writes through the rom window */
11334 + pci_read_config_byte(window->pdev, 0x40, &byte);
11335 + pci_write_config_byte(window->pdev, 0x40, byte & ~1);
11338 + /* Free all of the mtd devices */
11339 + list_for_each_entry_safe(map, scratch, &window->maps, list) {
11340 + if (map->rsrc.parent) {
11341 + release_resource(&map->rsrc);
11343 + del_mtd_device(map->mtd);
11344 + map_destroy(map->mtd);
11345 + list_del(&map->list);
11348 + if (window->rsrc.parent)
11349 + release_resource(&window->rsrc);
11351 + if (window->virt) {
11352 + iounmap(window->virt);
11353 + window->virt = NULL;
11354 + window->phys = 0;
11355 + window->size = 0;
11356 + window->pdev = NULL;
11361 static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
11362 const struct pci_device_id *ent)
11364 - struct rom_window {
11369 - static struct rom_window rom_window[] = {
11370 - { 0xffb00000, 5*1024*1024, (1<<7) | (1<<6), },
11371 - { 0xffc00000, 4*1024*1024, (1<<7), },
11372 - { 0xffff0000, 64*1024, 0 },
11375 - static const u32 rom_probe_sizes[] = {
11376 - 5*1024*1024, 4*1024*1024, 2*1024*1024, 1024*1024, 512*1024,
11377 - 256*1024, 128*1024, 64*1024, 0};
11378 - static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", 0 };
11379 + static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
11381 - struct amd76xrom_map_info *info = &amd76xrom_map;
11382 - struct rom_window *window;
11386 - window = &rom_window[0];
11388 - /* disabled because it fights with BIOS reserved regions */
11389 -#define REQUEST_MEM_REGION 0
11390 -#if REQUEST_MEM_REGION
11391 - while(window->size) {
11392 - if (request_mem_region(window->start, window->size, "amd76xrom")) {
11396 + struct amd76xrom_window *window = &amd76xrom_window;
11397 + struct amd76xrom_map_info *map = 0;
11398 + unsigned long map_top;
11400 + /* Remember the pci dev I find the window in */
11401 + window->pdev = pdev;
11403 + /* Assume the rom window is properly setup, and find it's size */
11404 + pci_read_config_byte(pdev, 0x43, &byte);
11405 + if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) {
11406 + window->phys = 0xffb00000; /* 5MiB */
11408 + else if ((byte & (1<<7)) == (1<<7)) {
11409 + window->phys = 0xffc00000; /* 4MiB */
11412 + window->phys = 0xffff0000; /* 64KiB */
11414 - if (!window->size) {
11415 - printk(KERN_ERR "amd76xrom: cannot reserve rom window\n");
11416 - goto err_out_none;
11417 + window->size = 0xffffffffUL - window->phys + 1UL;
11420 + * Try to reserve the window mem region. If this fails then
11421 + * it is likely due to a fragment of the window being
11422 + * "reseved" by the BIOS. In the case that the
11423 + * request_mem_region() fails then once the rom size is
11424 + * discovered we will try to reserve the unreserved fragment.
11426 + window->rsrc.name = MOD_NAME;
11427 + window->rsrc.start = window->phys;
11428 + window->rsrc.end = window->phys + window->size - 1;
11429 + window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
11430 + if (request_resource(&iomem_resource, &window->rsrc)) {
11431 + window->rsrc.parent = NULL;
11432 + printk(KERN_ERR MOD_NAME
11433 + " %s(): Unable to register resource"
11434 + " 0x%.08lx-0x%.08lx - kernel bug?\n",
11436 + window->rsrc.start, window->rsrc.end);
11438 -#endif /* REQUEST_MEM_REGION */
11442 /* Enable the selected rom window */
11443 pci_read_config_byte(pdev, 0x43, &byte);
11444 - pci_write_config_byte(pdev, 0x43, byte | window->segen_bits);
11445 + pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits);
11448 /* Enable writes through the rom window */
11449 pci_read_config_byte(pdev, 0x40, &byte);
11450 pci_write_config_byte(pdev, 0x40, byte | 1);
11453 /* FIXME handle registers 0x80 - 0x8C the bios region locks */
11455 - printk(KERN_NOTICE "amd76xrom window : %x at %x\n",
11456 - window->size, window->start);
11457 /* For write accesses caches are useless */
11458 - info->window_addr = (unsigned long)ioremap_nocache(window->start, window->size);
11459 + window->virt = ioremap_nocache(window->phys, window->size);
11460 + if (!window->virt) {
11461 + printk(KERN_ERR MOD_NAME ": Failed to ioremap\n");
11465 + /* Get the first address to look for an rom chip at */
11466 + map_top = window->phys;
11468 + /* The probe sequence run over the firmware hub lock
11469 + * registers sets them to 0x7 (no access).
11470 + * Probe at most the last 4M of the address space.
11472 + if (map_top < 0xffc00000) {
11473 + map_top = 0xffc00000;
11476 + /* Loop through and look for rom chips */
11477 + while((map_top - 1) < 0xffffffffUL) {
11478 + struct cfi_private *cfi;
11479 + unsigned long offset;
11482 - if (!info->window_addr) {
11483 - printk(KERN_ERR "Failed to ioremap\n");
11484 - goto err_out_free_mmio_region;
11487 - for(i = 0; (rom_size = rom_probe_sizes[i]); i++) {
11488 - char **chip_type;
11489 - if (rom_size > window->size) {
11492 - info->map.phys = window->start + window->size - rom_size;
11494 - info->window_addr + window->size - rom_size;
11495 - info->map.size = rom_size;
11496 - simple_map_init(&info->map);
11497 - chip_type = rom_probe_types;
11498 - for(; !info->mtd && *chip_type; chip_type++) {
11499 - info->mtd = do_map_probe(*chip_type, &amd76xrom_map.map);
11501 + map = kmalloc(sizeof(*map), GFP_KERNEL);
11506 + printk(KERN_ERR MOD_NAME ": kmalloc failed");
11509 + memset(map, 0, sizeof(*map));
11510 + INIT_LIST_HEAD(&map->list);
11511 + map->map.name = map->map_name;
11512 + map->map.phys = map_top;
11513 + offset = map_top - window->phys;
11514 + map->map.virt = (void __iomem *)
11515 + (((unsigned long)(window->virt)) + offset);
11516 + map->map.size = 0xffffffffUL - map_top + 1UL;
11517 + /* Set the name of the map to the address I am trying */
11518 + sprintf(map->map_name, "%s @%08lx",
11519 + MOD_NAME, map->map.phys);
11521 + /* There is no generic VPP support */
11522 + for(map->map.bankwidth = 32; map->map.bankwidth;
11523 + map->map.bankwidth >>= 1)
11525 + char **probe_type;
11526 + /* Skip bankwidths that are not supported */
11527 + if (!map_bankwidth_supported(map->map.bankwidth))
11530 + /* Setup the map methods */
11531 + simple_map_init(&map->map);
11533 + /* Try all of the probe methods */
11534 + probe_type = rom_probe_types;
11535 + for(; *probe_type; probe_type++) {
11536 + map->mtd = do_map_probe(*probe_type, &map->map);
11541 + map_top += ROM_PROBE_STEP_SIZE;
11544 + /* Trim the size if we are larger than the map */
11545 + if (map->mtd->size > map->map.size) {
11546 + printk(KERN_WARNING MOD_NAME
11547 + " rom(%u) larger than window(%lu). fixing...\n",
11548 + map->mtd->size, map->map.size);
11549 + map->mtd->size = map->map.size;
11551 + if (window->rsrc.parent) {
11553 + * Registering the MTD device in iomem may not be possible
11554 + * if there is a BIOS "reserved" and BUSY range. If this
11555 + * fails then continue anyway.
11557 + map->rsrc.name = map->map_name;
11558 + map->rsrc.start = map->map.phys;
11559 + map->rsrc.end = map->map.phys + map->mtd->size - 1;
11560 + map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
11561 + if (request_resource(&window->rsrc, &map->rsrc)) {
11562 + printk(KERN_ERR MOD_NAME
11563 + ": cannot reserve MTD resource\n");
11564 + map->rsrc.parent = NULL;
11568 + /* Make the whole region visible in the map */
11569 + map->map.virt = window->virt;
11570 + map->map.phys = window->phys;
11571 + cfi = map->map.fldrv_priv;
11572 + for(i = 0; i < cfi->numchips; i++) {
11573 + cfi->chips[i].start += offset;
11576 + /* Now that the mtd devices is complete claim and export it */
11577 + map->mtd->owner = THIS_MODULE;
11578 + add_mtd_device(map->mtd);
11581 + /* Calculate the new value of map_top */
11582 + map_top += map->mtd->size;
11584 + /* File away the map structure */
11585 + list_add(&map->list, &window->maps);
11588 - if (!info->mtd) {
11589 - goto err_out_iounmap;
11592 + /* Free any left over map structures */
11596 + /* See if I have any map structures */
11597 + if (list_empty(&window->maps)) {
11598 + amd76xrom_cleanup(window);
11601 - printk(KERN_NOTICE "amd76xrom chip at offset: 0x%x\n",
11602 - window->size - rom_size);
11604 - info->mtd->owner = THIS_MODULE;
11605 - add_mtd_device(info->mtd);
11606 - info->window_start = window->start;
11607 - info->window_size = window->size;
11611 - iounmap((void *)(info->window_addr));
11612 -err_out_free_mmio_region:
11613 -#if REQUEST_MEM_REGION
11614 - release_mem_region(window->start, window->size);
11616 -#endif /* REQUEST_MEM_REGION */
11621 static void __devexit amd76xrom_remove_one (struct pci_dev *pdev)
11623 - struct amd76xrom_map_info *info = &amd76xrom_map;
11626 - del_mtd_device(info->mtd);
11627 - map_destroy(info->mtd);
11629 - info->map.virt = 0;
11631 - iounmap((void *)(info->window_addr));
11632 - info->window_addr = 0;
11634 - /* Disable writes through the rom window */
11635 - pci_read_config_byte(pdev, 0x40, &byte);
11636 - pci_write_config_byte(pdev, 0x40, byte & ~1);
11637 + struct amd76xrom_window *window = &amd76xrom_window;
11639 -#if REQUEST_MEM_REGION
11640 - release_mem_region(info->window_start, info->window_size);
11641 -#endif /* REQUEST_MEM_REGION */
11642 + amd76xrom_cleanup(window);
11645 static struct pci_device_id amd76xrom_pci_tbl[] = {
11646 @@ -173,7 +286,7 @@
11649 static struct pci_driver amd76xrom_driver = {
11650 - .name = "amd76xrom",
11651 + .name = MOD_NAME,
11652 .id_table = amd76xrom_pci_tbl,
11653 .probe = amd76xrom_init_one,
11654 .remove = amd76xrom_remove_one,
11655 @@ -184,15 +297,14 @@
11657 struct pci_dev *pdev;
11658 struct pci_device_id *id;
11661 for(id = amd76xrom_pci_tbl; id->vendor; id++) {
11662 - pdev = pci_find_device(id->vendor, id->device, 0);
11663 + pdev = pci_find_device(id->vendor, id->device, NULL);
11669 - amd76xrom_map.pdev = pdev;
11670 return amd76xrom_init_one(pdev, &amd76xrom_pci_tbl[0]);
11673 @@ -203,7 +315,7 @@
11675 static void __exit cleanup_amd76xrom(void)
11677 - amd76xrom_remove_one(amd76xrom_map.pdev);
11678 + amd76xrom_remove_one(amd76xrom_window.pdev);
11681 module_init(init_amd76xrom);
11682 Index: linux-2.6.5/drivers/mtd/maps/arctic-mtd.c
11683 ===================================================================
11684 --- linux-2.6.5.orig/drivers/mtd/maps/arctic-mtd.c 2004-04-03 22:36:55.000000000 -0500
11685 +++ linux-2.6.5/drivers/mtd/maps/arctic-mtd.c 2005-02-01 17:11:17.000000000 -0500
11688 - * $Id: arctic-mtd.c,v 1.10 2003/06/02 16:37:59 trini Exp $
11689 + * $Id: arctic-mtd.c,v 1.12 2004/09/16 23:27:12 gleixner Exp $
11691 * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for
11692 * IBM 405LP Arctic boards.
11694 static struct map_info arctic_mtd_map = {
11697 - .buswidth = BUSWIDTH,
11698 + .bankwidth = BUSWIDTH,
11704 printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
11706 - arctic_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE);
11707 + arctic_mtd_map.virt = (void __iomem *) ioremap(PADDR, SIZE);
11709 if (!arctic_mtd_map.virt) {
11710 printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
11711 Index: linux-2.6.5/drivers/mtd/maps/autcpu12-nvram.c
11712 ===================================================================
11713 --- linux-2.6.5.orig/drivers/mtd/maps/autcpu12-nvram.c 2004-04-03 22:38:17.000000000 -0500
11714 +++ linux-2.6.5/drivers/mtd/maps/autcpu12-nvram.c 2005-02-01 17:11:17.000000000 -0500
11716 * NV-RAM memory access on autcpu12
11717 * (C) 2002 Thomas Gleixner (gleixner@autronix.de)
11719 - * $Id: autcpu12-nvram.c,v 1.5 2003/05/21 12:45:18 dwmw2 Exp $
11720 + * $Id: autcpu12-nvram.c,v 1.7 2004/09/16 23:27:12 gleixner Exp $
11722 * This program is free software; you can redistribute it and/or modify
11723 * it under the terms of the GNU General Public License as published by
11725 struct map_info autcpu12_sram_map = {
11730 .phys = 0x12000000,
11735 int err, save0, save1;
11737 - autcpu12_sram_map.virt = (unsigned long)ioremap(0x12000000, SZ_128K);
11738 + autcpu12_sram_map.virt = (void __iomem *)ioremap(0x12000000, SZ_128K);
11739 if (!autcpu12_sram_map.virt) {
11740 printk("Failed to ioremap autcpu12 NV-RAM space\n");
11743 /* We have a 128K found, restore 0x10000 and set size
11746 - ma[_write32(&autcpu12_sram_map,save1,0x10000);
11747 + map_write32(&autcpu12_sram_map,save1,0x10000);
11748 autcpu12_sram_map.size = SZ_128K;
11751 Index: linux-2.6.5/drivers/mtd/maps/beech-mtd.c
11752 ===================================================================
11753 --- linux-2.6.5.orig/drivers/mtd/maps/beech-mtd.c 2004-04-03 22:37:36.000000000 -0500
11754 +++ linux-2.6.5/drivers/mtd/maps/beech-mtd.c 2005-02-01 17:11:17.000000000 -0500
11757 - * $Id: beech-mtd.c,v 1.7 2003/05/21 12:45:18 dwmw2 Exp $
11758 + * $Id: beech-mtd.c,v 1.9 2004/09/16 23:27:12 gleixner Exp $
11760 * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for
11761 * IBM 405LP Beech boards.
11763 static struct map_info beech_mtd_map = {
11766 - .buswidth = BUSWIDTH,
11767 + .bankwidth = BUSWIDTH,
11773 printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
11775 - beech_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE);
11776 + beech_mtd_map.virt = (void __iomem *) ioremap(PADDR, SIZE);
11778 if (!beech_mtd_map.virt) {
11779 printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
11780 Index: linux-2.6.5/drivers/mtd/maps/cdb89712.c
11781 ===================================================================
11782 --- linux-2.6.5.orig/drivers/mtd/maps/cdb89712.c 2004-04-03 22:38:26.000000000 -0500
11783 +++ linux-2.6.5/drivers/mtd/maps/cdb89712.c 2005-02-01 17:11:17.000000000 -0500
11786 * Flash on Cirrus CDB89712
11788 - * $Id: cdb89712.c,v 1.7 2003/05/21 12:45:18 dwmw2 Exp $
11789 + * $Id: cdb89712.c,v 1.9 2004/09/16 23:27:12 gleixner Exp $
11792 #include <linux/module.h>
11794 struct map_info cdb89712_flash_map = {
11796 .size = FLASH_SIZE,
11797 - .buswidth = FLASH_WIDTH,
11798 + .bankwidth = FLASH_WIDTH,
11799 .phys = FLASH_START,
11806 - cdb89712_flash_map.virt = (unsigned long)ioremap(FLASH_START, FLASH_SIZE);
11807 + cdb89712_flash_map.virt = (void __iomem *)ioremap(FLASH_START, FLASH_SIZE);
11808 if (!cdb89712_flash_map.virt) {
11809 printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n");
11812 struct map_info cdb89712_sram_map = {
11815 - .buswidth = SRAM_WIDTH,
11816 + .bankwidth = SRAM_WIDTH,
11817 .phys = SRAM_START,
11820 @@ -114,7 +114,7 @@
11824 - cdb89712_sram_map.virt = (unsigned long)ioremap(SRAM_START, SRAM_SIZE);
11825 + cdb89712_sram_map.virt = (void __iomem *)ioremap(SRAM_START, SRAM_SIZE);
11826 if (!cdb89712_sram_map.virt) {
11827 printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n");
11829 @@ -161,7 +161,7 @@
11830 struct map_info cdb89712_bootrom_map = {
11832 .size = BOOTROM_SIZE,
11833 - .buswidth = BOOTROM_WIDTH,
11834 + .bankwidth = BOOTROM_WIDTH,
11835 .phys = BOOTROM_START,
11838 @@ -182,7 +182,7 @@
11842 - cdb89712_bootrom_map.virt = (unsigned long)ioremap(BOOTROM_START, BOOTROM_SIZE);
11843 + cdb89712_bootrom_map.virt = (void __iomem *)ioremap(BOOTROM_START, BOOTROM_SIZE);
11844 if (!cdb89712_bootrom_map.virt) {
11845 printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n");
11847 Index: linux-2.6.5/drivers/mtd/maps/ceiva.c
11848 ===================================================================
11849 --- linux-2.6.5.orig/drivers/mtd/maps/ceiva.c 2004-04-03 22:36:55.000000000 -0500
11850 +++ linux-2.6.5/drivers/mtd/maps/ceiva.c 2005-02-01 17:11:17.000000000 -0500
11853 * (C) 2000 Nicolas Pitre <nico@cam.org>
11855 - * $Id: ceiva.c,v 1.8 2003/05/21 12:45:18 dwmw2 Exp $
11856 + * $Id: ceiva.c,v 1.11 2004/09/16 23:27:12 gleixner Exp $
11859 #include <linux/config.h>
11860 @@ -150,8 +150,8 @@
11864 - clps[i].map->virt = (unsigned long)clps[i].vbase;
11865 - clps[i].map->buswidth = clps[i].width;
11866 + clps[i].map->virt = (void __iomem *)clps[i].vbase;
11867 + clps[i].map->bankwidth = clps[i].width;
11868 clps[i].map->size = clps[i].size;
11870 simple_map_init(&clps[i].map);
11871 Index: linux-2.6.5/drivers/mtd/maps/cfi_flagadm.c
11872 ===================================================================
11873 --- linux-2.6.5.orig/drivers/mtd/maps/cfi_flagadm.c 2004-04-03 22:36:13.000000000 -0500
11874 +++ linux-2.6.5/drivers/mtd/maps/cfi_flagadm.c 2005-02-01 17:11:17.000000000 -0500
11877 * Copyright © 2001 Flaga hf. Medical Devices, Kári DavÃðsson <kd@flaga.is>
11879 - * $Id: cfi_flagadm.c,v 1.11 2003/05/21 12:45:18 dwmw2 Exp $
11880 + * $Id: cfi_flagadm.c,v 1.13 2004/09/16 23:27:12 gleixner Exp $
11882 * This program is free software; you can redistribute it and/or modify it
11883 * under the terms of the GNU General Public License as published by the
11885 struct map_info flagadm_map = {
11886 .name = "FlagaDM flash device",
11887 .size = FLASH_SIZE,
11892 struct mtd_partition flagadm_parts[] = {
11894 FLASH_SIZE, FLASH_PHYS_ADDR);
11896 flagadm_map.phys = FLASH_PHYS_ADDR;
11897 - flagadm_map.virt = (unsigned long)ioremap(FLASH_PHYS_ADDR,
11898 + flagadm_map.virt = (void __iomem *s)ioremap(FLASH_PHYS_ADDR,
11901 if (!flagadm_map.virt) {
11902 Index: linux-2.6.5/drivers/mtd/maps/cstm_mips_ixx.c
11903 ===================================================================
11904 --- linux-2.6.5.orig/drivers/mtd/maps/cstm_mips_ixx.c 2004-04-03 22:36:25.000000000 -0500
11905 +++ linux-2.6.5/drivers/mtd/maps/cstm_mips_ixx.c 2005-02-01 17:11:17.000000000 -0500
11908 - * $Id: cstm_mips_ixx.c,v 1.9 2003/05/21 12:45:18 dwmw2 Exp $
11909 + * $Id: cstm_mips_ixx.c,v 1.11 2004/09/16 23:27:12 gleixner Exp $
11911 * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions.
11912 * Config with both CFI and JEDEC device support.
11913 @@ -104,7 +104,7 @@
11915 unsigned long window_addr;
11916 unsigned long window_size;
11919 int num_partitions;
11922 @@ -116,7 +116,7 @@
11923 "big flash", // name
11924 0x08000000, // window_addr
11925 0x02000000, // window_size
11928 1, // num_partitions
11931 @@ -138,7 +138,7 @@
11932 "MTD flash", // name
11933 CONFIG_MTD_CSTM_MIPS_IXX_START, // window_addr
11934 CONFIG_MTD_CSTM_MIPS_IXX_LEN, // window_size
11935 - CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH, // buswidth
11936 + CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH, // bankwidth
11937 1, // num_partitions
11940 @@ -170,14 +170,14 @@
11943 cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr;
11944 - cstm_mips_ixx_map[i].virt = (unsigned long)ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size);
11945 + cstm_mips_ixx_map[i].virt = (void __iomem *)ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size);
11946 if (!cstm_mips_ixx_map[i].virt) {
11947 printk(KERN_WARNING "Failed to ioremap\n");
11950 cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name;
11951 cstm_mips_ixx_map[i].size = cstm_mips_ixx_board_desc[i].window_size;
11952 - cstm_mips_ixx_map[i].buswidth = cstm_mips_ixx_board_desc[i].buswidth;
11953 + cstm_mips_ixx_map[i].bankwidth = cstm_mips_ixx_board_desc[i].bankwidth;
11954 #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
11955 cstm_mips_ixx_map[i].set_vpp = cstm_mips_ixx_set_vpp;
11957 Index: linux-2.6.5/drivers/mtd/maps/db1550-flash.c
11958 ===================================================================
11959 --- linux-2.6.5.orig/drivers/mtd/maps/db1550-flash.c 1969-12-31 19:00:00.000000000 -0500
11960 +++ linux-2.6.5/drivers/mtd/maps/db1550-flash.c 2005-02-01 17:11:17.000000000 -0500
11963 + * Flash memory access on Alchemy Db1550 board
11965 + * $Id: db1550-flash.c,v 1.4 2004/09/16 23:27:12 gleixner Exp $
11967 + * (C) 2004 Embedded Edge, LLC, based on db1550-flash.c:
11968 + * (C) 2003 Pete Popov <pete_popov@yahoo.com>
11972 +#include <linux/config.h>
11973 +#include <linux/init.h>
11974 +#include <linux/module.h>
11975 +#include <linux/types.h>
11976 +#include <linux/kernel.h>
11978 +#include <linux/mtd/mtd.h>
11979 +#include <linux/mtd/map.h>
11980 +#include <linux/mtd/partitions.h>
11982 +#include <asm/io.h>
11983 +#include <asm/au1000.h>
11986 +#define DBG(x...) printk(x)
11991 +static unsigned long window_addr;
11992 +static unsigned long window_size;
11995 +static struct map_info db1550_map = {
11996 + .name = "Db1550 flash",
11999 +static unsigned char flash_bankwidth = 4;
12002 + * Support only 64MB NOR Flash parts
12005 +#if defined(CONFIG_MTD_DB1550_BOOT) && defined(CONFIG_MTD_DB1550_USER)
12006 +#define DB1550_BOTH_BANKS
12007 +#elif defined(CONFIG_MTD_DB1550_BOOT) && !defined(CONFIG_MTD_DB1550_USER)
12008 +#define DB1550_BOOT_ONLY
12009 +#elif !defined(CONFIG_MTD_DB1550_BOOT) && defined(CONFIG_MTD_DB1550_USER)
12010 +#define DB1550_USER_ONLY
12013 +#ifdef DB1550_BOTH_BANKS
12014 +/* both banks will be used. Combine the first bank and the first
12015 + * part of the second bank together into a single jffs/jffs2
12018 +static struct mtd_partition db1550_partitions[] = {
12019 + /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
12020 + * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
12021 + * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
12024 + .name = "User FS",
12025 + .size = (0x1FC00000 - 0x18000000),
12026 + .offset = 0x0000000
12029 + .size = 0x0100000,
12030 + .offset = MTDPART_OFS_APPEND,
12031 + .mask_flags = MTD_WRITEABLE
12033 + .name = "raw kernel",
12034 + .size = (0x300000 - 0x40000), /* last 256KB is yamon env */
12035 + .offset = MTDPART_OFS_APPEND,
12038 +#elif defined(DB1550_BOOT_ONLY)
12039 +static struct mtd_partition db1550_partitions[] = {
12040 + /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
12041 + * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
12044 + .name = "User FS",
12045 + .size = 0x03c00000,
12046 + .offset = 0x0000000
12049 + .size = 0x0100000,
12050 + .offset = MTDPART_OFS_APPEND,
12051 + .mask_flags = MTD_WRITEABLE
12053 + .name = "raw kernel",
12054 + .size = (0x300000-0x40000), /* last 256KB is yamon env */
12055 + .offset = MTDPART_OFS_APPEND,
12058 +#elif defined(DB1550_USER_ONLY)
12059 +static struct mtd_partition db1550_partitions[] = {
12060 + /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
12061 + * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
12064 + .name = "User FS",
12065 + .size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */
12066 + .offset = 0x0000000
12068 + .name = "raw kernel",
12069 + .size = MTDPART_SIZ_FULL,
12070 + .offset = MTDPART_OFS_APPEND,
12074 +#error MTD_DB1550 define combo error /* should never happen */
12077 +#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
12079 +static struct mtd_info *mymtd;
12082 + * Probe the flash density and setup window address and size
12083 + * based on user CONFIG options. There are times when we don't
12084 + * want the MTD driver to be probing the boot or user flash,
12085 + * so having the option to enable only one bank is important.
12087 +int setup_flash_params(void)
12089 +#if defined(DB1550_BOTH_BANKS)
12090 + window_addr = 0x18000000;
12091 + window_size = 0x8000000;
12092 +#elif defined(DB1550_BOOT_ONLY)
12093 + window_addr = 0x1C000000;
12094 + window_size = 0x4000000;
12095 +#else /* USER ONLY */
12096 + window_addr = 0x1E000000;
12097 + window_size = 0x4000000;
12102 +int __init db1550_mtd_init(void)
12104 + struct mtd_partition *parts;
12105 + int nb_parts = 0;
12107 + /* Default flash bankwidth */
12108 + db1550_map.bankwidth = flash_bankwidth;
12110 + if (setup_flash_params())
12114 + * Static partition definition selection
12116 + parts = db1550_partitions;
12117 + nb_parts = NB_OF(db1550_partitions);
12118 + db1550_map.size = window_size;
12121 + * Now let's probe for the actual flash. Do it here since
12122 + * specific machine settings might have been set above.
12124 + printk(KERN_NOTICE "Pb1550 flash: probing %d-bit flash bus\n",
12125 + db1550_map.bankwidth*8);
12126 + db1550_map.virt =
12127 + (void __iomem *)ioremap(window_addr, window_size);
12128 + mymtd = do_map_probe("cfi_probe", &db1550_map);
12129 + if (!mymtd) return -ENXIO;
12130 + mymtd->owner = THIS_MODULE;
12132 + add_mtd_partitions(mymtd, parts, nb_parts);
12136 +static void __exit db1550_mtd_cleanup(void)
12139 + del_mtd_partitions(mymtd);
12140 + map_destroy(mymtd);
12144 +module_init(db1550_mtd_init);
12145 +module_exit(db1550_mtd_cleanup);
12147 +MODULE_AUTHOR("Embedded Edge, LLC");
12148 +MODULE_DESCRIPTION("Db1550 mtd map driver");
12149 +MODULE_LICENSE("GPL");
12150 Index: linux-2.6.5/drivers/mtd/maps/db1x00-flash.c
12151 ===================================================================
12152 --- linux-2.6.5.orig/drivers/mtd/maps/db1x00-flash.c 1969-12-31 19:00:00.000000000 -0500
12153 +++ linux-2.6.5/drivers/mtd/maps/db1x00-flash.c 2005-02-01 17:11:17.000000000 -0500
12156 + * Flash memory access on Alchemy Db1xxx boards
12158 + * $Id: db1x00-flash.c,v 1.4 2004/09/16 23:27:12 gleixner Exp $
12160 + * (C) 2003 Pete Popov <ppopov@pacbell.net>
12164 +#include <linux/config.h>
12165 +#include <linux/module.h>
12166 +#include <linux/types.h>
12167 +#include <linux/init.h>
12168 +#include <linux/kernel.h>
12170 +#include <linux/mtd/mtd.h>
12171 +#include <linux/mtd/map.h>
12172 +#include <linux/mtd/partitions.h>
12174 +#include <asm/io.h>
12175 +#include <asm/au1000.h>
12176 +#include <asm/db1x00.h>
12179 +#define DBG(x...) printk(x)
12184 +static unsigned long window_addr;
12185 +static unsigned long window_size;
12186 +static unsigned long flash_size;
12188 +static BCSR * const bcsr = (BCSR *)0xAE000000;
12189 +static unsigned char flash_bankwidth = 4;
12192 + * The Db1x boards support different flash densities. We setup
12193 + * the mtd_partition structures below for default of 64Mbit
12194 + * flash densities, and override the partitions sizes, if
12195 + * necessary, after we check the board status register.
12198 +#ifdef DB1X00_BOTH_BANKS
12199 +/* both banks will be used. Combine the first bank and the first
12200 + * part of the second bank together into a single jffs/jffs2
12203 +static struct mtd_partition db1x00_partitions[] = {
12205 + .name = "User FS",
12206 + .size = 0x1c00000,
12207 + .offset = 0x0000000
12210 + .size = 0x0100000,
12211 + .offset = MTDPART_OFS_APPEND,
12212 + .mask_flags = MTD_WRITEABLE
12214 + .name = "raw kernel",
12215 + .size = (0x300000-0x40000), /* last 256KB is env */
12216 + .offset = MTDPART_OFS_APPEND,
12219 +#elif defined(DB1X00_BOOT_ONLY)
12220 +static struct mtd_partition db1x00_partitions[] = {
12222 + .name = "User FS",
12223 + .size = 0x00c00000,
12224 + .offset = 0x0000000
12227 + .size = 0x0100000,
12228 + .offset = MTDPART_OFS_APPEND,
12229 + .mask_flags = MTD_WRITEABLE
12231 + .name = "raw kernel",
12232 + .size = (0x300000-0x40000), /* last 256KB is env */
12233 + .offset = MTDPART_OFS_APPEND,
12236 +#elif defined(DB1X00_USER_ONLY)
12237 +static struct mtd_partition db1x00_partitions[] = {
12239 + .name = "User FS",
12240 + .size = 0x0e00000,
12241 + .offset = 0x0000000
12243 + .name = "raw kernel",
12244 + .size = MTDPART_SIZ_FULL,
12245 + .offset = MTDPART_OFS_APPEND,
12249 +#error MTD_DB1X00 define combo error /* should never happen */
12251 +#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
12253 +#define NAME "Db1x00 Linux Flash"
12255 +static struct map_info db1xxx_mtd_map = {
12259 +static struct mtd_partition *parsed_parts;
12260 +static struct mtd_info *db1xxx_mtd;
12263 + * Probe the flash density and setup window address and size
12264 + * based on user CONFIG options. There are times when we don't
12265 + * want the MTD driver to be probing the boot or user flash,
12266 + * so having the option to enable only one bank is important.
12268 +int setup_flash_params(void)
12270 + switch ((bcsr->status >> 14) & 0x3) {
12271 + case 0: /* 64Mbit devices */
12272 + flash_size = 0x800000; /* 8MB per part */
12273 +#if defined(DB1X00_BOTH_BANKS)
12274 + window_addr = 0x1E000000;
12275 + window_size = 0x2000000;
12276 +#elif defined(DB1X00_BOOT_ONLY)
12277 + window_addr = 0x1F000000;
12278 + window_size = 0x1000000;
12279 +#else /* USER ONLY */
12280 + window_addr = 0x1E000000;
12281 + window_size = 0x1000000;
12285 + /* 128 Mbit devices */
12286 + flash_size = 0x1000000; /* 16MB per part */
12287 +#if defined(DB1X00_BOTH_BANKS)
12288 + window_addr = 0x1C000000;
12289 + window_size = 0x4000000;
12290 + /* USERFS from 0x1C00 0000 to 0x1FC0 0000 */
12291 + db1x00_partitions[0].size = 0x3C00000;
12292 +#elif defined(DB1X00_BOOT_ONLY)
12293 + window_addr = 0x1E000000;
12294 + window_size = 0x2000000;
12295 + /* USERFS from 0x1E00 0000 to 0x1FC0 0000 */
12296 + db1x00_partitions[0].size = 0x1C00000;
12297 +#else /* USER ONLY */
12298 + window_addr = 0x1C000000;
12299 + window_size = 0x2000000;
12300 + /* USERFS from 0x1C00 0000 to 0x1DE00000 */
12301 + db1x00_partitions[0].size = 0x1DE0000;
12305 + /* 256 Mbit devices */
12306 + flash_size = 0x4000000; /* 64MB per part */
12307 +#if defined(DB1X00_BOTH_BANKS)
12309 +#elif defined(DB1X00_BOOT_ONLY)
12310 + /* Boot ROM flash bank only; no user bank */
12311 + window_addr = 0x1C000000;
12312 + window_size = 0x4000000;
12313 + /* USERFS from 0x1C00 0000 to 0x1FC00000 */
12314 + db1x00_partitions[0].size = 0x3C00000;
12315 +#else /* USER ONLY */
12322 + db1xxx_mtd_map.size = window_size;
12323 + db1xxx_mtd_map.bankwidth = flash_bankwidth;
12324 + db1xxx_mtd_map.phys = window_addr;
12325 + db1xxx_mtd_map.bankwidth = flash_bankwidth;
12329 +int __init db1x00_mtd_init(void)
12331 + struct mtd_partition *parts;
12332 + int nb_parts = 0;
12334 + if (setup_flash_params())
12338 + * Static partition definition selection
12340 + parts = db1x00_partitions;
12341 + nb_parts = NB_OF(db1x00_partitions);
12344 + * Now let's probe for the actual flash. Do it here since
12345 + * specific machine settings might have been set above.
12347 + printk(KERN_NOTICE "Db1xxx flash: probing %d-bit flash bus\n",
12348 + db1xxx_mtd_map.bankwidth*8);
12349 + db1xxx_mtd_map.virt = (void __iomem *)ioremap(window_addr, window_size);
12350 + db1xxx_mtd = do_map_probe("cfi_probe", &db1xxx_mtd_map);
12351 + if (!db1xxx_mtd) return -ENXIO;
12352 + db1xxx_mtd->owner = THIS_MODULE;
12354 + add_mtd_partitions(db1xxx_mtd, parts, nb_parts);
12358 +static void __exit db1x00_mtd_cleanup(void)
12360 + if (db1xxx_mtd) {
12361 + del_mtd_partitions(db1xxx_mtd);
12362 + map_destroy(db1xxx_mtd);
12363 + if (parsed_parts)
12364 + kfree(parsed_parts);
12368 +module_init(db1x00_mtd_init);
12369 +module_exit(db1x00_mtd_cleanup);
12371 +MODULE_AUTHOR("Pete Popov");
12372 +MODULE_DESCRIPTION("Db1x00 mtd map driver");
12373 +MODULE_LICENSE("GPL");
12374 Index: linux-2.6.5/drivers/mtd/maps/dbox2-flash.c
12375 ===================================================================
12376 --- linux-2.6.5.orig/drivers/mtd/maps/dbox2-flash.c 2004-04-03 22:38:21.000000000 -0500
12377 +++ linux-2.6.5/drivers/mtd/maps/dbox2-flash.c 2005-02-01 17:11:17.000000000 -0500
12380 - * $Id: dbox2-flash.c,v 1.9 2003/05/21 12:45:18 dwmw2 Exp $
12381 + * $Id: dbox2-flash.c,v 1.12 2004/09/16 23:27:12 gleixner Exp $
12383 * D-Box 2 flash driver
12386 #include <linux/mtd/map.h>
12387 #include <linux/mtd/partitions.h>
12388 #include <linux/config.h>
12389 +#include <linux/errno.h>
12391 /* partition_info gives details on the logical partitions that the split the
12392 * single flash device into. If the size if zero we use up to the end of the
12393 @@ -25,31 +26,31 @@
12394 .mask_flags = MTD_WRITEABLE
12397 - .name = "flfs (ppcboot)",
12398 + .name = "FLFS (U-Boot)",
12399 .size = 128 * 1024,
12400 .offset = MTDPART_OFS_APPEND,
12404 - .name = "root (cramfs)",
12405 + .name = "Root (SquashFS)",
12406 .size = 7040 * 1024,
12407 .offset = MTDPART_OFS_APPEND,
12411 - .name = "var (jffs2)",
12412 + .name = "var (JFFS2)",
12413 .size = 896 * 1024,
12414 .offset = MTDPART_OFS_APPEND,
12418 - .name = "flash without bootloader",
12419 + .name = "Flash without bootloader",
12420 .size = MTDPART_SIZ_FULL,
12421 .offset = 128 * 1024,
12425 - .name = "complete flash",
12426 + .name = "Complete Flash",
12427 .size = MTDPART_SIZ_FULL,
12429 .mask_flags = MTD_WRITEABLE
12430 @@ -67,14 +68,14 @@
12431 struct map_info dbox2_flash_map = {
12432 .name = "D-Box 2 flash memory",
12433 .size = WINDOW_SIZE,
12436 .phys = WINDOW_ADDR,
12439 int __init init_dbox2_flash(void)
12441 printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR);
12442 - dbox2_flash_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
12443 + dbox2_flash_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE);
12445 if (!dbox2_flash_map.virt) {
12446 printk("Failed to ioremap\n");
12448 mymtd = do_map_probe("cfi_probe", &dbox2_flash_map);
12450 // Probe for single Intel 28F640
12451 - dbox2_flash_map.buswidth = 2;
12452 + dbox2_flash_map.bankwidth = 2;
12454 mymtd = do_map_probe("cfi_probe", &dbox2_flash_map);
12456 Index: linux-2.6.5/drivers/mtd/maps/dc21285.c
12457 ===================================================================
12458 --- linux-2.6.5.orig/drivers/mtd/maps/dc21285.c 2004-04-03 22:36:57.000000000 -0500
12459 +++ linux-2.6.5/drivers/mtd/maps/dc21285.c 2005-02-01 17:11:17.000000000 -0500
12464 - * $Id: dc21285.c,v 1.15 2003/05/21 12:45:18 dwmw2 Exp $
12465 + * $Id: dc21285.c,v 1.21 2004/09/16 23:27:13 gleixner Exp $
12467 #include <linux/config.h>
12468 #include <linux/module.h>
12469 #include <linux/types.h>
12470 #include <linux/kernel.h>
12471 #include <linux/init.h>
12472 +#include <linux/delay.h>
12474 #include <linux/mtd/mtd.h>
12475 #include <linux/mtd/map.h>
12476 @@ -19,91 +20,117 @@
12478 #include <asm/io.h>
12479 #include <asm/hardware/dec21285.h>
12480 +#include <asm/mach-types.h>
12483 -static struct mtd_info *mymtd;
12484 +static struct mtd_info *dc21285_mtd;
12486 -__u8 dc21285_read8(struct map_info *map, unsigned long ofs)
12487 +#ifdef CONFIG_ARCH_NETWINDER
12489 + * This is really ugly, but it seams to be the only
12490 + * realiable way to do it, as the cpld state machine
12491 + * is unpredictible. So we have a 25us penalty per
12494 +static void nw_en_write(void) {
12495 + extern spinlock_t gpio_lock;
12496 + unsigned long flags;
12499 + * we want to write a bit pattern XXX1 to Xilinx to enable
12500 + * the write gate, which will be open for about the next 2ms.
12502 + spin_lock_irqsave(&gpio_lock, flags);
12503 + cpld_modify(1, 1);
12504 + spin_unlock_irqrestore(&gpio_lock, flags);
12507 + * let the ISA bus to catch on...
12512 +#define nw_en_write() do { } while (0)
12515 +static map_word dc21285_read8(struct map_info *map, unsigned long ofs)
12517 - return *(__u8*)(map->map_priv_1 + ofs);
12518 + return *(uint8_t*)(map->map_priv_1 + ofs);
12521 -__u16 dc21285_read16(struct map_info *map, unsigned long ofs)
12522 +static map_word dc21285_read16(struct map_info *map, unsigned long ofs)
12524 - return *(__u16*)(map->map_priv_1 + ofs);
12525 + return *(uint16_t*)(map->map_priv_1 + ofs);
12528 -__u32 dc21285_read32(struct map_info *map, unsigned long ofs)
12529 +static map_word dc21285_read32(struct map_info *map, unsigned long ofs)
12531 - return *(__u32*)(map->map_priv_1 + ofs);
12532 + return *(uint32_t*)(map->map_priv_1 + ofs);
12535 -void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
12536 +static void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
12538 memcpy(to, (void*)(map->map_priv_1 + from), len);
12541 -void dc21285_write8(struct map_info *map, __u8 d, unsigned long adr)
12542 +static void dc21285_write(struct map_info *map, map_word d, unsigned long adr)
12544 + if (machine_is_netwinder())
12546 *CSR_ROMWRITEREG = adr & 3;
12548 - *(__u8*)(map->map_priv_1 + adr) = d;
12549 + *(uint8_t*)(map->map_priv_1 + adr) = d.x[0];
12552 -void dc21285_write16(struct map_info *map, __u16 d, unsigned long adr)
12553 +static void dc21285_write16(struct map_info *map, map_word d, unsigned long adr)
12555 + if (machine_is_netwinder())
12557 *CSR_ROMWRITEREG = adr & 3;
12559 - *(__u16*)(map->map_priv_1 + adr) = d;
12560 + *(uint16_t*)(map->map_priv_1 + adr) = d.x[0];
12563 -void dc21285_write32(struct map_info *map, __u32 d, unsigned long adr)
12564 +static void dc21285_write32(struct map_info *map, map_word d, unsigned long adr)
12566 - *(__u32*)(map->map_priv_1 + adr) = d;
12567 + if (machine_is_netwinder())
12569 + *(uint32_t*)(map->map_priv_1 + adr) = d.x[0];
12572 -void dc21285_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
12573 +static void dc21285_copy_to_32(struct map_info *map, unsigned long to, const void *from, ssize_t len)
12575 - switch (map->buswidth) {
12577 - while (len > 0) {
12578 - __u32 d = *((__u32*)from)++;
12579 - dc21285_write32(map, d, to);
12585 - while (len > 0) {
12586 - __u16 d = *((__u16*)from)++;
12587 - dc21285_write16(map, d, to);
12593 - while (len > 0) {
12594 - __u8 d = *((__u8*)from)++;
12595 - dc21285_write8(map, d, to);
12600 + while (len > 0) {
12601 + uint32_t d = *((uint32_t*)from)++;
12602 + dc21285_write32(map, d, to);
12608 +static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const void *from, ssize_t len)
12610 + while (len > 0) {
12611 + uint16_t d = *((uint16_t*)from)++;
12612 + dc21285_write16(map, d, to);
12618 -struct map_info dc21285_map = {
12619 +static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len)
12621 + uint8_t d = *((uint8_t*)from)++;
12622 + dc21285_write8(map, d, to);
12627 +static struct map_info dc21285_map = {
12628 .name = "DC21285 flash",
12630 .size = 16*1024*1024,
12631 - .read8 = dc21285_read8,
12632 - .read16 = dc21285_read16,
12633 - .read32 = dc21285_read32,
12634 .copy_from = dc21285_copy_from,
12635 - .write8 = dc21285_write8,
12636 - .write16 = dc21285_write16,
12637 - .write32 = dc21285_write32,
12638 - .copy_to = dc21285_copy_to
12642 @@ -113,81 +140,97 @@
12643 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
12646 -int __init init_dc21285(void)
12647 +static int __init init_dc21285(void)
12651 - * Flash timing is determined with bits 19-16 of the
12652 - * CSR_SA110_CNTL. The value is the number of wait cycles, or
12653 - * 0 for 16 cycles (the default). Cycles are 20 ns.
12654 - * Here we use 7 for 140 ns flash chips.
12656 - /* access time */
12657 - *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16));
12659 - *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20));
12660 - /* tristate time */
12661 - *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24));
12662 +#ifdef CONFIG_MTD_PARTITIONS
12666 - /* Determine buswidth */
12667 + /* Determine bankwidth */
12668 switch (*CSR_SA110_CNTL & (3<<14)) {
12669 case SA110_CNTL_ROMWIDTH_8:
12670 - dc21285_map.buswidth = 1;
12671 + dc21285_map.bankwidth = 1;
12672 + dc21285_map.read = dc21285_read8;
12673 + dc21285_map.write = dc21285_write8;
12674 + dc21285_map.copy_to = dc21285_copy_to_8;
12676 case SA110_CNTL_ROMWIDTH_16:
12677 - dc21285_map.buswidth = 2;
12678 + dc21285_map.bankwidth = 2;
12679 + dc21285_map.read = dc21285_read16;
12680 + dc21285_map.write = dc21285_write16;
12681 + dc21285_map.copy_to = dc21285_copy_to_16;
12683 case SA110_CNTL_ROMWIDTH_32:
12684 - dc21285_map.buswidth = 4;
12685 + dc21285_map.bankwidth = 4;
12687 + dc21285_map.read = dc21285_read32;
12688 + dc21285_map.write = dc21285_write32;
12689 + dc21285_map.copy_to = dc21285_copy_to_32;
12691 - printk (KERN_ERR "DC21285 flash: undefined buswidth\n");
12692 + printk (KERN_ERR "DC21285 flash: undefined bankwidth\n");
12695 - printk (KERN_NOTICE "DC21285 flash support (%d-bit buswidth)\n",
12696 - dc21285_map.buswidth*8);
12697 + printk (KERN_NOTICE "DC21285 flash support (%d-bit bankwidth)\n",
12698 + dc21285_map.bankwidth*8);
12700 /* Let's map the flash area */
12701 - dc21285_map.map_priv_1 = (unsigned long)ioremap(DC21285_FLASH, 16*1024*1024);
12702 + dc21285_map.map_priv_1 = (void __iomem *)ioremap(DC21285_FLASH, 16*1024*1024);
12703 if (!dc21285_map.map_priv_1) {
12704 printk("Failed to ioremap\n");
12708 - mymtd = do_map_probe("cfi_probe", &dc21285_map);
12711 + if (machine_is_ebsa285()) {
12712 + dc21285_mtd = do_map_probe("cfi_probe", &dc21285_map);
12714 + dc21285_mtd = do_map_probe("jedec_probe", &dc21285_map);
12717 - mymtd->owner = THIS_MODULE;
12719 - /* partition fixup */
12720 + if (!dc21285_mtd) {
12721 + iounmap((void *)dc21285_map.map_priv_1);
12725 + dc21285_mtd->owner = THIS_MODULE;
12727 #ifdef CONFIG_MTD_PARTITIONS
12728 - nrparts = parse_mtd_partitions(mymtd, probes, &dc21285_parts, (void *)0);
12729 - if (nrparts > 0) {
12730 - add_mtd_partitions(mymtd, dc21285_parts, nrparts);
12734 - add_mtd_device(mymtd);
12736 + nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, (void *)0);
12738 + add_mtd_partitions(dc21285_mtd, dc21285_parts, nrparts);
12741 + add_mtd_device(dc21285_mtd);
12743 + if(machine_is_ebsa285()) {
12745 + * Flash timing is determined with bits 19-16 of the
12746 + * CSR_SA110_CNTL. The value is the number of wait cycles, or
12747 + * 0 for 16 cycles (the default). Cycles are 20 ns.
12748 + * Here we use 7 for 140 ns flash chips.
12750 + /* access time */
12751 + *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16));
12753 + *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20));
12754 + /* tristate time */
12755 + *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24));
12758 - iounmap((void *)dc21285_map.map_priv_1);
12764 static void __exit cleanup_dc21285(void)
12766 #ifdef CONFIG_MTD_PARTITIONS
12767 if (dc21285_parts) {
12768 - del_mtd_partitions(mymtd);
12769 + del_mtd_partitions(dc21285_mtd);
12770 kfree(dc21285_parts);
12773 - del_mtd_device(mymtd);
12774 + del_mtd_device(dc21285_mtd);
12776 - map_destroy(mymtd);
12777 + map_destroy(dc21285_mtd);
12778 iounmap((void *)dc21285_map.map_priv_1);
12781 Index: linux-2.6.5/drivers/mtd/maps/dilnetpc.c
12782 ===================================================================
12783 --- linux-2.6.5.orig/drivers/mtd/maps/dilnetpc.c 2004-04-03 22:36:26.000000000 -0500
12784 +++ linux-2.6.5/drivers/mtd/maps/dilnetpc.c 2005-02-01 17:11:17.000000000 -0500
12786 * along with this program; if not, write to the Free Software
12787 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
12789 - * $Id: dilnetpc.c,v 1.12 2003/05/21 12:45:18 dwmw2 Exp $
12790 + * $Id: dilnetpc.c,v 1.14 2004/09/16 23:27:13 gleixner Exp $
12792 * The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems
12793 * featuring the AMD Elan SC410 processor. There are two variants of this
12794 @@ -252,7 +252,7 @@
12795 static struct map_info dnpc_map = {
12796 .name = "ADNP Flash Bank",
12797 .size = ADNP_WINDOW_SIZE,
12800 .set_vpp = adnp_set_vpp,
12801 .phys = WINDOW_ADDR
12803 @@ -403,7 +403,7 @@
12804 printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n",
12805 is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys);
12807 - dnpc_map.virt = (unsigned long)ioremap_nocache(dnpc_map.phys, dnpc_map.size);
12808 + dnpc_map.virt = (void __iomem *)ioremap_nocache(dnpc_map.phys, dnpc_map.size);
12810 dnpc_map_flash(dnpc_map.phys, dnpc_map.size);
12812 Index: linux-2.6.5/drivers/mtd/maps/dmv182.c
12813 ===================================================================
12814 --- linux-2.6.5.orig/drivers/mtd/maps/dmv182.c 1969-12-31 19:00:00.000000000 -0500
12815 +++ linux-2.6.5/drivers/mtd/maps/dmv182.c 2005-02-01 17:11:17.000000000 -0500
12819 + * drivers/mtd/maps/svme182.c
12821 + * Flash map driver for the Dy4 SVME182 board
12823 + * $Id: dmv182.c,v 1.4 2004/09/16 23:27:13 gleixner Exp $
12825 + * Copyright 2003-2004, TimeSys Corporation
12827 + * Based on the SVME181 flash map, by Tom Nelson, Dot4, Inc. for TimeSys Corp.
12829 + * This program is free software; you can redistribute it and/or modify it
12830 + * under the terms of the GNU General Public License as published by the
12831 + * Free Software Foundation; either version 2 of the License, or (at your
12832 + * option) any later version.
12835 +#include <linux/config.h>
12836 +#include <linux/module.h>
12837 +#include <linux/init.h>
12838 +#include <linux/types.h>
12839 +#include <linux/kernel.h>
12840 +#include <asm/io.h>
12841 +#include <linux/mtd/mtd.h>
12842 +#include <linux/mtd/map.h>
12843 +#include <linux/mtd/partitions.h>
12844 +#include <linux/errno.h>
12847 + * This driver currently handles only the 16MiB user flash bank 1 on the
12848 + * board. It does not provide access to bank 0 (contains the Dy4 FFW), bank 2
12849 + * (VxWorks boot), or the optional 48MiB expansion flash.
12851 + * scott.wood@timesys.com: On the newer boards with 128MiB flash, it
12852 + * now supports the first 96MiB (the boot flash bank containing FFW
12853 + * is excluded). The VxWorks loader is in partition 1.
12856 +#define FLASH_BASE_ADDR 0xf0000000
12857 +#define FLASH_BANK_SIZE (128*1024*1024)
12859 +MODULE_AUTHOR("Scott Wood, TimeSys Corporation <scott.wood@timesys.com>");
12860 +MODULE_DESCRIPTION("User-programmable flash device on the Dy4 SVME182 board");
12861 +MODULE_LICENSE("GPL");
12863 +static struct map_info svme182_map = {
12864 + .name = "Dy4 SVME182",
12866 + .size = 128 * 1024 * 1024
12869 +#define BOOTIMAGE_PART_SIZE ((6*1024*1024)-RESERVED_PART_SIZE)
12871 +// Allow 6MiB for the kernel
12872 +#define NEW_BOOTIMAGE_PART_SIZE (6 * 1024 * 1024)
12873 +// Allow 1MiB for the bootloader
12874 +#define NEW_BOOTLOADER_PART_SIZE (1024 * 1024)
12875 +// Use the remaining 9MiB at the end of flash for the RFS
12876 +#define NEW_RFS_PART_SIZE (0x01000000 - NEW_BOOTLOADER_PART_SIZE - \
12877 + NEW_BOOTIMAGE_PART_SIZE)
12879 +static struct mtd_partition svme182_partitions[] = {
12880 + // The Lower PABS is only 128KiB, but the partition code doesn't
12881 + // like partitions that don't end on the largest erase block
12882 + // size of the device, even if all of the erase blocks in the
12883 + // partition are small ones. The hardware should prevent
12884 + // writes to the actual PABS areas.
12886 + name: "Lower PABS and CPU 0 bootloader or kernel",
12887 + size: 6*1024*1024,
12891 + name: "Root Filesystem",
12892 + size: 10*1024*1024,
12893 + offset: MTDPART_OFS_NXTBLK
12896 + name: "CPU1 Bootloader",
12898 + offset: MTDPART_OFS_NXTBLK,
12902 + size: 110*1024*1024,
12903 + offset: MTDPART_OFS_NXTBLK
12906 + name: "Foundation Firmware and Upper PABS",
12908 + offset: MTDPART_OFS_NXTBLK,
12909 + mask_flags: MTD_WRITEABLE // read-only
12913 +static struct mtd_info *this_mtd;
12915 +static int __init init_svme182(void)
12917 + struct mtd_partition *partitions;
12918 + int num_parts = sizeof(svme182_partitions) / sizeof(struct mtd_partition);
12920 + partitions = svme182_partitions;
12922 + svme182_map.virt =
12923 + (void __iomem *)ioremap(FLASH_BASE_ADDR, svme182_map.size);
12925 + if (svme182_map.virt == 0) {
12926 + printk("Failed to ioremap FLASH memory area.\n");
12930 + simple_map_init(&svme182_map);
12932 + this_mtd = do_map_probe("cfi_probe", &svme182_map);
12935 + iounmap((void *)svme182_map.virt);
12939 + printk(KERN_NOTICE "SVME182 flash device: %dMiB at 0x%08x\n",
12940 + this_mtd->size >> 20, FLASH_BASE_ADDR);
12942 + this_mtd->owner = THIS_MODULE;
12943 + add_mtd_partitions(this_mtd, partitions, num_parts);
12948 +static void __exit cleanup_svme182(void)
12952 + del_mtd_partitions(this_mtd);
12953 + map_destroy(this_mtd);
12956 + if (svme182_map.virt)
12958 + iounmap((void *)svme182_map.virt);
12959 + svme182_map.virt = 0;
12965 +module_init(init_svme182);
12966 +module_exit(cleanup_svme182);
12967 Index: linux-2.6.5/drivers/mtd/maps/ebony.c
12968 ===================================================================
12969 --- linux-2.6.5.orig/drivers/mtd/maps/ebony.c 2004-04-03 22:37:59.000000000 -0500
12970 +++ linux-2.6.5/drivers/mtd/maps/ebony.c 2005-02-01 17:11:17.000000000 -0500
12973 - * $Id: ebony.c,v 1.8 2003/06/23 11:48:18 dwmw2 Exp $
12974 + * $Id: ebony.c,v 1.12 2004/09/16 23:27:13 gleixner Exp $
12976 * Mapping for Ebony user flash
12978 - * Matt Porter <mporter@mvista.com>
12979 + * Matt Porter <mporter@kernel.crashing.org>
12981 - * Copyright 2002 MontaVista Software Inc.
12982 + * Copyright 2002-2004 MontaVista Software Inc.
12984 * This program is free software; you can redistribute it and/or modify it
12985 * under the terms of the GNU General Public License as published by the
12986 @@ -21,22 +21,23 @@
12987 #include <linux/mtd/map.h>
12988 #include <linux/mtd/partitions.h>
12989 #include <linux/config.h>
12990 +#include <linux/version.h>
12991 #include <asm/io.h>
12992 -#include <asm/ibm440.h>
12993 -#include <platforms/ebony.h>
12994 +#include <asm/ibm44x.h>
12995 +#include <platforms/4xx/ebony.h>
12997 static struct mtd_info *flash;
12999 static struct map_info ebony_small_map = {
13000 .name = "Ebony small flash",
13001 .size = EBONY_SMALL_FLASH_SIZE,
13006 static struct map_info ebony_large_map = {
13007 .name = "Ebony large flash",
13008 .size = EBONY_LARGE_FLASH_SIZE,
13013 static struct mtd_partition ebony_small_partitions[] = {
13015 int __init init_ebony(void)
13018 - unsigned long fpga0_adr;
13020 unsigned long long small_flash_base, large_flash_base;
13022 fpga0_adr = ioremap64(EBONY_FPGA_ADDR, 16);
13026 fpga0_reg = readb(fpga0_adr);
13027 - iounmap64(fpga0_adr);
13028 + iounmap(fpga0_adr);
13030 if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
13031 !EBONY_FLASH_SEL(fpga0_reg))
13034 ebony_small_map.phys = small_flash_base;
13035 ebony_small_map.virt =
13036 - (unsigned long)ioremap64(small_flash_base,
13037 + (void __iomem *)ioremap64(small_flash_base,
13038 ebony_small_map.size);
13040 if (!ebony_small_map.virt) {
13041 @@ -160,5 +161,5 @@
13042 module_exit(cleanup_ebony);
13044 MODULE_LICENSE("GPL");
13045 -MODULE_AUTHOR("Matt Porter <mporter@mvista.com>");
13046 +MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
13047 MODULE_DESCRIPTION("MTD map and partitions for IBM 440GP Ebony boards");
13048 Index: linux-2.6.5/drivers/mtd/maps/edb7312.c
13049 ===================================================================
13050 --- linux-2.6.5.orig/drivers/mtd/maps/edb7312.c 2004-04-03 22:38:27.000000000 -0500
13051 +++ linux-2.6.5/drivers/mtd/maps/edb7312.c 2005-02-01 17:11:17.000000000 -0500
13054 - * $Id: edb7312.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $
13055 + * $Id: edb7312.c,v 1.12 2004/09/16 23:27:13 gleixner Exp $
13057 * Handle mapping of the NOR flash on Cogent EDB7312 boards
13061 #define FLASH_BLOCKSIZE_MAIN 0x20000
13062 #define FLASH_NUMBLOCKS_MAIN 128
13063 -/* can be "cfi_probe", "jedec_probe", "map_rom", 0 }; */
13064 -#define PROBETYPES { "cfi_probe", 0 }
13065 +/* can be "cfi_probe", "jedec_probe", "map_rom", NULL }; */
13066 +#define PROBETYPES { "cfi_probe", NULL }
13068 #define MSG_PREFIX "EDB7312-NOR:" /* prefix for our printk()'s */
13069 #define MTDID "edb7312-nor" /* for mtdparts= partitioning */
13071 struct map_info edb7312nor_map = {
13072 .name = "NOR flash on EDB7312",
13073 .size = WINDOW_SIZE,
13074 - .buswidth = BUSWIDTH,
13075 + .bankwidth = BUSWIDTH,
13076 .phys = WINDOW_ADDR,
13081 printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n",
13082 WINDOW_SIZE, WINDOW_ADDR);
13083 - edb7312nor_map.virt = (unsigned long)
13084 - ioremap(WINDOW_ADDR, WINDOW_SIZE);
13085 + edb7312nor_map.virt = (void __iomem *)
13086 + ioremap(WINDOW_ADDR, WINDOW_SIZE);
13088 if (!edb7312nor_map.virt) {
13089 printk(MSG_PREFIX "failed to ioremap\n");
13090 Index: linux-2.6.5/drivers/mtd/maps/elan-104nc.c
13091 ===================================================================
13092 --- linux-2.6.5.orig/drivers/mtd/maps/elan-104nc.c 2004-04-03 22:37:06.000000000 -0500
13093 +++ linux-2.6.5/drivers/mtd/maps/elan-104nc.c 2005-02-01 17:11:17.000000000 -0500
13095 along with this program; if not, write to the Free Software
13096 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
13098 - $Id: elan-104nc.c,v 1.18 2003/06/23 07:37:02 dwmw2 Exp $
13099 + $Id: elan-104nc.c,v 1.22 2004/09/16 23:27:13 gleixner Exp $
13101 The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x16
13102 mode. This drivers uses the CFI probe and Intel Extended Command Set drivers.
13104 #define PAGE_IO_SIZE 2
13106 static volatile int page_in_window = -1; // Current page in window.
13107 -static unsigned long iomapadr;
13108 +static void __iomem *iomapadr;
13109 static spinlock_t elan_104nc_spin = SPIN_LOCK_UNLOCKED;
13111 /* partition_info gives details on the logical partitions that the split the
13112 @@ -107,39 +107,19 @@
13116 -static __u8 elan_104nc_read8(struct map_info *map, unsigned long ofs)
13117 +static map_word elan_104nc_read16(struct map_info *map, unsigned long ofs)
13121 spin_lock(&elan_104nc_spin);
13122 elan_104nc_page(map, ofs);
13123 - ret = readb(iomapadr + (ofs & WINDOW_MASK));
13124 - spin_unlock(&elan_104nc_spin);
13128 -static __u16 elan_104nc_read16(struct map_info *map, unsigned long ofs)
13131 - spin_lock(&elan_104nc_spin);
13132 - elan_104nc_page(map, ofs);
13133 - ret = readw(iomapadr + (ofs & WINDOW_MASK));
13134 - spin_unlock(&elan_104nc_spin);
13138 -static __u32 elan_104nc_read32(struct map_info *map, unsigned long ofs)
13141 - spin_lock(&elan_104nc_spin);
13142 - elan_104nc_page(map, ofs);
13143 - ret = readl(iomapadr + (ofs & WINDOW_MASK));
13144 + ret.x[0] = readw(iomapadr + (ofs & WINDOW_MASK));
13145 spin_unlock(&elan_104nc_spin);
13149 static void elan_104nc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
13153 unsigned long thislen = len;
13154 if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
13155 thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
13156 @@ -154,27 +134,11 @@
13160 -static void elan_104nc_write8(struct map_info *map, __u8 d, unsigned long adr)
13162 - spin_lock(&elan_104nc_spin);
13163 - elan_104nc_page(map, adr);
13164 - writeb(d, iomapadr + (adr & WINDOW_MASK));
13165 - spin_unlock(&elan_104nc_spin);
13168 -static void elan_104nc_write16(struct map_info *map, __u16 d, unsigned long adr)
13170 - spin_lock(&elan_104nc_spin);
13171 - elan_104nc_page(map, adr);
13172 - writew(d, iomapadr + (adr & WINDOW_MASK));
13173 - spin_unlock(&elan_104nc_spin);
13176 -static void elan_104nc_write32(struct map_info *map, __u32 d, unsigned long adr)
13177 +static void elan_104nc_write16(struct map_info *map, map_word d, unsigned long adr)
13179 spin_lock(&elan_104nc_spin);
13180 elan_104nc_page(map, adr);
13181 - writel(d, iomapadr + (adr & WINDOW_MASK));
13182 + writew(d.x[0], iomapadr + (adr & WINDOW_MASK));
13183 spin_unlock(&elan_104nc_spin);
13186 @@ -201,14 +165,10 @@
13187 .size = 8*1024*1024, /* this must be set to a maximum possible amount
13188 of flash so the cfi probe routines find all
13191 - .read8 = elan_104nc_read8,
13192 - .read16 = elan_104nc_read16,
13193 - .read32 = elan_104nc_read32,
13195 + .read = elan_104nc_read16,
13196 .copy_from = elan_104nc_copy_from,
13197 - .write8 = elan_104nc_write8,
13198 - .write16 = elan_104nc_write16,
13199 - .write32 = elan_104nc_write32,
13200 + .write = elan_104nc_write16,
13201 .copy_to = elan_104nc_copy_to
13204 @@ -230,7 +190,7 @@
13205 /* Urg! We use I/O port 0x22 without request_region()ing it,
13206 because it's already allocated to the PIC. */
13208 - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
13209 + iomapadr = (void __iomem *)ioremap(WINDOW_START, WINDOW_LENGTH);
13211 printk( KERN_ERR"%s: failed to ioremap memory region\n",
13212 elan_104nc_map.name );
13213 Index: linux-2.6.5/drivers/mtd/maps/epxa10db-flash.c
13214 ===================================================================
13215 --- linux-2.6.5.orig/drivers/mtd/maps/epxa10db-flash.c 2004-04-03 22:37:39.000000000 -0500
13216 +++ linux-2.6.5/drivers/mtd/maps/epxa10db-flash.c 2005-02-01 17:11:17.000000000 -0500
13218 * Copyright (C) 2001 Altera Corporation
13219 * Copyright (C) 2001 Red Hat, Inc.
13221 - * $Id: epxa10db-flash.c,v 1.10 2003/05/21 12:45:18 dwmw2 Exp $
13222 + * $Id: epxa10db-flash.c,v 1.12 2004/09/16 23:27:13 gleixner Exp $
13224 * This program is free software; you can redistribute it and/or modify
13225 * it under the terms of the GNU General Public License as published by
13227 static struct map_info epxa_map = {
13228 .name = "EPXA flash",
13229 .size = FLASH_SIZE,
13232 .phys = FLASH_START,
13237 printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
13239 - epxa_map.virt = (unsigned long)ioremap(FLASH_START, FLASH_SIZE);
13240 + epxa_map.virt = (void __iomem *)ioremap(FLASH_START, FLASH_SIZE);
13241 if (!epxa_map.virt) {
13242 printk("Failed to ioremap %s flash\n",BOARD_NAME);
13244 Index: linux-2.6.5/drivers/mtd/maps/fortunet.c
13245 ===================================================================
13246 --- linux-2.6.5.orig/drivers/mtd/maps/fortunet.c 2004-04-03 22:36:27.000000000 -0500
13247 +++ linux-2.6.5/drivers/mtd/maps/fortunet.c 2005-02-01 17:11:17.000000000 -0500
13249 /* fortunet.c memory map
13251 - * $Id: fortunet.c,v 1.6 2003/05/21 12:45:18 dwmw2 Exp $
13252 + * $Id: fortunet.c,v 1.8 2004/09/16 23:27:13 gleixner Exp $
13255 #include <linux/module.h>
13259 int window_addr_physical;
13261 + int altbankwidth;
13262 struct map_info map_info;
13263 struct mtd_info *mymtd;
13264 struct mtd_partition parts[MAX_NUM_PARTITIONS];
13267 struct map_info default_map = {
13268 .size = DEF_WINDOW_SIZE,
13273 static char * __init get_string_option(char *dest,int dest_size,char *sor)
13274 @@ -102,7 +102,7 @@
13277 printk(MTD_FORTUNET_PK "Bad parameters for MTD Region "
13278 - " name,region-number[,base,size,buswidth,altbuswidth]\n");
13279 + " name,region-number[,base,size,bankwidth,altbankwidth]\n");
13282 if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
13283 @@ -116,7 +116,7 @@
13284 &default_map,sizeof(map_regions[params[1]].map_info));
13285 map_regions_set[params[1]] = 1;
13286 map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY;
13287 - map_regions[params[1]].altbuswidth = 2;
13288 + map_regions[params[1]].altbankwidth = 2;
13289 map_regions[params[1]].mymtd = NULL;
13290 map_regions[params[1]].map_info.name = map_regions[params[1]].map_name;
13291 strcpy(map_regions[params[1]].map_info.name,string);
13292 @@ -130,11 +130,11 @@
13296 - map_regions[params[1]].map_info.buswidth = params[4];
13297 + map_regions[params[1]].map_info.bankwidth = params[4];
13301 - map_regions[params[1]].altbuswidth = params[5];
13302 + map_regions[params[1]].altbankwidth = params[5];
13306 @@ -193,7 +193,7 @@
13307 sizeof(map_regions[ix].map_info));
13308 map_regions_set[ix] = 1;
13309 map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY;
13310 - map_regions[ix].altbuswidth = 2;
13311 + map_regions[ix].altbankwidth = 2;
13312 map_regions[ix].mymtd = NULL;
13313 map_regions[ix].map_info.name = map_regions[ix].map_name;
13314 strcpy(map_regions[ix].map_info.name,"FORTUNET");
13315 @@ -210,7 +210,7 @@
13316 map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical,
13318 map_regions[ix].map_info.virt =
13319 - (int)ioremap_nocache(
13320 + (void __iomem *)ioremap_nocache(
13321 map_regions[ix].window_addr_physical,
13322 map_regions[ix].map_info.size);
13323 if(!map_regions[ix].map_info.virt)
13324 @@ -227,13 +227,13 @@
13325 map_regions[ix].mymtd = do_map_probe("cfi_probe",
13326 &map_regions[ix].map_info);
13327 if((!map_regions[ix].mymtd)&&(
13328 - map_regions[ix].altbuswidth!=map_regions[ix].map_info.buswidth))
13329 + map_regions[ix].altbankwidth!=map_regions[ix].map_info.bankwidth))
13331 - printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate buswidth "
13332 + printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth "
13334 map_regions[ix].map_info.name);
13335 - map_regions[ix].map_info.buswidth =
13336 - map_regions[ix].altbuswidth;
13337 + map_regions[ix].map_info.bankwidth =
13338 + map_regions[ix].altbankwidth;
13339 map_regions[ix].mymtd = do_map_probe("cfi_probe",
13340 &map_regions[ix].map_info);
13342 Index: linux-2.6.5/drivers/mtd/maps/h720x-flash.c
13343 ===================================================================
13344 --- linux-2.6.5.orig/drivers/mtd/maps/h720x-flash.c 2004-04-03 22:36:26.000000000 -0500
13345 +++ linux-2.6.5/drivers/mtd/maps/h720x-flash.c 2005-02-01 17:11:17.000000000 -0500
13347 * Flash memory access on Hynix GMS30C7201/HMS30C7202 based
13348 * evaluation boards
13350 + * $Id: h720x-flash.c,v 1.10 2004/09/16 23:27:13 gleixner Exp $
13352 * (C) 2002 Jungjun Kim <jungjun.kim@hynix.com>
13353 * 2003 Thomas Gleixner <tglx@linutronix.de>
13357 #include <linux/config.h>
13358 #include <linux/module.h>
13361 static struct map_info h720x_map = {
13365 .size = FLASH_SIZE,
13366 .phys = FLASH_PHYS,
13370 char *part_type = NULL;
13372 - h720x_map.virt = (unsigned long)ioremap(FLASH_PHYS, FLASH_SIZE);
13373 + h720x_map.virt = (void __iomem *)ioremap(FLASH_PHYS, FLASH_SIZE);
13375 if (!h720x_map.virt) {
13376 printk(KERN_ERR "H720x-MTD: ioremap failed\n");
13377 @@ -80,13 +82,13 @@
13379 simple_map_init(&h720x_map);
13381 - // Probe for flash buswidth 4
13382 + // Probe for flash bankwidth 4
13383 printk (KERN_INFO "H720x-MTD probing 32bit FLASH\n");
13384 mymtd = do_map_probe("cfi_probe", &h720x_map);
13386 printk (KERN_INFO "H720x-MTD probing 16bit FLASH\n");
13387 - // Probe for buswidth 2
13388 - h720x_map.buswidth = 2;
13389 + // Probe for bankwidth 2
13390 + h720x_map.bankwidth = 2;
13391 mymtd = do_map_probe("cfi_probe", &h720x_map);
13394 Index: linux-2.6.5/drivers/mtd/maps/ichxrom.c
13395 ===================================================================
13396 --- linux-2.6.5.orig/drivers/mtd/maps/ichxrom.c 1969-12-31 19:00:00.000000000 -0500
13397 +++ linux-2.6.5/drivers/mtd/maps/ichxrom.c 2005-02-01 17:11:17.000000000 -0500
13402 + * Normal mappings of chips in physical memory
13403 + * $Id: ichxrom.c,v 1.13 2004/09/17 11:45:06 eric Exp $
13406 +#include <linux/module.h>
13407 +#include <linux/types.h>
13408 +#include <linux/kernel.h>
13409 +#include <linux/init.h>
13410 +#include <asm/io.h>
13411 +#include <linux/mtd/mtd.h>
13412 +#include <linux/mtd/map.h>
13413 +#include <linux/mtd/cfi.h>
13414 +#include <linux/mtd/flashchip.h>
13415 +#include <linux/config.h>
13416 +#include <linux/pci.h>
13417 +#include <linux/pci_ids.h>
13418 +#include <linux/list.h>
13420 +#define xstr(s) str(s)
13422 +#define MOD_NAME xstr(KBUILD_BASENAME)
13424 +#define ADDRESS_NAME_LEN 18
13426 +#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
13428 +#define BIOS_CNTL 0x4e
13429 +#define FWH_DEC_EN1 0xE3
13430 +#define FWH_DEC_EN2 0xF0
13431 +#define FWH_SEL1 0xE8
13432 +#define FWH_SEL2 0xEE
13434 +struct ichxrom_window {
13435 + void __iomem* virt;
13436 + unsigned long phys;
13437 + unsigned long size;
13438 + struct list_head maps;
13439 + struct resource rsrc;
13440 + struct pci_dev *pdev;
13443 +struct ichxrom_map_info {
13444 + struct list_head list;
13445 + struct map_info map;
13446 + struct mtd_info *mtd;
13447 + struct resource rsrc;
13448 + char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
13451 +static struct ichxrom_window ichxrom_window = {
13452 + .maps = LIST_HEAD_INIT(ichxrom_window.maps),
13455 +static void ichxrom_cleanup(struct ichxrom_window *window)
13457 + struct ichxrom_map_info *map, *scratch;
13460 + /* Disable writes through the rom window */
13461 + pci_read_config_word(window->pdev, BIOS_CNTL, &word);
13462 + pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1);
13464 + /* Free all of the mtd devices */
13465 + list_for_each_entry_safe(map, scratch, &window->maps, list) {
13466 + if (map->rsrc.parent)
13467 + release_resource(&map->rsrc);
13468 + del_mtd_device(map->mtd);
13469 + map_destroy(map->mtd);
13470 + list_del(&map->list);
13473 + if (window->rsrc.parent)
13474 + release_resource(&window->rsrc);
13475 + if (window->virt) {
13476 + iounmap(window->virt);
13477 + window->virt = NULL;
13478 + window->phys = 0;
13479 + window->size = 0;
13480 + window->pdev = NULL;
13485 +static int __devinit ichxrom_init_one (struct pci_dev *pdev,
13486 + const struct pci_device_id *ent)
13488 + static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
13489 + struct ichxrom_window *window = &ichxrom_window;
13490 + struct ichxrom_map_info *map = 0;
13491 + unsigned long map_top;
13495 + /* For now I just handle the ichx and I assume there
13496 + * are not a lot of resources up at the top of the address
13497 + * space. It is possible to handle other devices in the
13498 + * top 16MB but it is very painful. Also since
13499 + * you can only really attach a FWH to an ICHX there
13500 + * a number of simplifications you can make.
13502 + * Also you can page firmware hubs if an 8MB window isn't enough
13503 + * but don't currently handle that case either.
13505 + window->pdev = pdev;
13507 + /* Find a region continuous to the end of the ROM window */
13508 + window->phys = 0;
13509 + pci_read_config_byte(pdev, FWH_DEC_EN1, &byte);
13510 + if (byte == 0xff) {
13511 + window->phys = 0xffc00000;
13512 + pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
13513 + if ((byte & 0x0f) == 0x0f) {
13514 + window->phys = 0xff400000;
13516 + else if ((byte & 0x0e) == 0x0e) {
13517 + window->phys = 0xff500000;
13519 + else if ((byte & 0x0c) == 0x0c) {
13520 + window->phys = 0xff600000;
13522 + else if ((byte & 0x08) == 0x08) {
13523 + window->phys = 0xff700000;
13526 + else if ((byte & 0xfe) == 0xfe) {
13527 + window->phys = 0xffc80000;
13529 + else if ((byte & 0xfc) == 0xfc) {
13530 + window->phys = 0xffd00000;
13532 + else if ((byte & 0xf8) == 0xf8) {
13533 + window->phys = 0xffd80000;
13535 + else if ((byte & 0xf0) == 0xf0) {
13536 + window->phys = 0xffe00000;
13538 + else if ((byte & 0xe0) == 0xe0) {
13539 + window->phys = 0xffe80000;
13541 + else if ((byte & 0xc0) == 0xc0) {
13542 + window->phys = 0xfff00000;
13544 + else if ((byte & 0x80) == 0x80) {
13545 + window->phys = 0xfff80000;
13548 + if (window->phys == 0) {
13549 + printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
13552 + window->phys -= 0x400000UL;
13553 + window->size = (0xffffffffUL - window->phys) + 1UL;
13555 + /* Enable writes through the rom window */
13556 + pci_read_config_word(pdev, BIOS_CNTL, &word);
13557 + if (!(word & 1) && (word & (1<<1))) {
13558 + /* The BIOS will generate an error if I enable
13559 + * this device, so don't even try.
13561 + printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n");
13564 + pci_write_config_word(pdev, BIOS_CNTL, word | 1);
13567 + * Try to reserve the window mem region. If this fails then
13568 + * it is likely due to the window being "reseved" by the BIOS.
13570 + window->rsrc.name = MOD_NAME;
13571 + window->rsrc.start = window->phys;
13572 + window->rsrc.end = window->phys + window->size - 1;
13573 + window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
13574 + if (request_resource(&iomem_resource, &window->rsrc)) {
13575 + window->rsrc.parent = NULL;
13576 + printk(KERN_DEBUG MOD_NAME
13577 + ": %s(): Unable to register resource"
13578 + " 0x%.08lx-0x%.08lx - kernel bug?\n",
13580 + window->rsrc.start, window->rsrc.end);
13583 + /* Map the firmware hub into my address space. */
13584 + window->virt = ioremap_nocache(window->phys, window->size);
13585 + if (!window->virt) {
13586 + printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
13587 + window->phys, window->size);
13591 + /* Get the first address to look for an rom chip at */
13592 + map_top = window->phys;
13593 + if ((window->phys & 0x3fffff) != 0) {
13594 + map_top = window->phys + 0x400000;
13597 + /* The probe sequence run over the firmware hub lock
13598 + * registers sets them to 0x7 (no access).
13599 + * Probe at most the last 4M of the address space.
13601 + if (map_top < 0xffc00000) {
13602 + map_top = 0xffc00000;
13605 + /* Loop through and look for rom chips */
13606 + while((map_top - 1) < 0xffffffffUL) {
13607 + struct cfi_private *cfi;
13608 + unsigned long offset;
13612 + map = kmalloc(sizeof(*map), GFP_KERNEL);
13615 + printk(KERN_ERR MOD_NAME ": kmalloc failed");
13618 + memset(map, 0, sizeof(*map));
13619 + INIT_LIST_HEAD(&map->list);
13620 + map->map.name = map->map_name;
13621 + map->map.phys = map_top;
13622 + offset = map_top - window->phys;
13623 + map->map.virt = (void __iomem *)
13624 + (((unsigned long)(window->virt)) + offset);
13625 + map->map.size = 0xffffffffUL - map_top + 1UL;
13626 + /* Set the name of the map to the address I am trying */
13627 + sprintf(map->map_name, "%s @%08lx",
13628 + MOD_NAME, map->map.phys);
13630 + /* Firmware hubs only use vpp when being programmed
13631 + * in a factory setting. So in-place programming
13632 + * needs to use a different method.
13634 + for(map->map.bankwidth = 32; map->map.bankwidth;
13635 + map->map.bankwidth >>= 1)
13637 + char **probe_type;
13638 + /* Skip bankwidths that are not supported */
13639 + if (!map_bankwidth_supported(map->map.bankwidth))
13642 + /* Setup the map methods */
13643 + simple_map_init(&map->map);
13645 + /* Try all of the probe methods */
13646 + probe_type = rom_probe_types;
13647 + for(; *probe_type; probe_type++) {
13648 + map->mtd = do_map_probe(*probe_type, &map->map);
13653 + map_top += ROM_PROBE_STEP_SIZE;
13656 + /* Trim the size if we are larger than the map */
13657 + if (map->mtd->size > map->map.size) {
13658 + printk(KERN_WARNING MOD_NAME
13659 + " rom(%u) larger than window(%lu). fixing...\n",
13660 + map->mtd->size, map->map.size);
13661 + map->mtd->size = map->map.size;
13663 + if (window->rsrc.parent) {
13665 + * Registering the MTD device in iomem may not be possible
13666 + * if there is a BIOS "reserved" and BUSY range. If this
13667 + * fails then continue anyway.
13669 + map->rsrc.name = map->map_name;
13670 + map->rsrc.start = map->map.phys;
13671 + map->rsrc.end = map->map.phys + map->mtd->size - 1;
13672 + map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
13673 + if (request_resource(&window->rsrc, &map->rsrc)) {
13674 + printk(KERN_ERR MOD_NAME
13675 + ": cannot reserve MTD resource\n");
13676 + map->rsrc.parent = NULL;
13680 + /* Make the whole region visible in the map */
13681 + map->map.virt = window->virt;
13682 + map->map.phys = window->phys;
13683 + cfi = map->map.fldrv_priv;
13684 + for(i = 0; i < cfi->numchips; i++) {
13685 + cfi->chips[i].start += offset;
13688 + /* Now that the mtd devices is complete claim and export it */
13689 + map->mtd->owner = THIS_MODULE;
13690 + add_mtd_device(map->mtd);
13693 + /* Calculate the new value of map_top */
13694 + map_top += map->mtd->size;
13696 + /* File away the map structure */
13697 + list_add(&map->list, &window->maps);
13702 + /* Free any left over map structures */
13706 + /* See if I have any map structures */
13707 + if (list_empty(&window->maps)) {
13708 + ichxrom_cleanup(window);
13716 +static void __devexit ichxrom_remove_one (struct pci_dev *pdev)
13718 + struct ichxrom_window *window = &ichxrom_window;
13719 + ichxrom_cleanup(window);
13722 +static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = {
13723 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
13724 + PCI_ANY_ID, PCI_ANY_ID, },
13725 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
13726 + PCI_ANY_ID, PCI_ANY_ID, },
13727 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
13728 + PCI_ANY_ID, PCI_ANY_ID, },
13729 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
13730 + PCI_ANY_ID, PCI_ANY_ID, },
13731 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
13732 + PCI_ANY_ID, PCI_ANY_ID, },
13736 +MODULE_DEVICE_TABLE(pci, ichxrom_pci_tbl);
13739 +static struct pci_driver ichxrom_driver = {
13740 + .name = MOD_NAME,
13741 + .id_table = ichxrom_pci_tbl,
13742 + .probe = ichxrom_init_one,
13743 + .remove = ichxrom_remove_one,
13747 +int __init init_ichxrom(void)
13749 + struct pci_dev *pdev;
13750 + struct pci_device_id *id;
13753 + for (id = ichxrom_pci_tbl; id->vendor; id++) {
13754 + pdev = pci_find_device(id->vendor, id->device, NULL);
13760 + return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]);
13764 + return pci_module_init(&ichxrom_driver);
13768 +static void __exit cleanup_ichxrom(void)
13770 + ichxrom_remove_one(ichxrom_window.pdev);
13773 +module_init(init_ichxrom);
13774 +module_exit(cleanup_ichxrom);
13776 +MODULE_LICENSE("GPL");
13777 +MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
13778 +MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ICHX southbridge");
13779 Index: linux-2.6.5/drivers/mtd/maps/impa7.c
13780 ===================================================================
13781 --- linux-2.6.5.orig/drivers/mtd/maps/impa7.c 2004-04-03 22:36:26.000000000 -0500
13782 +++ linux-2.6.5/drivers/mtd/maps/impa7.c 2005-02-01 17:11:17.000000000 -0500
13785 - * $Id: impa7.c,v 1.9 2003/06/23 11:47:43 dwmw2 Exp $
13786 + * $Id: impa7.c,v 1.12 2004/09/16 23:27:13 gleixner Exp $
13788 * Handle mapping of the NOR flash on implementa A7 boards
13790 @@ -30,25 +30,25 @@
13791 #define NUM_FLASHBANKS 2
13794 -/* can be { "cfi_probe", "jedec_probe", "map_rom", 0 }; */
13795 -#define PROBETYPES { "jedec_probe", 0 }
13796 +/* can be { "cfi_probe", "jedec_probe", "map_rom", NULL } */
13797 +#define PROBETYPES { "jedec_probe", NULL }
13799 #define MSG_PREFIX "impA7:" /* prefix for our printk()'s */
13800 #define MTDID "impa7-%d" /* for mtdparts= partitioning */
13802 -static struct mtd_info *impa7_mtd[NUM_FLASHBANKS] = { 0 };
13803 +static struct mtd_info *impa7_mtd[NUM_FLASHBANKS];
13806 static struct map_info impa7_map[NUM_FLASHBANKS] = {
13808 .name = "impA7 NOR Flash Bank #0",
13809 .size = WINDOW_SIZE0,
13810 - .buswidth = BUSWIDTH,
13811 + .bankwidth = BUSWIDTH,
13814 .name = "impA7 NOR Flash Bank #1",
13815 .size = WINDOW_SIZE1,
13816 - .buswidth = BUSWIDTH,
13817 + .bankwidth = BUSWIDTH,
13822 pt[i].size, pt[i].addr);
13824 impa7_map[i].phys = pt[i].addr;
13825 - impa7_map[i].virt = (unsigned long)
13826 + impa7_map[i].virt = (void __iomem *)
13827 ioremap(pt[i].addr, pt[i].size);
13828 if (!impa7_map[i].virt) {
13829 printk(MSG_PREFIX "failed to ioremap\n");
13830 Index: linux-2.6.5/drivers/mtd/maps/integrator-flash-v24.c
13831 ===================================================================
13832 --- linux-2.6.5.orig/drivers/mtd/maps/integrator-flash-v24.c 1969-12-31 19:00:00.000000000 -0500
13833 +++ linux-2.6.5/drivers/mtd/maps/integrator-flash-v24.c 2005-02-01 17:11:17.000000000 -0500
13835 +/*======================================================================
13837 + drivers/mtd/maps/armflash.c: ARM Flash Layout/Partitioning
13839 + Copyright (C) 2000 ARM Limited
13841 + This program is free software; you can redistribute it and/or modify
13842 + it under the terms of the GNU General Public License as published by
13843 + the Free Software Foundation; either version 2 of the License, or
13844 + (at your option) any later version.
13846 + This program is distributed in the hope that it will be useful,
13847 + but WITHOUT ANY WARRANTY; without even the implied warranty of
13848 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13849 + GNU General Public License for more details.
13851 + You should have received a copy of the GNU General Public License
13852 + along with this program; if not, write to the Free Software
13853 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13855 + This is access code for flashes using ARM's flash partitioning
13858 + $Id: integrator-flash-v24.c,v 1.14 2004/09/16 23:27:13 gleixner Exp $
13860 +======================================================================*/
13862 +#include <linux/config.h>
13863 +#include <linux/module.h>
13864 +#include <linux/types.h>
13865 +#include <linux/kernel.h>
13866 +#include <linux/slab.h>
13867 +#include <linux/ioport.h>
13868 +#include <linux/init.h>
13870 +#include <linux/mtd/mtd.h>
13871 +#include <linux/mtd/map.h>
13872 +#include <linux/mtd/partitions.h>
13874 +#include <asm/hardware.h>
13875 +#include <asm/io.h>
13876 +#include <asm/system.h>
13878 +// board specific stuff - sorry, it should be in arch/arm/mach-*.
13879 +#ifdef CONFIG_ARCH_INTEGRATOR
13881 +#define FLASH_BASE INTEGRATOR_FLASH_BASE
13882 +#define FLASH_SIZE INTEGRATOR_FLASH_SIZE
13884 +#define FLASH_PART_SIZE 0x400000
13886 +#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
13887 +#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
13888 +#define EBI_CSR1 (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_CSR1_OFFSET)
13889 +#define EBI_LOCK (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_LOCK_OFFSET)
13892 + * Initialise the flash access systems:
13895 + * - Set write enable bit in EBI reg
13897 +static void armflash_flash_init(void)
13899 + unsigned int tmp;
13901 + __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
13903 + tmp = __raw_readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
13904 + __raw_writel(tmp, EBI_CSR1);
13906 + if (!(__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) {
13907 + __raw_writel(0xa05f, EBI_LOCK);
13908 + __raw_writel(tmp, EBI_CSR1);
13909 + __raw_writel(0, EBI_LOCK);
13914 + * Shutdown the flash access systems:
13917 + * - Clear write enable bit in EBI reg
13919 +static void armflash_flash_exit(void)
13921 + unsigned int tmp;
13923 + __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
13926 + * Clear the write enable bit in system controller EBI register.
13928 + tmp = __raw_readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
13929 + __raw_writel(tmp, EBI_CSR1);
13931 + if (__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) {
13932 + __raw_writel(0xa05f, EBI_LOCK);
13933 + __raw_writel(tmp, EBI_CSR1);
13934 + __raw_writel(0, EBI_LOCK);
13938 +static void armflash_flash_wp(int on)
13940 + unsigned int reg;
13947 + __raw_writel(INTEGRATOR_SC_CTRL_nFLWP, reg);
13950 +static void armflash_set_vpp(struct map_info *map, int on)
13952 + unsigned int reg;
13959 + __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
13963 +#ifdef CONFIG_ARCH_P720T
13965 +#define FLASH_BASE (0x04000000)
13966 +#define FLASH_SIZE (64*1024*1024)
13968 +#define FLASH_PART_SIZE (4*1024*1024)
13969 +#define FLASH_BLOCK_SIZE (128*1024)
13971 +static void armflash_flash_init(void)
13975 +static void armflash_flash_exit(void)
13979 +static void armflash_flash_wp(int on)
13983 +static void armflash_set_vpp(struct map_info *map, int on)
13989 +static struct map_info armflash_map =
13992 + .set_vpp = armflash_set_vpp,
13993 + .phys = FLASH_BASE,
13996 +static struct mtd_info *mtd;
13997 +static struct mtd_partition *parts;
13998 +static const char *probes[] = { "RedBoot", "afs", NULL };
14000 +static int __init armflash_cfi_init(void *base, u_int size)
14004 + armflash_flash_init();
14005 + armflash_flash_wp(1);
14008 + * look for CFI based flash parts fitted to this board
14010 + armflash_map.size = size;
14011 + armflash_map.bankwidth = 4;
14012 + armflash_map.virt = (void __iomem *) base;
14014 + simple_map_init(&armflash_map);
14017 + * Also, the CFI layer automatically works out what size
14018 + * of chips we have, and does the necessary identification
14019 + * for us automatically.
14021 + mtd = do_map_probe("cfi_probe", &armflash_map);
14025 + mtd->owner = THIS_MODULE;
14027 + ret = parse_mtd_partitions(mtd, probes, &parts, (void *)0);
14029 + ret = add_mtd_partitions(mtd, parts, ret);
14031 + printk(KERN_ERR "mtd partition registration "
14032 + "failed: %d\n", ret);
14036 + * If we got an error, free all resources.
14039 + del_mtd_partitions(mtd);
14040 + map_destroy(mtd);
14046 +static void armflash_cfi_exit(void)
14049 + del_mtd_partitions(mtd);
14050 + map_destroy(mtd);
14056 +static int __init armflash_init(void)
14058 + int err = -EBUSY;
14061 + if (request_mem_region(FLASH_BASE, FLASH_SIZE, "flash") == NULL)
14064 + base = ioremap(FLASH_BASE, FLASH_SIZE);
14066 + if (base == NULL)
14069 + err = armflash_cfi_init(base, FLASH_SIZE);
14073 + release_mem_region(FLASH_BASE, FLASH_SIZE);
14079 +static void __exit armflash_exit(void)
14081 + armflash_cfi_exit();
14082 + iounmap((void *)armflash_map.virt);
14083 + release_mem_region(FLASH_BASE, FLASH_SIZE);
14084 + armflash_flash_exit();
14087 +module_init(armflash_init);
14088 +module_exit(armflash_exit);
14090 +MODULE_AUTHOR("ARM Ltd");
14091 +MODULE_DESCRIPTION("ARM Integrator CFI map driver");
14092 +MODULE_LICENSE("GPL");
14093 Index: linux-2.6.5/drivers/mtd/maps/integrator-flash.c
14094 ===================================================================
14095 --- linux-2.6.5.orig/drivers/mtd/maps/integrator-flash.c 2004-04-03 22:37:41.000000000 -0500
14096 +++ linux-2.6.5/drivers/mtd/maps/integrator-flash.c 2005-02-01 17:11:17.000000000 -0500
14098 This is access code for flashes using ARM's flash partitioning
14101 - $Id: integrator-flash.c,v 1.15 2004/02/27 22:37:39 rmk Exp $
14102 + $Id: integrator-flash.c,v 1.17 2004/09/16 23:27:13 gleixner Exp $
14104 ======================================================================*/
14106 @@ -108,9 +108,9 @@
14107 * look for CFI based flash parts fitted to this board
14109 info->map.size = size;
14110 - info->map.buswidth = plat->width;
14111 + info->map.bankwidth = plat->width;
14112 info->map.phys = res->start;
14113 - info->map.virt = (unsigned long) base;
14114 + info->map.virt = (void __iomem *) base;
14115 info->map.name = dev->dev.bus_id;
14116 info->map.set_vpp = armflash_set_vpp;
14118 Index: linux-2.6.5/drivers/mtd/maps/ipaq-flash.c
14119 ===================================================================
14120 --- linux-2.6.5.orig/drivers/mtd/maps/ipaq-flash.c 1969-12-31 19:00:00.000000000 -0500
14121 +++ linux-2.6.5/drivers/mtd/maps/ipaq-flash.c 2005-02-01 17:11:17.000000000 -0500
14124 + * Flash memory access on iPAQ Handhelds (either SA1100 or PXA250 based)
14126 + * (C) 2000 Nicolas Pitre <nico@cam.org>
14127 + * (C) 2002 Hewlett-Packard Company <jamey.hicks@hp.com>
14128 + * (C) 2003 Christian Pellegrin <chri@ascensit.com>, <chri@infis.univ.ts.it>: concatenation of multiple flashes
14130 + * $Id: ipaq-flash.c,v 1.2 2004/09/16 23:27:13 gleixner Exp $
14133 +#include <linux/config.h>
14134 +#include <linux/module.h>
14135 +#include <linux/types.h>
14136 +#include <linux/kernel.h>
14137 +#include <linux/spinlock.h>
14138 +#include <linux/init.h>
14139 +#include <linux/slab.h>
14140 +#include <asm/page.h>
14141 +#include <asm/mach-types.h>
14142 +#include <asm/system.h>
14143 +#include <asm/errno.h>
14145 +#include <linux/mtd/mtd.h>
14146 +#include <linux/mtd/map.h>
14147 +#include <linux/mtd/partitions.h>
14148 +#ifdef CONFIG_MTD_CONCAT
14149 +#include <linux/mtd/concat.h>
14152 +#include <asm/hardware.h>
14153 +#include <asm/arch-sa1100/h3600.h>
14154 +#include <asm/io.h>
14157 +#ifndef CONFIG_IPAQ_HANDHELD
14158 +#error This is for iPAQ Handhelds only
14160 +#ifdef CONFIG_SA1100_JORNADA56X
14162 +static void jornada56x_set_vpp(struct map_info *map, int vpp)
14165 + GPSR = GPIO_GPIO26;
14167 + GPCR = GPIO_GPIO26;
14168 + GPDR |= GPIO_GPIO26;
14173 +#ifdef CONFIG_SA1100_JORNADA720
14175 +static void jornada720_set_vpp(struct map_info *map, int vpp)
14186 +#define MAX_IPAQ_CS 2 /* Number of CS we are going to test */
14188 +#define IPAQ_MAP_INIT(X) \
14190 + name: "IPAQ flash " X, \
14194 +static struct map_info ipaq_map[MAX_IPAQ_CS] = {
14195 + IPAQ_MAP_INIT("bank 1"),
14196 + IPAQ_MAP_INIT("bank 2")
14199 +static struct mtd_info *my_sub_mtd[MAX_IPAQ_CS] = {
14205 + * Here are partition information for all known IPAQ-based devices.
14206 + * See include/linux/mtd/partitions.h for definition of the mtd_partition
14209 + * The *_max_flash_size is the maximum possible mapped flash size which
14210 + * is not necessarily the actual flash size. It must be no more than
14211 + * the value specified in the "struct map_desc *_io_desc" mapping
14212 + * definition for the corresponding machine.
14214 + * Please keep these in alphabetical order, and formatted as per existing
14215 + * entries. Thanks.
14218 +#ifdef CONFIG_IPAQ_HANDHELD
14219 +static unsigned long h3xxx_max_flash_size = 0x04000000;
14220 +static struct mtd_partition h3xxx_partitions[] = {
14222 + name: "H3XXX boot firmware",
14223 +#ifndef CONFIG_LAB
14224 + size: 0x00040000,
14226 + size: 0x00080000,
14229 +#ifndef CONFIG_LAB
14230 + mask_flags: MTD_WRITEABLE, /* force read-only */
14234 + name: "H3XXX root jffs2",
14235 +#ifndef CONFIG_LAB
14236 + size: 0x2000000 - 2*0x40000, /* Warning, this is fixed later */
14237 + offset: 0x00040000,
14239 + size: 0x2000000 - 0x40000 - 0x80000, /* Warning, this is fixed later */
14240 + offset: 0x00080000,
14246 + offset: 0x2000000 - 0x40000, /* Warning, this is fixed later */
14247 + mask_flags: MTD_WRITEABLE, /* force read-only */
14251 +#ifndef CONFIG_MTD_CONCAT
14252 +static struct mtd_partition h3xxx_partitions_bank2[] = {
14253 + /* this is used only on 2 CS machines when concat is not present */
14255 + name: "second H3XXX root jffs2",
14256 + size: 0x1000000 - 0x40000, /* Warning, this is fixed later */
14257 + offset: 0x00000000,
14260 + name: "second asset",
14262 + offset: 0x1000000 - 0x40000, /* Warning, this is fixed later */
14263 + mask_flags: MTD_WRITEABLE, /* force read-only */
14268 +static spinlock_t ipaq_vpp_lock = SPIN_LOCK_UNLOCKED;
14270 +static void h3xxx_set_vpp(struct map_info *map, int vpp)
14272 + static int nest = 0;
14274 + spin_lock(&ipaq_vpp_lock);
14280 + assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 1);
14282 + assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 0);
14283 + spin_unlock(&ipaq_vpp_lock);
14288 +#if defined(CONFIG_SA1100_JORNADA56X) || defined(CONFIG_SA1100_JORNADA720)
14289 +static unsigned long jornada_max_flash_size = 0x02000000;
14290 +static struct mtd_partition jornada_partitions[] = {
14292 + name: "Jornada boot firmware",
14293 + size: 0x00040000,
14295 + mask_flags: MTD_WRITEABLE, /* force read-only */
14297 + name: "Jornada root jffs2",
14298 + size: MTDPART_SIZ_FULL,
14299 + offset: 0x00040000,
14305 +static struct mtd_partition *parsed_parts;
14306 +static struct mtd_info *mymtd;
14308 +static unsigned long cs_phys[] = {
14309 +#ifdef CONFIG_ARCH_SA1100
14326 +static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
14328 +static int __init h1900_special_case(void);
14330 +int __init ipaq_mtd_init(void)
14332 + struct mtd_partition *parts = NULL;
14333 + int nb_parts = 0;
14334 + int parsed_nr_parts = 0;
14335 + const char *part_type;
14336 + int i; /* used when we have >1 flash chips */
14337 + unsigned long tot_flashsize = 0; /* used when we have >1 flash chips */
14339 + /* Default flash bankwidth */
14340 + // ipaq_map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
14342 + if (machine_is_h1900())
14344 + /* For our intents, the h1900 is not a real iPAQ, so we special-case it. */
14345 + return h1900_special_case();
14348 + if (machine_is_h3100() || machine_is_h1900())
14349 + for(i=0; i<MAX_IPAQ_CS; i++)
14350 + ipaq_map[i].bankwidth = 2;
14352 + for(i=0; i<MAX_IPAQ_CS; i++)
14353 + ipaq_map[i].bankwidth = 4;
14356 + * Static partition definition selection
14358 + part_type = "static";
14360 + simple_map_init(&ipaq_map[0]);
14361 + simple_map_init(&ipaq_map[1]);
14363 +#ifdef CONFIG_IPAQ_HANDHELD
14364 + if (machine_is_ipaq()) {
14365 + parts = h3xxx_partitions;
14366 + nb_parts = ARRAY_SIZE(h3xxx_partitions);
14367 + for(i=0; i<MAX_IPAQ_CS; i++) {
14368 + ipaq_map[i].size = h3xxx_max_flash_size;
14369 + ipaq_map[i].set_vpp = h3xxx_set_vpp;
14370 + ipaq_map[i].phys = cs_phys[i];
14371 + ipaq_map[i].virt = (void __iomem *)__ioremap(cs_phys[i], 0x04000000, 0, 1);
14372 + if (machine_is_h3100 () || machine_is_h1900())
14373 + ipaq_map[i].bankwidth = 2;
14375 + if (machine_is_h3600()) {
14376 + /* No asset partition here */
14377 + h3xxx_partitions[1].size += 0x40000;
14382 +#ifdef CONFIG_ARCH_H5400
14383 + if (machine_is_h5400()) {
14384 + ipaq_map[0].size = 0x02000000;
14385 + ipaq_map[1].size = 0x02000000;
14386 + ipaq_map[1].phys = 0x02000000;
14387 + ipaq_map[1].virt = ipaq_map[0].virt + 0x02000000;
14390 +#ifdef CONFIG_ARCH_H1900
14391 + if (machine_is_h1900()) {
14392 + ipaq_map[0].size = 0x00400000;
14393 + ipaq_map[1].size = 0x02000000;
14394 + ipaq_map[1].phys = 0x00080000;
14395 + ipaq_map[1].virt = ipaq_map[0].virt + 0x00080000;
14399 +#ifdef CONFIG_SA1100_JORNADA56X
14400 + if (machine_is_jornada56x()) {
14401 + parts = jornada_partitions;
14402 + nb_parts = ARRAY_SIZE(jornada_partitions);
14403 + ipaq_map[0].size = jornada_max_flash_size;
14404 + ipaq_map[0].set_vpp = jornada56x_set_vpp;
14405 + ipaq_map[0].virt = (__u32)__ioremap(0x0, 0x04000000, 0, 1);
14408 +#ifdef CONFIG_SA1100_JORNADA720
14409 + if (machine_is_jornada720()) {
14410 + parts = jornada_partitions;
14411 + nb_parts = ARRAY_SIZE(jornada_partitions);
14412 + ipaq_map[0].size = jornada_max_flash_size;
14413 + ipaq_map[0].set_vpp = jornada720_set_vpp;
14418 + if (machine_is_ipaq()) { /* for iPAQs only */
14419 + for(i=0; i<MAX_IPAQ_CS; i++) {
14420 + printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with CFI.\n", ipaq_map[i].bankwidth*8, ipaq_map[i].virt);
14421 + my_sub_mtd[i] = do_map_probe("cfi_probe", &ipaq_map[i]);
14422 + if (!my_sub_mtd[i]) {
14423 + printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with JEDEC.\n", ipaq_map[i].bankwidth*8, ipaq_map[i].virt);
14424 + my_sub_mtd[i] = do_map_probe("jedec_probe", &ipaq_map[i]);
14426 + if (!my_sub_mtd[i]) {
14427 + printk(KERN_NOTICE "iPAQ flash: failed to find flash.\n");
14433 + printk(KERN_NOTICE "iPAQ flash: found %d bytes\n", my_sub_mtd[i]->size);
14435 + /* do we really need this debugging? --joshua 20030703 */
14436 + // printk("my_sub_mtd[%d]=%p\n", i, my_sub_mtd[i]);
14437 + my_sub_mtd[i]->owner = THIS_MODULE;
14438 + tot_flashsize += my_sub_mtd[i]->size;
14440 +#ifdef CONFIG_MTD_CONCAT
14441 + /* fix the asset location */
14442 +# ifdef CONFIG_LAB
14443 + h3xxx_partitions[1].size = tot_flashsize - 0x40000 - 0x80000 /* extra big boot block */;
14445 + h3xxx_partitions[1].size = tot_flashsize - 2 * 0x40000;
14447 + h3xxx_partitions[2].offset = tot_flashsize - 0x40000;
14448 + /* and concat the devices */
14449 + mymtd = mtd_concat_create(&my_sub_mtd[0], i,
14452 + printk("Cannot create iPAQ concat device\n");
14456 + mymtd = my_sub_mtd[0];
14459 + *In the very near future, command line partition parsing
14460 + * will use the device name as 'mtd-id' instead of a value
14461 + * passed to the parse_cmdline_partitions() routine. Since
14462 + * the bootldr says 'ipaq', make sure it continues to work.
14464 + mymtd->name = "ipaq";
14466 + if ((machine_is_h3600())) {
14467 +# ifdef CONFIG_LAB
14468 + h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x80000;
14470 + h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000;
14474 +# ifdef CONFIG_LAB
14475 + h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000 - 0x80000; /* extra big boot block */
14477 + h3xxx_partitions[1].size = my_sub_mtd[0]->size - 2*0x40000;
14479 + h3xxx_partitions[2].offset = my_sub_mtd[0]->size - 0x40000;
14482 + if (my_sub_mtd[1]) {
14483 +# ifdef CONFIG_LAB
14484 + h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x80000;
14486 + h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x40000;
14488 + h3xxx_partitions_bank2[1].offset = my_sub_mtd[1]->size - 0x40000;
14494 + * Now let's probe for the actual flash. Do it here since
14495 + * specific machine settings might have been set above.
14497 + printk(KERN_NOTICE "IPAQ flash: probing %d-bit flash bus, window=%lx\n", ipaq_map[0].bankwidth*8, ipaq_map[0].virt);
14498 + mymtd = do_map_probe("cfi_probe", &ipaq_map[0]);
14501 + mymtd->owner = THIS_MODULE;
14506 + * Dynamic partition selection stuff (might override the static ones)
14509 + i = parse_mtd_partitions(mymtd, part_probes, &parsed_parts, 0);
14512 + nb_parts = parsed_nr_parts = i;
14513 + parts = parsed_parts;
14514 + part_type = "dynamic";
14518 + printk(KERN_NOTICE "IPAQ flash: no partition info available, registering whole flash at once\n");
14519 + add_mtd_device(mymtd);
14520 +#ifndef CONFIG_MTD_CONCAT
14521 + if (my_sub_mtd[1])
14522 + add_mtd_device(my_sub_mtd[1]);
14525 + printk(KERN_NOTICE "Using %s partition definition\n", part_type);
14526 + add_mtd_partitions(mymtd, parts, nb_parts);
14527 +#ifndef CONFIG_MTD_CONCAT
14528 + if (my_sub_mtd[1])
14529 + add_mtd_partitions(my_sub_mtd[1], h3xxx_partitions_bank2, ARRAY_SIZE(h3xxx_partitions_bank2));
14536 +static void __exit ipaq_mtd_cleanup(void)
14541 + del_mtd_partitions(mymtd);
14542 +#ifndef CONFIG_MTD_CONCAT
14543 + if (my_sub_mtd[1])
14544 + del_mtd_partitions(my_sub_mtd[1]);
14546 + map_destroy(mymtd);
14547 +#ifdef CONFIG_MTD_CONCAT
14548 + for(i=0; i<MAX_IPAQ_CS; i++)
14550 + for(i=1; i<MAX_IPAQ_CS; i++)
14553 + if (my_sub_mtd[i])
14554 + map_destroy(my_sub_mtd[i]);
14556 + if (parsed_parts)
14557 + kfree(parsed_parts);
14561 +static int __init h1900_special_case(void)
14563 + /* The iPAQ h1900 is a special case - it has weird ROM. */
14564 + simple_map_init(&ipaq_map[0]);
14565 + ipaq_map[0].size = 0x80000;
14566 + ipaq_map[0].set_vpp = h3xxx_set_vpp;
14567 + ipaq_map[0].phys = 0x0;
14568 + ipaq_map[0].virt = (void __iomem *)__ioremap(0x0, 0x04000000, 0, 1);
14569 + ipaq_map[0].bankwidth = 2;
14571 + printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with JEDEC.\n", ipaq_map[0].bankwidth*8, ipaq_map[0].virt);
14572 + mymtd = do_map_probe("jedec_probe", &ipaq_map[0]);
14575 + add_mtd_device(mymtd);
14576 + printk(KERN_NOTICE "iPAQ flash: registered h1910 flash\n");
14581 +module_init(ipaq_mtd_init);
14582 +module_exit(ipaq_mtd_cleanup);
14584 +MODULE_AUTHOR("Jamey Hicks");
14585 +MODULE_DESCRIPTION("IPAQ CFI map driver");
14586 +MODULE_LICENSE("MIT");
14587 Index: linux-2.6.5/drivers/mtd/maps/iq80310.c
14588 ===================================================================
14589 --- linux-2.6.5.orig/drivers/mtd/maps/iq80310.c 2004-04-03 22:38:15.000000000 -0500
14590 +++ linux-2.6.5/drivers/mtd/maps/iq80310.c 2005-02-01 17:11:17.000000000 -0500
14593 - * $Id: iq80310.c,v 1.17 2003/06/23 11:48:18 dwmw2 Exp $
14594 + * $Id: iq80310.c,v 1.19 2004/09/16 23:27:13 gleixner Exp $
14596 * Mapping for the Intel XScale IQ80310 evaluation board
14599 static struct map_info iq80310_map = {
14600 .name = "IQ80310 flash",
14601 .size = WINDOW_SIZE,
14602 - .buswidth = BUSWIDTH,
14603 + .bankwidth = BUSWIDTH,
14604 .phys = WINDOW_ADDR
14608 int parsed_nr_parts = 0;
14611 - iq80310_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
14612 + iq80310_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE);
14613 if (!iq80310_map.virt) {
14614 printk("Failed to ioremap\n");
14616 Index: linux-2.6.5/drivers/mtd/maps/ixp2000.c
14617 ===================================================================
14618 --- linux-2.6.5.orig/drivers/mtd/maps/ixp2000.c 1969-12-31 19:00:00.000000000 -0500
14619 +++ linux-2.6.5/drivers/mtd/maps/ixp2000.c 2005-02-01 17:11:17.000000000 -0500
14622 + * $Id: ixp2000.c,v 1.3 2004/09/16 23:27:13 gleixner Exp $
14624 + * drivers/mtd/maps/ixp2000.c
14626 + * Mapping for the Intel XScale IXP2000 based systems
14628 + * Copyright (C) 2002 Intel Corp.
14629 + * Copyright (C) 2003-2004 MontaVista Software, Inc.
14631 + * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
14632 + * Maintainer: Deepak Saxena <dsaxena@plexity.net>
14634 + * This program is free software; you can redistribute it and/or modify
14635 + * it under the terms of the GNU General Public License version 2 as
14636 + * published by the Free Software Foundation.
14640 +#include <linux/module.h>
14641 +#include <linux/types.h>
14642 +#include <linux/init.h>
14643 +#include <linux/kernel.h>
14644 +#include <linux/string.h>
14645 +#include <linux/mtd/mtd.h>
14646 +#include <linux/mtd/map.h>
14647 +#include <linux/mtd/partitions.h>
14648 +#include <linux/ioport.h>
14649 +#include <linux/device.h>
14651 +#include <asm/io.h>
14652 +#include <asm/hardware.h>
14653 +#include <asm/mach-types.h>
14654 +#include <asm/mach/flash.h>
14656 +#include <linux/reboot.h>
14658 +struct ixp2000_flash_info {
14659 + struct mtd_info *mtd;
14660 + struct map_info map;
14661 + struct mtd_partition *partitions;
14662 + struct resource *res;
14666 +static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
14668 + unsigned long (*set_bank)(unsigned long) =
14669 + (unsigned long(*)(unsigned long))map->map_priv_2;
14671 + return (set_bank ? set_bank(ofs) : ofs);
14676 + * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which
14677 + * causes the lower address bits to be XORed with 0x11 on 8 bit accesses
14678 + * and XORed with 0x10 on 16 bit accesses. See the spec update, erratum 44.
14680 +static int erratum44_workaround = 0;
14682 +static inline unsigned long address_fix8_write(unsigned long addr)
14684 + if (erratum44_workaround) {
14685 + return (addr ^ 3);
14691 +#define address_fix8_write(x) (x)
14694 +static map_word ixp2000_flash_read8(struct map_info *map, unsigned long ofs)
14698 + val.x[0] = *((u8 *)(map->map_priv_1 + flash_bank_setup(map, ofs)));
14703 + * We can't use the standard memcpy due to the broken SlowPort
14704 + * address translation on rev A0 and A1 silicon and the fact that
14705 + * we have banked flash.
14707 +static void ixp2000_flash_copy_from(struct map_info *map, void *to,
14708 + unsigned long from, ssize_t len)
14710 + from = flash_bank_setup(map, from);
14712 + *(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++);
14715 +static void ixp2000_flash_write8(struct map_info *map, map_word d, unsigned long ofs)
14717 + *(__u8 *) (address_fix8_write(map->map_priv_1 +
14718 + flash_bank_setup(map, ofs))) = d.x[0];
14721 +static void ixp2000_flash_copy_to(struct map_info *map, unsigned long to,
14722 + const void *from, ssize_t len)
14724 + to = flash_bank_setup(map, to);
14726 + unsigned long tmp = address_fix8_write(map->map_priv_1 + to++);
14727 + *(__u8 *)(tmp) = *(__u8 *)(from++);
14732 +static int ixp2000_flash_remove(struct device *_dev)
14734 + struct platform_device *dev = to_platform_device(_dev);
14735 + struct flash_platform_data *plat = dev->dev.platform_data;
14736 + struct ixp2000_flash_info *info = dev_get_drvdata(&dev->dev);
14738 + dev_set_drvdata(&dev->dev, NULL);
14744 + del_mtd_partitions(info->mtd);
14745 + map_destroy(info->mtd);
14747 + if (info->map.map_priv_1)
14748 + iounmap((void *) info->map.map_priv_1);
14750 + if (info->partitions) {
14751 + kfree(info->partitions); }
14754 + release_resource(info->res);
14755 + kfree(info->res);
14765 +static int ixp2000_flash_probe(struct device *_dev)
14767 + static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
14768 + struct platform_device *dev = to_platform_device(_dev);
14769 + struct ixp2000_flash_data *ixp_data = dev->dev.platform_data;
14770 + struct flash_platform_data *plat;
14771 + struct ixp2000_flash_info *info;
14772 + unsigned long window_size;
14778 + plat = ixp_data->platform_data;
14782 + window_size = dev->resource->end - dev->resource->start + 1;
14783 + dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n",
14784 + ixp_data->nr_banks, ((u32)window_size >> 20));
14786 + if (plat->width != 1) {
14787 + dev_err(_dev, "IXP2000 MTD map only supports 8-bit mode, asking for %d\n",
14788 + plat->width * 8);
14792 + info = kmalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL);
14797 + memzero(info, sizeof(struct ixp2000_flash_info));
14799 + dev_set_drvdata(&dev->dev, info);
14802 + * Tell the MTD layer we're not 1:1 mapped so that it does
14803 + * not attempt to do a direct access on us.
14805 + info->map.phys = NO_XIP;
14807 + info->nr_banks = ixp_data->nr_banks;
14808 + info->map.size = ixp_data->nr_banks * window_size;
14809 + info->map.bankwidth = 1;
14812 + * map_priv_2 is used to store a ptr to to the bank_setup routine
14814 + info->map.map_priv_2 = (void __iomem *) ixp_data->bank_setup;
14816 + info->map.name = dev->dev.bus_id;
14817 + info->map.read = ixp2000_flash_read8;
14818 + info->map.write = ixp2000_flash_write8;
14819 + info->map.copy_from = ixp2000_flash_copy_from;
14820 + info->map.copy_to = ixp2000_flash_copy_to;
14822 + info->res = request_mem_region(dev->resource->start,
14823 + dev->resource->end - dev->resource->start + 1,
14824 + dev->dev.bus_id);
14825 + if (!info->res) {
14826 + dev_err(_dev, "Could not reserve memory region\n");
14831 + info->map.map_priv_1 =
14832 + (void __iomem *) ioremap(dev->resource->start,
14833 + dev->resource->end - dev->resource->start + 1);
14834 + if (!info->map.map_priv_1) {
14835 + dev_err(_dev, "Failed to ioremap flash region\n");
14841 + * Setup read mode for FLASH
14843 + *IXP2000_SLOWPORT_FRM = 1;
14845 +#if defined(__ARMEB__)
14847 + * Enable erratum 44 workaround for NPUs with broken slowport
14850 + errata44_workaround = ixp2000_has_broken_slowport();
14851 + dev_info(_dev, "Erratum 44 workaround %s\n",
14852 + erratum44_workaround ? "enabled" : "disabled");
14855 + info->mtd = do_map_probe(plat->map_name, &info->map);
14856 + if (!info->mtd) {
14857 + dev_err(_dev, "map_probe failed\n");
14861 + info->mtd->owner = THIS_MODULE;
14863 + err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
14865 + err = add_mtd_partitions(info->mtd, info->partitions, err);
14867 + dev_err(_dev, "Could not parse partitions\n");
14876 + ixp2000_flash_remove(_dev);
14880 +static struct device_driver ixp2000_flash_driver = {
14881 + .name = "IXP2000-Flash",
14882 + .bus = &platform_bus_type,
14883 + .probe = &ixp2000_flash_probe,
14884 + .remove = &ixp2000_flash_remove
14887 +static int __init ixp2000_flash_init(void)
14889 + return driver_register(&ixp2000_flash_driver);
14892 +static void __exit ixp2000_flash_exit(void)
14894 + driver_unregister(&ixp2000_flash_driver);
14897 +module_init(ixp2000_flash_init);
14898 +module_exit(ixp2000_flash_exit);
14899 +MODULE_LICENSE("GPL");
14900 +MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
14902 Index: linux-2.6.5/drivers/mtd/maps/ixp4xx.c
14903 ===================================================================
14904 --- linux-2.6.5.orig/drivers/mtd/maps/ixp4xx.c 1969-12-31 19:00:00.000000000 -0500
14905 +++ linux-2.6.5/drivers/mtd/maps/ixp4xx.c 2005-02-01 17:11:17.000000000 -0500
14908 + * $Id: ixp4xx.c,v 1.6 2004/09/17 00:25:06 gleixner Exp $
14910 + * drivers/mtd/maps/ixp4xx.c
14912 + * MTD Map file for IXP4XX based systems. Please do not make per-board
14913 + * changes in here. If your board needs special setup, do it in your
14914 + * platform level code in arch/arm/mach-ixp4xx/board-setup.c
14916 + * Original Author: Intel Corporation
14917 + * Maintainer: Deepak Saxena <dsaxena@mvista.com>
14919 + * Copyright (C) 2002 Intel Corporation
14920 + * Copyright (C) 2003-2004 MontaVista Software, Inc.
14924 +#include <linux/module.h>
14925 +#include <linux/types.h>
14926 +#include <linux/init.h>
14927 +#include <linux/kernel.h>
14928 +#include <linux/string.h>
14929 +#include <linux/mtd/mtd.h>
14930 +#include <linux/mtd/map.h>
14931 +#include <linux/mtd/partitions.h>
14932 +#include <linux/ioport.h>
14933 +#include <linux/device.h>
14934 +#include <asm/io.h>
14935 +#include <asm/mach-types.h>
14936 +#include <asm/mach/flash.h>
14938 +#include <linux/reboot.h>
14941 +#define BYTE0(h) ((h) & 0xFF)
14942 +#define BYTE1(h) (((h) >> 8) & 0xFF)
14944 +#define BYTE0(h) (((h) >> 8) & 0xFF)
14945 +#define BYTE1(h) ((h) & 0xFF)
14948 +static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
14951 + val.x[0] = *(__u16 *) (map->map_priv_1 + ofs);
14956 + * The IXP4xx expansion bus only allows 16-bit wide acceses
14957 + * when attached to a 16-bit wide device (such as the 28F128J3A),
14958 + * so we can't just memcpy_fromio().
14960 +static void ixp4xx_copy_from(struct map_info *map, void *to,
14961 + unsigned long from, ssize_t len)
14964 + u8 *dest = (u8 *) to;
14965 + u16 *src = (u16 *) (map->map_priv_1 + from);
14968 + for (i = 0; i < (len / 2); i++) {
14970 + dest[i * 2] = BYTE0(data);
14971 + dest[i * 2 + 1] = BYTE1(data);
14975 + dest[len - 1] = BYTE0(src[i]);
14979 + * Unaligned writes are ignored, causing the 8-bit
14980 + * probe to fail and proceed to the 16-bit probe (which succeeds).
14982 +static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
14985 + *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
14989 + * Fast write16 function without the probing check above
14991 +static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
14993 + *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
14996 +struct ixp4xx_flash_info {
14997 + struct mtd_info *mtd;
14998 + struct map_info map;
14999 + struct mtd_partition *partitions;
15000 + struct resource *res;
15003 +static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
15005 +static int ixp4xx_flash_remove(struct device *_dev)
15007 + struct platform_device *dev = to_platform_device(_dev);
15008 + struct flash_platform_data *plat = dev->dev.platform_data;
15009 + struct ixp4xx_flash_info *info = dev_get_drvdata(&dev->dev);
15012 + dev_set_drvdata(&dev->dev, NULL);
15018 + * This is required for a soft reboot to work.
15021 + ixp4xx_write16(&info->map, d, 0x55 * 0x2);
15024 + del_mtd_partitions(info->mtd);
15025 + map_destroy(info->mtd);
15027 + if (info->map.map_priv_1)
15028 + iounmap((void *) info->map.map_priv_1);
15030 + if (info->partitions)
15031 + kfree(info->partitions);
15034 + release_resource(info->res);
15035 + kfree(info->res);
15041 + /* Disable flash write */
15042 + *IXP4XX_EXP_CS0 &= ~IXP4XX_FLASH_WRITABLE;
15047 +static int ixp4xx_flash_probe(struct device *_dev)
15049 + struct platform_device *dev = to_platform_device(_dev);
15050 + struct flash_platform_data *plat = dev->dev.platform_data;
15051 + struct ixp4xx_flash_info *info;
15057 + if (plat->init) {
15058 + err = plat->init();
15063 + info = kmalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL);
15068 + memzero(info, sizeof(struct ixp4xx_flash_info));
15070 + dev_set_drvdata(&dev->dev, info);
15073 + * Enable flash write
15074 + * TODO: Move this out to board specific code
15076 + *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
15079 + * Tell the MTD layer we're not 1:1 mapped so that it does
15080 + * not attempt to do a direct access on us.
15082 + info->map.phys = NO_XIP;
15083 + info->map.size = dev->resource->end - dev->resource->start + 1;
15086 + * We only support 16-bit accesses for now. If and when
15087 + * any board use 8-bit access, we'll fixup the driver to
15090 + info->map.bankwidth = 2;
15091 + info->map.name = dev->dev.bus_id;
15092 + info->map.read = ixp4xx_read16,
15093 + info->map.write = ixp4xx_probe_write16,
15094 + info->map.copy_from = ixp4xx_copy_from,
15096 + info->res = request_mem_region(dev->resource->start,
15097 + dev->resource->end - dev->resource->start + 1,
15099 + if (!info->res) {
15100 + printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n");
15105 + info->map.map_priv_1 =
15106 + (void __iomem *) ioremap(dev->resource->start,
15107 + dev->resource->end - dev->resource->start + 1);
15108 + if (!info->map.map_priv_1) {
15109 + printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n");
15114 + info->mtd = do_map_probe(plat->map_name, &info->map);
15115 + if (!info->mtd) {
15116 + printk(KERN_ERR "IXP4XXFlash: map_probe failed\n");
15120 + info->mtd->owner = THIS_MODULE;
15122 + /* Use the fast version */
15123 + info->map.write = ixp4xx_write16,
15125 + err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
15127 + err = add_mtd_partitions(info->mtd, info->partitions, err);
15129 + printk(KERN_ERR "Could not parse partitions\n");
15138 + ixp4xx_flash_remove(_dev);
15142 +static struct device_driver ixp4xx_flash_driver = {
15143 + .name = "IXP4XX-Flash",
15144 + .bus = &platform_bus_type,
15145 + .probe = ixp4xx_flash_probe,
15146 + .remove = ixp4xx_flash_remove,
15149 +static int __init ixp4xx_flash_init(void)
15151 + return driver_register(&ixp4xx_flash_driver);
15154 +static void __exit ixp4xx_flash_exit(void)
15156 + driver_unregister(&ixp4xx_flash_driver);
15160 +module_init(ixp4xx_flash_init);
15161 +module_exit(ixp4xx_flash_exit);
15163 +MODULE_LICENSE("GPL");
15164 +MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems")
15165 +MODULE_AUTHOR("Deepak Saxena");
15167 Index: linux-2.6.5/drivers/mtd/maps/l440gx.c
15168 ===================================================================
15169 --- linux-2.6.5.orig/drivers/mtd/maps/l440gx.c 2004-04-03 22:37:59.000000000 -0500
15170 +++ linux-2.6.5/drivers/mtd/maps/l440gx.c 2005-02-01 17:11:17.000000000 -0500
15173 - * $Id: l440gx.c,v 1.12 2003/05/21 12:45:19 dwmw2 Exp $
15174 + * $Id: l440gx.c,v 1.14 2004/09/16 23:27:13 gleixner Exp $
15176 * BIOS Flash chip on Intel 440GX board.
15179 struct map_info l440gx_map = {
15180 .name = "L440GX BIOS",
15181 .size = WINDOW_SIZE,
15182 - .buswidth = BUSWIDTH,
15183 + .bankwidth = BUSWIDTH,
15184 .phys = WINDOW_ADDR,
15186 /* FIXME verify that this is the
15191 - l440gx_map.virt = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
15192 + l440gx_map.virt = (void __iomem *)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
15194 if (!l440gx_map.virt) {
15195 printk(KERN_WARNING "Failed to ioremap L440GX flash region\n");
15196 Index: linux-2.6.5/drivers/mtd/maps/lasat.c
15197 ===================================================================
15198 --- linux-2.6.5.orig/drivers/mtd/maps/lasat.c 2004-04-03 22:36:25.000000000 -0500
15199 +++ linux-2.6.5/drivers/mtd/maps/lasat.c 2005-02-01 17:11:17.000000000 -0500
15202 - * Flash device on lasat 100 and 200 boards
15203 + * Flash device on Lasat 100 and 200 boards
15205 - * Presumably (C) 2002 Brian Murphy <brian@murphy.dk> or whoever he
15207 + * (C) 2002 Brian Murphy <brian@murphy.dk>
15209 * This program is free software; you can redistribute it and/or
15210 * modify it under the terms of the GNU General Public License version
15211 * 2 as published by the Free Software Foundation.
15213 - * $Id: lasat.c,v 1.5 2003/05/21 12:45:19 dwmw2 Exp $
15214 + * $Id: lasat.c,v 1.8 2004/09/16 23:27:13 gleixner Exp $
15218 @@ -22,44 +21,53 @@
15219 #include <linux/mtd/partitions.h>
15220 #include <linux/config.h>
15221 #include <asm/lasat/lasat.h>
15222 -#include <asm/lasat/lasat_mtd.h>
15224 -static struct mtd_info *mymtd;
15226 -static struct map_info sp_map = {
15227 - .name = "SP flash",
15230 +static struct mtd_info *lasat_mtd;
15232 static struct mtd_partition partition_info[LASAT_MTD_LAST];
15233 static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
15235 -static int __init init_sp(void)
15236 +static void lasat_set_vpp(struct map_info *map, int vpp)
15239 - /* this does not play well with the old flash code which
15240 - * protects and uprotects the flash when necessary */
15241 - /* FIXME: Implement set_vpp() */
15242 - printk(KERN_NOTICE "Unprotecting flash\n");
15243 - *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
15245 - sp_map.virt = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
15246 - sp_map.phys = virt_to_phys(sp_map.virt);
15247 - sp_map.size = lasat_board_info.li_flash_size;
15249 + *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
15251 + *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit);
15254 +static struct map_info lasat_map = {
15255 + .name = "LASAT flash",
15257 + .set_vpp = lasat_set_vpp
15260 - simple_map_init(&sp_map);
15261 +static int __init init_lasat(void)
15264 + /* since we use AMD chips and set_vpp is not implimented
15265 + * for these (yet) we still have to permanently enable flash write */
15266 + printk(KERN_NOTICE "Unprotecting flash\n");
15267 + ENABLE_VPP((&lasat_map));
15269 + lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
15270 + lasat_map.virt = (void __iomem *)ioremap_nocache(
15271 + lasat_map.phys, lasat_board_info.li_flash_size);
15272 + lasat_map.size = lasat_board_info.li_flash_size;
15274 - printk(KERN_NOTICE "sp flash device: %lx at %lx\n",
15275 - sp_map.size, sp_map.phys);
15276 + simple_map_init(&lasat_map);
15278 for (i=0; i < LASAT_MTD_LAST; i++)
15279 partition_info[i].name = lasat_mtd_partnames[i];
15281 - mymtd = do_map_probe("cfi_probe", &sp_map);
15283 + lasat_mtd = do_map_probe("cfi_probe", &lasat_map);
15286 + lasat_mtd = do_map_probe("jedec_probe", &lasat_map);
15289 u32 size, offset = 0;
15291 - mymtd->owner = THIS_MODULE;
15292 + lasat_mtd->owner = THIS_MODULE;
15294 for (i=0; i < LASAT_MTD_LAST; i++) {
15295 size = lasat_flash_partition_size(i);
15296 @@ -68,26 +76,26 @@
15300 - add_mtd_partitions( mymtd, partition_info, LASAT_MTD_LAST );
15301 + add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST );
15308 -static void __exit cleanup_sp(void)
15309 +static void __exit cleanup_lasat(void)
15312 - del_mtd_partitions(mymtd);
15313 - map_destroy(mymtd);
15315 + del_mtd_partitions(lasat_mtd);
15316 + map_destroy(lasat_mtd);
15318 - if (sp_map.virt) {
15320 + if (lasat_map.virt) {
15321 + lasat_map.virt = 0;
15325 -module_init(init_sp);
15326 -module_exit(cleanup_sp);
15327 +module_init(init_lasat);
15328 +module_exit(cleanup_lasat);
15330 MODULE_LICENSE("GPL");
15331 MODULE_AUTHOR("Brian Murphy <brian@murphy.dk>");
15332 Index: linux-2.6.5/drivers/mtd/maps/lubbock-flash.c
15333 ===================================================================
15334 --- linux-2.6.5.orig/drivers/mtd/maps/lubbock-flash.c 2004-04-03 22:37:37.000000000 -0500
15335 +++ linux-2.6.5/drivers/mtd/maps/lubbock-flash.c 2005-02-01 17:11:17.000000000 -0500
15338 - * $Id: lubbock-flash.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $
15339 + * $Id: lubbock-flash.c,v 1.17 2004/09/16 23:27:13 gleixner Exp $
15341 * Map driver for the Lubbock developer platform.
15343 @@ -15,11 +15,12 @@
15344 #include <linux/types.h>
15345 #include <linux/kernel.h>
15346 #include <linux/init.h>
15347 -#include <asm/io.h>
15348 #include <linux/mtd/mtd.h>
15349 #include <linux/mtd/map.h>
15350 #include <linux/mtd/partitions.h>
15351 +#include <asm/io.h>
15352 #include <asm/hardware.h>
15353 +#include <asm/arch/lubbock.h>
15356 #define ROM_ADDR 0x00000000
15357 @@ -27,12 +28,19 @@
15359 #define WINDOW_SIZE 64*1024*1024
15361 +static void lubbock_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len)
15363 + consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
15366 static struct map_info lubbock_maps[2] = { {
15367 .size = WINDOW_SIZE,
15368 .phys = 0x00000000,
15369 + .inval_cache = lubbock_map_inval_cache,
15371 .size = WINDOW_SIZE,
15372 .phys = 0x04000000,
15373 + .inval_cache = lubbock_map_inval_cache,
15376 static struct mtd_partition lubbock_partitions[] = {
15377 @@ -60,10 +68,10 @@
15379 static int __init init_lubbock(void)
15381 - int flashboot = (CONF_SWITCHES & 1);
15382 + int flashboot = (LUB_CONF_SWITCHES & 1);
15385 - lubbock_maps[0].buswidth = lubbock_maps[1].buswidth =
15386 + lubbock_maps[0].bankwidth = lubbock_maps[1].bankwidth =
15387 (BOOT_DEF & 1) ? 2 : 4;
15389 /* Compensate for the nROMBT switch which swaps the flash banks */
15390 @@ -74,23 +82,28 @@
15391 lubbock_maps[flashboot].name = "Lubbock Boot ROM";
15393 for (i = 0; i < 2; i++) {
15394 - lubbock_maps[i].virt = (unsigned long)ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
15395 + lubbock_maps[i].virt = (void __iomem *)ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
15396 if (!lubbock_maps[i].virt) {
15397 printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name);
15402 + lubbock_maps[i].cached = ioremap_cached(lubbock_maps[i].phys, WINDOW_SIZE);
15403 + if (!lubbock_maps[i].cached)
15404 + printk(KERN_WARNING "Failed to ioremap cached %s\n", lubbock_maps[i].name);
15405 simple_map_init(&lubbock_maps[i]);
15407 - printk(KERN_NOTICE "Probing %s at physical address 0x%08lx (%d-bit buswidth)\n",
15408 + printk(KERN_NOTICE "Probing %s at physical address 0x%08lx (%d-bit bankwidth)\n",
15409 lubbock_maps[i].name, lubbock_maps[i].phys,
15410 - lubbock_maps[i].buswidth * 8);
15411 + lubbock_maps[i].bankwidth * 8);
15413 mymtds[i] = do_map_probe("cfi_probe", &lubbock_maps[i]);
15416 iounmap((void *)lubbock_maps[i].virt);
15417 + if (lubbock_maps[i].cached)
15418 + iounmap(lubbock_maps[i].cached);
15422 @@ -137,6 +150,8 @@
15424 map_destroy(mymtds[i]);
15425 iounmap((void *)lubbock_maps[i].virt);
15426 + if (lubbock_maps[i].cached)
15427 + iounmap(lubbock_maps[i].cached);
15429 if (parsed_parts[i])
15430 kfree(parsed_parts[i]);
15431 Index: linux-2.6.5/drivers/mtd/maps/map_funcs.c
15432 ===================================================================
15433 --- linux-2.6.5.orig/drivers/mtd/maps/map_funcs.c 2005-02-01 16:55:39.000000000 -0500
15434 +++ linux-2.6.5/drivers/mtd/maps/map_funcs.c 2005-02-01 17:11:17.000000000 -0500
15437 - * $Id: map_funcs.c,v 1.2 2003/05/21 15:15:07 dwmw2 Exp $
15438 + * $Id: map_funcs.c,v 1.9 2004/07/13 22:33:15 dwmw2 Exp $
15440 * Out-of-line map I/O functions for simple maps when CONFIG_COMPLEX_MAPPINGS
15444 #include <linux/kernel.h>
15445 #include <linux/module.h>
15446 -#include <linux/config.h>
15447 -#include <linux/types.h>
15448 -#include <linux/string.h>
15449 -#include <asm/io.h>
15451 #include <linux/mtd/map.h>
15452 -#include <linux/mtd/cfi.h>
15454 -static u8 simple_map_read8(struct map_info *map, unsigned long ofs)
15455 +static map_word simple_map_read(struct map_info *map, unsigned long ofs)
15457 - return __raw_readb(map->virt + ofs);
15458 + return inline_map_read(map, ofs);
15461 -static u16 simple_map_read16(struct map_info *map, unsigned long ofs)
15462 +static void simple_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
15464 - return __raw_readw(map->virt + ofs);
15467 -static u32 simple_map_read32(struct map_info *map, unsigned long ofs)
15469 - return __raw_readl(map->virt + ofs);
15472 -static u64 simple_map_read64(struct map_info *map, unsigned long ofs)
15474 -#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */
15478 - return __raw_readll(map->virt + ofs);
15482 -static void simple_map_write8(struct map_info *map, u8 datum, unsigned long ofs)
15484 - __raw_writeb(datum, map->virt + ofs);
15488 -static void simple_map_write16(struct map_info *map, u16 datum, unsigned long ofs)
15490 - __raw_writew(datum, map->virt + ofs);
15494 -static void simple_map_write32(struct map_info *map, u32 datum, unsigned long ofs)
15496 - __raw_writel(datum, map->virt + ofs);
15500 -static void simple_map_write64(struct map_info *map, u64 datum, unsigned long ofs)
15502 -#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */
15505 - __raw_writell(datum, map->virt + ofs);
15507 -#endif /* CFI_B8 */
15508 + inline_map_write(map, datum, ofs);
15511 static void simple_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
15513 - memcpy_fromio(to, (char *)map->virt + from, len);
15514 + inline_map_copy_from(map, to, from, len);
15517 static void simple_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
15519 - memcpy_toio((char *)map->virt + to, from, len);
15520 + inline_map_copy_to(map, to, from, len);
15523 void simple_map_init(struct map_info *map)
15525 - map->read8 = simple_map_read8;
15526 - map->read16 = simple_map_read16;
15527 - map->read32 = simple_map_read32;
15528 - map->read64 = simple_map_read64;
15529 - map->write8 = simple_map_write8;
15530 - map->write16 = simple_map_write16;
15531 - map->write32 = simple_map_write32;
15532 - map->write64 = simple_map_write64;
15533 + BUG_ON(!map_bankwidth_supported(map->bankwidth));
15535 + map->read = simple_map_read;
15536 + map->write = simple_map_write;
15537 map->copy_from = simple_map_copy_from;
15538 map->copy_to = simple_map_copy_to;
15540 Index: linux-2.6.5/drivers/mtd/maps/mbx860.c
15541 ===================================================================
15542 --- linux-2.6.5.orig/drivers/mtd/maps/mbx860.c 2004-04-03 22:36:54.000000000 -0500
15543 +++ linux-2.6.5/drivers/mtd/maps/mbx860.c 2005-02-01 17:11:17.000000000 -0500
15546 - * $Id: mbx860.c,v 1.5 2003/05/21 12:45:19 dwmw2 Exp $
15547 + * $Id: mbx860.c,v 1.7 2004/09/16 23:27:13 gleixner Exp $
15549 * Handle mapping of the flash on MBX860 boards
15551 @@ -54,13 +54,13 @@
15552 .name = "MBX flash",
15553 .size = WINDOW_SIZE,
15554 .phys = WINDOW_ADDR,
15559 int __init init_mbx(void)
15561 printk(KERN_NOTICE "Motorola MBX flash device: 0x%x at 0x%x\n", WINDOW_SIZE*4, WINDOW_ADDR);
15562 - mbx_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
15563 + mbx_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
15565 if (!mbx_map.virt) {
15566 printk("Failed to ioremap\n");
15567 Index: linux-2.6.5/drivers/mtd/maps/mpc1211.c
15568 ===================================================================
15569 --- linux-2.6.5.orig/drivers/mtd/maps/mpc1211.c 1969-12-31 19:00:00.000000000 -0500
15570 +++ linux-2.6.5/drivers/mtd/maps/mpc1211.c 2005-02-01 17:11:17.000000000 -0500
15573 + * Flash on MPC-1211
15575 + * $Id: mpc1211.c,v 1.4 2004/09/16 23:27:13 gleixner Exp $
15577 + * (C) 2002 Interface, Saito.K & Jeanne
15582 +#include <linux/module.h>
15583 +#include <linux/types.h>
15584 +#include <linux/kernel.h>
15585 +#include <asm/io.h>
15586 +#include <linux/mtd/mtd.h>
15587 +#include <linux/mtd/map.h>
15588 +#include <linux/mtd/partitions.h>
15589 +#include <linux/config.h>
15591 +static struct mtd_info *flash_mtd;
15592 +static struct mtd_partition *parsed_parts;
15594 +struct map_info mpc1211_flash_map = {
15595 + .name = "MPC-1211 FLASH",
15600 +static struct mtd_partition mpc1211_partitions[] = {
15602 + .name = "IPL & ETH-BOOT",
15603 + .offset = 0x00000000,
15607 + .name = "Flash FS",
15608 + .offset = 0x00010000,
15609 + .size = MTDPART_SIZ_FULL,
15613 +static int __init init_mpc1211_maps(void)
15617 + mpc1211_flash_map.phys = 0;
15618 + mpc1211_flash_map.virt = (void __iomem *)P2SEGADDR(0);
15620 + simple_map_init(&mpc1211_flash_map);
15622 + printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n");
15623 + flash_mtd = do_map_probe("jedec_probe", &mpc1211_flash_map);
15624 + if (!flash_mtd) {
15625 + printk(KERN_NOTICE "Flash chips not detected at either possible location.\n");
15628 + printk(KERN_NOTICE "MPC-1211: Flash at 0x%08lx\n", mpc1211_flash_map.virt & 0x1fffffff);
15629 + flash_mtd->module = THIS_MODULE;
15631 + parsed_parts = mpc1211_partitions;
15632 + nr_parts = ARRAY_SIZE(mpc1211_partitions);
15634 + add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
15638 +static void __exit cleanup_mpc1211_maps(void)
15640 + if (parsed_parts)
15641 + del_mtd_partitions(flash_mtd);
15643 + del_mtd_device(flash_mtd);
15644 + map_destroy(flash_mtd);
15647 +module_init(init_mpc1211_maps);
15648 +module_exit(cleanup_mpc1211_maps);
15650 +MODULE_LICENSE("GPL");
15651 +MODULE_AUTHOR("Saito.K & Jeanne <ksaito@interface.co.jp>");
15652 +MODULE_DESCRIPTION("MTD map driver for MPC-1211 boards. Interface");
15653 Index: linux-2.6.5/drivers/mtd/maps/netsc520.c
15654 ===================================================================
15655 --- linux-2.6.5.orig/drivers/mtd/maps/netsc520.c 2004-04-03 22:37:41.000000000 -0500
15656 +++ linux-2.6.5/drivers/mtd/maps/netsc520.c 2005-02-01 17:11:17.000000000 -0500
15658 * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com)
15659 * based on sc520cdp.c by Sysgo Real-Time Solutions GmbH
15661 - * $Id: netsc520.c,v 1.9 2003/05/21 12:45:19 dwmw2 Exp $
15662 + * $Id: netsc520.c,v 1.11 2004/09/16 23:27:13 gleixner Exp $
15664 * This program is free software; you can redistribute it and/or modify
15665 * it under the terms of the GNU General Public License as published by
15667 static struct map_info netsc520_map = {
15668 .name = "netsc520 Flash Bank",
15669 .size = WINDOW_SIZE,
15672 .phys = WINDOW_ADDR,
15676 static int __init init_netsc520(void)
15678 printk(KERN_NOTICE "NetSc520 flash device: 0x%lx at 0x%lx\n", netsc520_map.size, netsc520_map.phys);
15679 - netsc520_map.virt = (unsigned long)ioremap_nocache(netsc520_map.phys, netsc520_map.size);
15680 + netsc520_map.virt = (void __iomem *)ioremap_nocache(netsc520_map.phys, netsc520_map.size);
15682 if (!netsc520_map.virt) {
15683 printk("Failed to ioremap_nocache\n");
15684 Index: linux-2.6.5/drivers/mtd/maps/nettel.c
15685 ===================================================================
15686 --- linux-2.6.5.orig/drivers/mtd/maps/nettel.c 2004-04-03 22:36:52.000000000 -0500
15687 +++ linux-2.6.5/drivers/mtd/maps/nettel.c 2005-02-01 17:11:17.000000000 -0500
15689 * (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com)
15690 * (C) Copyright 2001-2002, SnapGear (www.snapgear.com)
15692 - * $Id: nettel.c,v 1.4 2003/05/20 20:59:30 dwmw2 Exp $
15693 + * $Id: nettel.c,v 1.6 2004/09/16 23:27:13 gleixner Exp $
15696 /****************************************************************************/
15698 static struct map_info nettel_intel_map = {
15699 .name = "SnapGear Intel",
15701 - .buswidth = INTEL_BUSWIDTH,
15702 + .bankwidth = INTEL_BUSWIDTH,
15705 static struct mtd_partition nettel_intel_partitions[] = {
15706 @@ -103,7 +103,7 @@
15707 static struct map_info nettel_amd_map = {
15708 .name = "SnapGear AMD",
15709 .size = AMD_WINDOW_MAXSIZE,
15710 - .buswidth = AMD_BUSWIDTH,
15711 + .bankwidth = AMD_BUSWIDTH,
15714 static struct mtd_partition nettel_amd_partitions[] = {
15715 @@ -273,8 +273,7 @@
15716 __asm__ ("wbinvd");
15718 nettel_amd_map.phys = amdaddr;
15719 - nettel_amd_map.virt = (unsigned long)
15720 - ioremap_nocache(amdaddr, maxsize);
15721 + nettel_amd_map.virt = (void __iomem *) ioremap_nocache(amdaddr, maxsize);
15722 if (!nettel_amd_map.virt) {
15723 printk("SNAPGEAR: failed to ioremap() BOOTCS\n");
15725 Index: linux-2.6.5/drivers/mtd/maps/ocelot.c
15726 ===================================================================
15727 --- linux-2.6.5.orig/drivers/mtd/maps/ocelot.c 2004-04-03 22:38:22.000000000 -0500
15728 +++ linux-2.6.5/drivers/mtd/maps/ocelot.c 2005-02-01 17:11:17.000000000 -0500
15731 - * $Id: ocelot.c,v 1.12 2003/05/21 12:45:19 dwmw2 Exp $
15732 + * $Id: ocelot.c,v 1.14 2004/09/16 23:27:13 gleixner Exp $
15734 * Flash on Momenco Ocelot
15736 @@ -49,14 +49,14 @@
15737 struct map_info ocelot_flash_map = {
15738 .name = "Ocelot boot flash",
15739 .size = FLASH_WINDOW_SIZE,
15740 - .buswidth = FLASH_BUSWIDTH,
15741 + .bankwidth = FLASH_BUSWIDTH,
15742 .phys = FLASH_WINDOW_ADDR,
15745 struct map_info ocelot_nvram_map = {
15746 .name = "Ocelot NVRAM",
15747 .size = NVRAM_WINDOW_SIZE,
15748 - .buswidth = NVRAM_BUSWIDTH,
15749 + .bankwidth = NVRAM_BUSWIDTH,
15750 .phys = NVRAM_WINDOW_ADDR,
15756 /* Now ioremap the NVRAM space */
15757 - ocelot_nvram_map.virt = (unsigned long)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE);
15758 + ocelot_nvram_map.virt = (void __iomem *)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE);
15759 if (!ocelot_nvram_map.virt) {
15760 printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n");
15762 @@ -101,7 +101,7 @@
15763 nvram_mtd->write = ocelot_ram_write;
15765 /* Now map the flash space */
15766 - ocelot_flash_map.virt = (unsigned long)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE);
15767 + ocelot_flash_map.virt = (void __iomem *)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE);
15768 if (!ocelot_flash_map.virt) {
15769 printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n");
15771 Index: linux-2.6.5/drivers/mtd/maps/ocotea.c
15772 ===================================================================
15773 --- linux-2.6.5.orig/drivers/mtd/maps/ocotea.c 1969-12-31 19:00:00.000000000 -0500
15774 +++ linux-2.6.5/drivers/mtd/maps/ocotea.c 2005-02-01 17:11:17.000000000 -0500
15777 + * Mapping for Ocotea user flash
15779 + * Matt Porter <mporter@kernel.crashing.org>
15781 + * Copyright 2002-2004 MontaVista Software Inc.
15783 + * This program is free software; you can redistribute it and/or modify it
15784 + * under the terms of the GNU General Public License as published by the
15785 + * Free Software Foundation; either version 2 of the License, or (at your
15786 + * option) any later version.
15789 +#include <linux/module.h>
15790 +#include <linux/types.h>
15791 +#include <linux/kernel.h>
15792 +#include <linux/init.h>
15793 +#include <linux/mtd/mtd.h>
15794 +#include <linux/mtd/map.h>
15795 +#include <linux/mtd/partitions.h>
15796 +#include <linux/config.h>
15797 +#include <linux/version.h>
15798 +#include <asm/io.h>
15799 +#include <asm/ibm44x.h>
15800 +#include <platforms/4xx/ocotea.h>
15802 +static struct mtd_info *flash;
15804 +static struct map_info ocotea_small_map = {
15805 + .name = "Ocotea small flash",
15806 + .size = OCOTEA_SMALL_FLASH_SIZE,
15810 +static struct map_info ocotea_large_map = {
15811 + .name = "Ocotea large flash",
15812 + .size = OCOTEA_LARGE_FLASH_SIZE,
15816 +static struct mtd_partition ocotea_small_partitions[] = {
15820 + .size = 0x100000,
15824 +static struct mtd_partition ocotea_large_partitions[] = {
15828 + .size = 0x300000,
15831 + .name = "firmware",
15832 + .offset = 0x300000,
15833 + .size = 0x100000,
15837 +#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
15839 +int __init init_ocotea(void)
15843 + unsigned long long small_flash_base, large_flash_base;
15845 + fpga0_adr = ioremap64(OCOTEA_FPGA_ADDR, 16);
15849 + fpga0_reg = readb((unsigned long)fpga0_adr);
15850 + iounmap(fpga0_adr);
15852 + if (OCOTEA_BOOT_LARGE_FLASH(fpga0_reg)) {
15853 + small_flash_base = OCOTEA_SMALL_FLASH_HIGH;
15854 + large_flash_base = OCOTEA_LARGE_FLASH_LOW;
15857 + small_flash_base = OCOTEA_SMALL_FLASH_LOW;
15858 + large_flash_base = OCOTEA_LARGE_FLASH_HIGH;
15861 + ocotea_small_map.phys = small_flash_base;
15862 + ocotea_small_map.virt =
15863 + (void __iomem *)ioremap64(small_flash_base,
15864 + ocotea_small_map.size);
15866 + if (!ocotea_small_map.virt) {
15867 + printk("Failed to ioremap flash\n");
15871 + simple_map_init(&ocotea_small_map);
15873 + flash = do_map_probe("map_rom", &ocotea_small_map);
15875 + flash->owner = THIS_MODULE;
15876 + add_mtd_partitions(flash, ocotea_small_partitions,
15877 + NB_OF(ocotea_small_partitions));
15879 + printk("map probe failed for flash\n");
15883 + ocotea_large_map.phys = large_flash_base;
15884 + ocotea_large_map.virt =
15885 + (void __iomem *)ioremap64(large_flash_base,
15886 + ocotea_large_map.size);
15888 + if (!ocotea_large_map.virt) {
15889 + printk("Failed to ioremap flash\n");
15893 + simple_map_init(&ocotea_large_map);
15895 + flash = do_map_probe("cfi_probe", &ocotea_large_map);
15897 + flash->owner = THIS_MODULE;
15898 + add_mtd_partitions(flash, ocotea_large_partitions,
15899 + NB_OF(ocotea_large_partitions));
15901 + printk("map probe failed for flash\n");
15908 +static void __exit cleanup_ocotea(void)
15911 + del_mtd_partitions(flash);
15912 + map_destroy(flash);
15915 + if (ocotea_small_map.virt) {
15916 + iounmap((void *)ocotea_small_map.virt);
15917 + ocotea_small_map.virt = 0;
15920 + if (ocotea_large_map.virt) {
15921 + iounmap((void *)ocotea_large_map.virt);
15922 + ocotea_large_map.virt = 0;
15926 +module_init(init_ocotea);
15927 +module_exit(cleanup_ocotea);
15929 +MODULE_LICENSE("GPL");
15930 +MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
15931 +MODULE_DESCRIPTION("MTD map and partitions for IBM 440GX Ocotea boards");
15932 Index: linux-2.6.5/drivers/mtd/maps/octagon-5066.c
15933 ===================================================================
15934 --- linux-2.6.5.orig/drivers/mtd/maps/octagon-5066.c 2004-04-03 22:36:25.000000000 -0500
15935 +++ linux-2.6.5/drivers/mtd/maps/octagon-5066.c 2005-02-01 17:11:17.000000000 -0500
15937 -// $Id: octagon-5066.c,v 1.24 2003/05/21 15:15:07 dwmw2 Exp $
15938 +// $Id: octagon-5066.c,v 1.26 2004/07/12 22:38:29 dwmw2 Exp $
15939 /* ######################################################################
15941 Octagon 5066 MTD Driver.
15942 @@ -62,32 +62,12 @@
15946 -static __u8 oct5066_read8(struct map_info *map, unsigned long ofs)
15947 +static map_word oct5066_read8(struct map_info *map, unsigned long ofs)
15951 spin_lock(&oct5066_spin);
15952 oct5066_page(map, ofs);
15953 - ret = readb(iomapadr + (ofs & WINDOW_MASK));
15954 - spin_unlock(&oct5066_spin);
15958 -static __u16 oct5066_read16(struct map_info *map, unsigned long ofs)
15961 - spin_lock(&oct5066_spin);
15962 - oct5066_page(map, ofs);
15963 - ret = readw(iomapadr + (ofs & WINDOW_MASK));
15964 - spin_unlock(&oct5066_spin);
15968 -static __u32 oct5066_read32(struct map_info *map, unsigned long ofs)
15971 - spin_lock(&oct5066_spin);
15972 - oct5066_page(map, ofs);
15973 - ret = readl(iomapadr + (ofs & WINDOW_MASK));
15974 + ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK));
15975 spin_unlock(&oct5066_spin);
15978 @@ -109,27 +89,11 @@
15982 -static void oct5066_write8(struct map_info *map, __u8 d, unsigned long adr)
15984 - spin_lock(&oct5066_spin);
15985 - oct5066_page(map, adr);
15986 - writeb(d, iomapadr + (adr & WINDOW_MASK));
15987 - spin_unlock(&oct5066_spin);
15990 -static void oct5066_write16(struct map_info *map, __u16 d, unsigned long adr)
15992 - spin_lock(&oct5066_spin);
15993 - oct5066_page(map, adr);
15994 - writew(d, iomapadr + (adr & WINDOW_MASK));
15995 - spin_unlock(&oct5066_spin);
15998 -static void oct5066_write32(struct map_info *map, __u32 d, unsigned long adr)
15999 +static void oct5066_write8(struct map_info *map, map_word d, unsigned long adr)
16001 spin_lock(&oct5066_spin);
16002 oct5066_page(map, adr);
16003 - writel(d, iomapadr + (adr & WINDOW_MASK));
16004 + writeb(d.x[0], iomapadr + (adr & WINDOW_MASK));
16005 spin_unlock(&oct5066_spin);
16008 @@ -155,14 +119,10 @@
16009 .name = "Octagon 5066 Socket",
16011 .size = 512 * 1024,
16013 - .read8 = oct5066_read8,
16014 - .read16 = oct5066_read16,
16015 - .read32 = oct5066_read32,
16017 + .read = oct5066_read8,
16018 .copy_from = oct5066_copy_from,
16019 - .write8 = oct5066_write8,
16020 - .write16 = oct5066_write16,
16021 - .write32 = oct5066_write32,
16022 + .write = oct5066_write8,
16023 .copy_to = oct5066_copy_to,
16026 @@ -170,14 +130,10 @@
16027 .name = "Octagon 5066 Internal Flash",
16029 .size = 2 * 1024 * 1024,
16031 - .read8 = oct5066_read8,
16032 - .read16 = oct5066_read16,
16033 - .read32 = oct5066_read32,
16035 + .read = oct5066_read8,
16036 .copy_from = oct5066_copy_from,
16037 - .write8 = oct5066_write8,
16038 - .write16 = oct5066_write16,
16039 - .write32 = oct5066_write32,
16040 + .write = oct5066_write8,
16041 .copy_to = oct5066_copy_to,
16044 Index: linux-2.6.5/drivers/mtd/maps/omap-toto-flash.c
16045 ===================================================================
16046 --- linux-2.6.5.orig/drivers/mtd/maps/omap-toto-flash.c 1969-12-31 19:00:00.000000000 -0500
16047 +++ linux-2.6.5/drivers/mtd/maps/omap-toto-flash.c 2005-02-01 17:11:17.000000000 -0500
16050 + * NOR Flash memory access on TI Toto board
16052 + * jzhang@ti.com (C) 2003 Texas Instruments.
16054 + * (C) 2002 MontVista Software, Inc.
16056 + * $Id: omap-toto-flash.c,v 1.3 2004/09/16 23:27:13 gleixner Exp $
16059 +#include <linux/config.h>
16060 +#include <linux/module.h>
16061 +#include <linux/types.h>
16062 +#include <linux/kernel.h>
16064 +#include <linux/errno.h>
16065 +#include <linux/init.h>
16067 +#include <linux/mtd/mtd.h>
16068 +#include <linux/mtd/map.h>
16069 +#include <linux/mtd/partitions.h>
16071 +#include <asm/hardware.h>
16072 +#include <asm/io.h>
16075 +#ifndef CONFIG_ARCH_OMAP
16076 +#error This is for OMAP architecture only
16079 +//these lines need be moved to a hardware header file
16080 +#define OMAP_TOTO_FLASH_BASE 0xd8000000
16081 +#define OMAP_TOTO_FLASH_SIZE 0x80000
16083 +static struct map_info omap_toto_map_flash = {
16084 + .name = "OMAP Toto flash",
16086 + .virt = (void __iomem *)OMAP_TOTO_FLASH_BASE,
16090 +static struct mtd_partition toto_flash_partitions[] = {
16092 + .name = "BootLoader",
16093 + .size = 0x00040000, /* hopefully u-boot will stay 128k + 128*/
16095 + .mask_flags = MTD_WRITEABLE, /* force read-only */
16097 + .name = "ReservedSpace",
16098 + .size = 0x00030000,
16099 + .offset = MTDPART_OFS_APPEND,
16100 + //mask_flags: MTD_WRITEABLE, /* force read-only */
16102 + .name = "EnvArea", /* bottom 64KiB for env vars */
16103 + .size = MTDPART_SIZ_FULL,
16104 + .offset = MTDPART_OFS_APPEND,
16108 +static struct mtd_partition *parsed_parts;
16110 +static struct mtd_info *flash_mtd;
16112 +static int __init init_flash (void)
16115 + struct mtd_partition *parts;
16116 + int nb_parts = 0;
16117 + int parsed_nr_parts = 0;
16118 + const char *part_type;
16121 + * Static partition definition selection
16123 + part_type = "static";
16125 + parts = toto_flash_partitions;
16126 + nb_parts = ARRAY_SIZE(toto_flash_partitions);
16127 + omap_toto_map_flash.size = OMAP_TOTO_FLASH_SIZE;
16128 + omap_toto_map_flash.phys = virt_to_phys(OMAP_TOTO_FLASH_BASE);
16130 + simple_map_init(&omap_toto_map_flash);
16132 + * Now let's probe for the actual flash. Do it here since
16133 + * specific machine settings might have been set above.
16135 + printk(KERN_NOTICE "OMAP toto flash: probing %d-bit flash bus\n",
16136 + omap_toto_map_flash.bankwidth*8);
16137 + flash_mtd = do_map_probe("jedec_probe", &omap_toto_map_flash);
16141 + if (parsed_nr_parts > 0) {
16142 + parts = parsed_parts;
16143 + nb_parts = parsed_nr_parts;
16146 + if (nb_parts == 0) {
16147 + printk(KERN_NOTICE "OMAP toto flash: no partition info available,"
16148 + "registering whole flash at once\n");
16149 + if (add_mtd_device(flash_mtd)){
16153 + printk(KERN_NOTICE "Using %s partition definition\n",
16155 + return add_mtd_partitions(flash_mtd, parts, nb_parts);
16160 +int __init omap_toto_mtd_init(void)
16164 + if (status = init_flash()) {
16165 + printk(KERN_ERR "OMAP Toto Flash: unable to init map for toto flash\n");
16170 +static void __exit omap_toto_mtd_cleanup(void)
16173 + del_mtd_partitions(flash_mtd);
16174 + map_destroy(flash_mtd);
16175 + if (parsed_parts)
16176 + kfree(parsed_parts);
16180 +module_init(omap_toto_mtd_init);
16181 +module_exit(omap_toto_mtd_cleanup);
16183 +MODULE_AUTHOR("Jian Zhang");
16184 +MODULE_DESCRIPTION("OMAP Toto board map driver");
16185 +MODULE_LICENSE("GPL");
16186 Index: linux-2.6.5/drivers/mtd/maps/pb1550-flash.c
16187 ===================================================================
16188 --- linux-2.6.5.orig/drivers/mtd/maps/pb1550-flash.c 1969-12-31 19:00:00.000000000 -0500
16189 +++ linux-2.6.5/drivers/mtd/maps/pb1550-flash.c 2005-02-01 17:11:17.000000000 -0500
16192 + * Flash memory access on Alchemy Pb1550 board
16194 + * $Id: pb1550-flash.c,v 1.5 2004/09/16 23:27:13 gleixner Exp $
16196 + * (C) 2004 Embedded Edge, LLC, based on pb1550-flash.c:
16197 + * (C) 2003 Pete Popov <ppopov@pacbell.net>
16201 +#include <linux/config.h>
16202 +#include <linux/init.h>
16203 +#include <linux/module.h>
16204 +#include <linux/types.h>
16205 +#include <linux/kernel.h>
16207 +#include <linux/mtd/mtd.h>
16208 +#include <linux/mtd/map.h>
16209 +#include <linux/mtd/partitions.h>
16211 +#include <asm/io.h>
16212 +#include <asm/au1000.h>
16213 +#include <asm/pb1550.h>
16216 +#define DBG(x...) printk(x)
16221 +static unsigned long window_addr;
16222 +static unsigned long window_size;
16225 +static struct map_info pb1550_map = {
16226 + .name = "Pb1550 flash",
16229 +static unsigned char flash_bankwidth = 4;
16232 + * Support only 64MB NOR Flash parts
16235 +#ifdef PB1550_BOTH_BANKS
16236 +/* both banks will be used. Combine the first bank and the first
16237 + * part of the second bank together into a single jffs/jffs2
16240 +static struct mtd_partition pb1550_partitions[] = {
16241 + /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
16242 + * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
16243 + * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
16246 + .name = "User FS",
16247 + .size = (0x1FC00000 - 0x18000000),
16248 + .offset = 0x0000000
16251 + .size = 0x0100000,
16252 + .offset = MTDPART_OFS_APPEND,
16253 + .mask_flags = MTD_WRITEABLE
16255 + .name = "raw kernel",
16256 + .size = (0x300000 - 0x40000), /* last 256KB is yamon env */
16257 + .offset = MTDPART_OFS_APPEND,
16260 +#elif defined(PB1550_BOOT_ONLY)
16261 +static struct mtd_partition pb1550_partitions[] = {
16262 + /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
16263 + * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
16266 + .name = "User FS",
16267 + .size = 0x03c00000,
16268 + .offset = 0x0000000
16271 + .size = 0x0100000,
16272 + .offset = MTDPART_OFS_APPEND,
16273 + .mask_flags = MTD_WRITEABLE
16275 + .name = "raw kernel",
16276 + .size = (0x300000-0x40000), /* last 256KB is yamon env */
16277 + .offset = MTDPART_OFS_APPEND,
16280 +#elif defined(PB1550_USER_ONLY)
16281 +static struct mtd_partition pb1550_partitions[] = {
16282 + /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
16283 + * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
16286 + .name = "User FS",
16287 + .size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */
16288 + .offset = 0x0000000
16290 + .name = "raw kernel",
16291 + .size = MTDPART_SIZ_FULL,
16292 + .offset = MTDPART_OFS_APPEND,
16296 +#error MTD_PB1550 define combo error /* should never happen */
16299 +#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
16301 +static struct mtd_info *mymtd;
16304 + * Probe the flash density and setup window address and size
16305 + * based on user CONFIG options. There are times when we don't
16306 + * want the MTD driver to be probing the boot or user flash,
16307 + * so having the option to enable only one bank is important.
16309 +int setup_flash_params(void)
16311 + u16 boot_swapboot;
16312 + boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
16313 + ((bcsr->status >> 6) & 0x1);
16314 + printk("Pb1550 MTD: boot:swap %d\n", boot_swapboot);
16316 + switch (boot_swapboot) {
16317 + case 0: /* 512Mbit devices, both enabled */
16321 +#if defined(PB1550_BOTH_BANKS)
16322 + window_addr = 0x18000000;
16323 + window_size = 0x8000000;
16324 +#elif defined(PB1550_BOOT_ONLY)
16325 + window_addr = 0x1C000000;
16326 + window_size = 0x4000000;
16327 +#else /* USER ONLY */
16328 + window_addr = 0x1E000000;
16329 + window_size = 0x4000000;
16336 + /* 64 MB Boot NOR Flash is disabled */
16337 + /* and the start address is moved to 0x0C00000 */
16338 + window_addr = 0x0C000000;
16339 + window_size = 0x4000000;
16341 + printk("Pb1550 MTD: unsupported boot:swap setting\n");
16347 +int __init pb1550_mtd_init(void)
16349 + struct mtd_partition *parts;
16350 + int nb_parts = 0;
16352 + /* Default flash bankwidth */
16353 + pb1550_map.bankwidth = flash_bankwidth;
16355 + if (setup_flash_params())
16359 + * Static partition definition selection
16361 + parts = pb1550_partitions;
16362 + nb_parts = NB_OF(pb1550_partitions);
16363 + pb1550_map.size = window_size;
16366 + * Now let's probe for the actual flash. Do it here since
16367 + * specific machine settings might have been set above.
16369 + printk(KERN_NOTICE "Pb1550 flash: probing %d-bit flash bus\n",
16370 + pb1550_map.bankwidth*8);
16371 + pb1550_map.virt =
16372 + (void __iomem *)ioremap(window_addr, window_size);
16373 + mymtd = do_map_probe("cfi_probe", &pb1550_map);
16374 + if (!mymtd) return -ENXIO;
16375 + mymtd->owner = THIS_MODULE;
16377 + add_mtd_partitions(mymtd, parts, nb_parts);
16381 +static void __exit pb1550_mtd_cleanup(void)
16384 + del_mtd_partitions(mymtd);
16385 + map_destroy(mymtd);
16389 +module_init(pb1550_mtd_init);
16390 +module_exit(pb1550_mtd_cleanup);
16392 +MODULE_AUTHOR("Embedded Edge, LLC");
16393 +MODULE_DESCRIPTION("Pb1550 mtd map driver");
16394 +MODULE_LICENSE("GPL");
16395 Index: linux-2.6.5/drivers/mtd/maps/pb1xxx-flash.c
16396 ===================================================================
16397 --- linux-2.6.5.orig/drivers/mtd/maps/pb1xxx-flash.c 2004-04-03 22:38:24.000000000 -0500
16398 +++ linux-2.6.5/drivers/mtd/maps/pb1xxx-flash.c 2005-02-01 17:11:17.000000000 -0500
16401 * (C) 2001 Pete Popov <ppopov@mvista.com>
16403 - * $Id: pb1xxx-flash.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $
16404 + * $Id: pb1xxx-flash.c,v 1.12 2004/09/16 23:27:13 gleixner Exp $
16407 #include <linux/config.h>
16408 #include <linux/module.h>
16409 #include <linux/types.h>
16410 -#include <linux/kernel.h>
16411 #include <linux/init.h>
16412 +#include <linux/kernel.h>
16414 #include <linux/mtd/mtd.h>
16415 #include <linux/mtd/map.h>
16416 @@ -26,102 +26,87 @@
16419 #ifdef CONFIG_MIPS_PB1000
16421 #define WINDOW_ADDR 0x1F800000
16422 #define WINDOW_SIZE 0x800000
16426 -static struct map_info pb1xxx_map = {
16427 - .name = "Pb1xxx flash",
16431 -#ifdef CONFIG_MIPS_PB1000
16433 -static unsigned long flash_size = 0x00800000;
16434 -static unsigned char flash_buswidth = 4;
16435 static struct mtd_partition pb1xxx_partitions[] = {
16437 - .name = "yamon env",
16438 - .size = 0x00020000,
16440 - .mask_flags = MTD_WRITEABLE
16442 - .name = "User FS",
16443 - .size = 0x003e0000,
16444 - .offset = 0x20000,
16446 - .name = "boot code",
16447 - .size = 0x100000,
16448 - .offset = 0x400000,
16449 - .mask_flags = MTD_WRITEABLE
16451 - .name = "raw/kernel",
16452 - .size = 0x300000,
16453 - .offset = 0x500000
16455 + .name = "yamon env",
16456 + .size = 0x00020000,
16458 + .mask_flags = MTD_WRITEABLE},
16460 + .name = "User FS",
16461 + .size = 0x003e0000,
16462 + .offset = 0x20000,},
16464 + .name = "boot code",
16465 + .size = 0x100000,
16466 + .offset = 0x400000,
16467 + .mask_flags = MTD_WRITEABLE},
16469 + .name = "raw/kernel",
16470 + .size = 0x300000,
16471 + .offset = 0x500000}
16474 #elif defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100)
16476 -static unsigned char flash_buswidth = 4;
16477 #if defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER)
16478 -/* both 32MiB banks will be used. Combine the first 32MiB bank and the
16479 - * first 28MiB of the second bank together into a single jffs/jffs2
16480 +/* both 32MB banks will be used. Combine the first 32MB bank and the
16481 + * first 28MB of the second bank together into a single jffs/jffs2
16484 -static unsigned long flash_size = 0x04000000;
16485 #define WINDOW_ADDR 0x1C000000
16486 #define WINDOW_SIZE 0x4000000
16487 static struct mtd_partition pb1xxx_partitions[] = {
16489 - .name = "User FS",
16490 - .size = 0x3c00000,
16491 - .offset = 0x0000000
16494 - .size = 0x0100000,
16495 - .offset = 0x3c00000,
16496 - .mask_flags = MTD_WRITEABLE
16498 - .name = "raw kernel",
16499 - .size = 0x02c0000,
16500 - .offset = 0x3d00000
16501 + .name = "User FS",
16502 + .size = 0x3c00000,
16503 + .offset = 0x0000000
16506 + .size = 0x0100000,
16507 + .offset = 0x3c00000,
16508 + .mask_flags = MTD_WRITEABLE
16510 + .name = "raw kernel",
16511 + .size = 0x02c0000,
16512 + .offset = 0x3d00000
16515 #elif defined(CONFIG_MTD_PB1500_BOOT) && !defined(CONFIG_MTD_PB1500_USER)
16516 -static unsigned long flash_size = 0x02000000;
16517 #define WINDOW_ADDR 0x1E000000
16518 #define WINDOW_SIZE 0x2000000
16519 static struct mtd_partition pb1xxx_partitions[] = {
16521 - .name = "User FS",
16522 - .size = 0x1c00000,
16523 - .offset = 0x0000000
16526 - .size = 0x0100000,
16527 - .offset = 0x1c00000,
16528 - .mask_flags = MTD_WRITEABLE
16530 - .name = "raw kernel",
16531 - .size = 0x02c0000,
16532 - .offset = 0x1d00000
16533 + .name = "User FS",
16534 + .size = 0x1c00000,
16535 + .offset = 0x0000000
16538 + .size = 0x0100000,
16539 + .offset = 0x1c00000,
16540 + .mask_flags = MTD_WRITEABLE
16542 + .name = "raw kernel",
16543 + .size = 0x02c0000,
16544 + .offset = 0x1d00000
16547 #elif !defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER)
16548 -static unsigned long flash_size = 0x02000000;
16549 #define WINDOW_ADDR 0x1C000000
16550 #define WINDOW_SIZE 0x2000000
16551 static struct mtd_partition pb1xxx_partitions[] = {
16553 - .name = "User FS",
16554 - .size = 0x1e00000,
16555 - .offset = 0x0000000
16557 - .name = "raw kernel",
16558 - .size = 0x0200000,
16559 - .offset = 0x1e00000,
16560 + .name = "User FS",
16561 + .size = 0x1e00000,
16562 + .offset = 0x0000000
16564 + .name = "raw kernel",
16565 + .size = 0x0200000,
16566 + .offset = 0x1e00000,
16570 @@ -131,8 +116,20 @@
16571 #error Unsupported board
16574 -static struct mtd_partition *parsed_parts;
16575 -static struct mtd_info *mymtd;
16576 +#define NAME "Pb1x00 Linux Flash"
16577 +#define PADDR WINDOW_ADDR
16578 +#define BUSWIDTH 4
16579 +#define SIZE WINDOW_SIZE
16580 +#define PARTITIONS 4
16582 +static struct map_info pb1xxx_mtd_map = {
16585 + .bankwidth = BUSWIDTH,
16589 +static struct mtd_info *pb1xxx_mtd;
16591 int __init pb1xxx_mtd_init(void)
16593 @@ -140,49 +137,38 @@
16597 - /* Default flash buswidth */
16598 - pb1xxx_map.buswidth = flash_buswidth;
16601 * Static partition definition selection
16603 part_type = "static";
16604 parts = pb1xxx_partitions;
16605 nb_parts = ARRAY_SIZE(pb1xxx_partitions);
16606 - pb1xxx_map.size = flash_size;
16609 * Now let's probe for the actual flash. Do it here since
16610 * specific machine settings might have been set above.
16612 printk(KERN_NOTICE "Pb1xxx flash: probing %d-bit flash bus\n",
16613 - pb1xxx_map.buswidth*8);
16614 - pb1xxx_map.phys = WINDOW_ADDR;
16615 - pb1xxx_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
16617 - simple_map_init(&pb1xxx_map);
16619 - mymtd = do_map_probe("cfi_probe", &pb1xxx_map);
16621 - iounmap(pb1xxx_map.virt);
16624 - mymtd->owner = THIS_MODULE;
16626 + pb1xxx_mtd_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE);
16628 + simple_map_init(&pb1xxx_mtd_map);
16630 + pb1xxx_mtd = do_map_probe("cfi_probe", &pb1xxx_mtd_map);
16631 + if (!pb1xxx_mtd) return -ENXIO;
16632 + pb1xxx_mtd->owner = THIS_MODULE;
16634 - add_mtd_partitions(mymtd, parts, nb_parts);
16635 + add_mtd_partitions(pb1xxx_mtd, parts, nb_parts);
16639 static void __exit pb1xxx_mtd_cleanup(void)
16642 - del_mtd_partitions(mymtd);
16643 - map_destroy(mymtd);
16644 - if (parsed_parts)
16645 - kfree(parsed_parts);
16646 + if (pb1xxx_mtd) {
16647 + del_mtd_partitions(pb1xxx_mtd);
16648 + map_destroy(pb1xxx_mtd);
16649 + iounmap((void *) pb1xxx_mtd_map.virt);
16651 - if (pb1xxx_map.virt)
16652 - iounmap(pb1xxx_map.virt);
16655 module_init(pb1xxx_mtd_init);
16656 Index: linux-2.6.5/drivers/mtd/maps/pci.c
16657 ===================================================================
16658 --- linux-2.6.5.orig/drivers/mtd/maps/pci.c 2004-04-03 22:36:56.000000000 -0500
16659 +++ linux-2.6.5/drivers/mtd/maps/pci.c 2005-02-01 17:11:17.000000000 -0500
16661 * it under the terms of the GNU General Public License version 2 as
16662 * published by the Free Software Foundation.
16664 - * $Id: pci.c,v 1.5 2003/05/20 20:59:31 dwmw2 Exp $
16665 + * $Id: pci.c,v 1.8 2004/07/12 22:38:29 dwmw2 Exp $
16667 * Generic PCI memory map driver. We support the following boards:
16668 * - Intel IQ80310 ATU.
16670 struct pci_dev *dev;
16673 +static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs)
16675 + struct map_pci_info *map = (struct map_pci_info *)_map;
16677 + val.x[0]= readb(map->base + map->translate(map, ofs));
16678 +// printk("read8 : %08lx => %02x\n", ofs, val.x[0]);
16683 +static map_word mtd_pci_read16(struct map_info *_map, unsigned long ofs)
16685 + struct map_pci_info *map = (struct map_pci_info *)_map;
16687 + val.x[0] = readw(map->base + map->translate(map, ofs));
16688 +// printk("read16: %08lx => %04x\n", ofs, val.x[0]);
16692 +static map_word mtd_pci_read32(struct map_info *_map, unsigned long ofs)
16694 + struct map_pci_info *map = (struct map_pci_info *)_map;
16696 + val.x[0] = readl(map->base + map->translate(map, ofs));
16697 +// printk("read32: %08lx => %08x\n", ofs, val.x[0]);
16701 +static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
16703 + struct map_pci_info *map = (struct map_pci_info *)_map;
16704 + memcpy_fromio(to, map->base + map->translate(map, from), len);
16707 +static void mtd_pci_write8(struct map_info *_map, map_word val, unsigned long ofs)
16709 + struct map_pci_info *map = (struct map_pci_info *)_map;
16710 +// printk("write8 : %08lx <= %02x\n", ofs, val.x[0]);
16711 + writeb(val.x[0], map->base + map->translate(map, ofs));
16715 +static void mtd_pci_write16(struct map_info *_map, map_word val, unsigned long ofs)
16717 + struct map_pci_info *map = (struct map_pci_info *)_map;
16718 +// printk("write16: %08lx <= %04x\n", ofs, val.x[0]);
16719 + writew(val.x[0], map->base + map->translate(map, ofs));
16722 +static void mtd_pci_write32(struct map_info *_map, map_word val, unsigned long ofs)
16724 + struct map_pci_info *map = (struct map_pci_info *)_map;
16725 +// printk("write32: %08lx <= %08x\n", ofs, val.x[0]);
16726 + writel(val.x[0], map->base + map->translate(map, ofs));
16729 +static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
16731 + struct map_pci_info *map = (struct map_pci_info *)_map;
16732 + memcpy_toio(map->base + map->translate(map, to), from, len);
16735 +static struct map_info mtd_pci_map = {
16737 + .copy_from = mtd_pci_copyfrom,
16738 + .copy_to = mtd_pci_copyto,
16742 * Intel IOP80310 Flash driver
16744 @@ -48,7 +116,10 @@
16748 - map->map.buswidth = 1;
16749 + map->map.bankwidth = 1;
16750 + map->map.read = mtd_pci_read8,
16751 + map->map.write = mtd_pci_write8,
16753 map->map.size = 0x00800000;
16754 map->base = ioremap_nocache(pci_resource_start(dev, 0),
16755 pci_resource_len(dev, 0));
16756 @@ -147,7 +218,9 @@
16760 - map->map.buswidth = 4;
16761 + map->map.bankwidth = 4;
16762 + map->map.read = mtd_pci_read32,
16763 + map->map.write = mtd_pci_write32,
16764 map->map.size = len;
16765 map->base = ioremap_nocache(base, len);
16767 @@ -215,75 +288,6 @@
16768 * Generic code follows.
16771 -static u8 mtd_pci_read8(struct map_info *_map, unsigned long ofs)
16773 - struct map_pci_info *map = (struct map_pci_info *)_map;
16774 - u8 val = readb(map->base + map->translate(map, ofs));
16775 -// printk("read8 : %08lx => %02x\n", ofs, val);
16779 -static u16 mtd_pci_read16(struct map_info *_map, unsigned long ofs)
16781 - struct map_pci_info *map = (struct map_pci_info *)_map;
16782 - u16 val = readw(map->base + map->translate(map, ofs));
16783 -// printk("read16: %08lx => %04x\n", ofs, val);
16787 -static u32 mtd_pci_read32(struct map_info *_map, unsigned long ofs)
16789 - struct map_pci_info *map = (struct map_pci_info *)_map;
16790 - u32 val = readl(map->base + map->translate(map, ofs));
16791 -// printk("read32: %08lx => %08x\n", ofs, val);
16795 -static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
16797 - struct map_pci_info *map = (struct map_pci_info *)_map;
16798 - memcpy_fromio(to, map->base + map->translate(map, from), len);
16801 -static void mtd_pci_write8(struct map_info *_map, u8 val, unsigned long ofs)
16803 - struct map_pci_info *map = (struct map_pci_info *)_map;
16804 -// printk("write8 : %08lx <= %02x\n", ofs, val);
16805 - writeb(val, map->base + map->translate(map, ofs));
16808 -static void mtd_pci_write16(struct map_info *_map, u16 val, unsigned long ofs)
16810 - struct map_pci_info *map = (struct map_pci_info *)_map;
16811 -// printk("write16: %08lx <= %04x\n", ofs, val);
16812 - writew(val, map->base + map->translate(map, ofs));
16815 -static void mtd_pci_write32(struct map_info *_map, u32 val, unsigned long ofs)
16817 - struct map_pci_info *map = (struct map_pci_info *)_map;
16818 -// printk("write32: %08lx <= %08x\n", ofs, val);
16819 - writel(val, map->base + map->translate(map, ofs));
16822 -static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
16824 - struct map_pci_info *map = (struct map_pci_info *)_map;
16825 - memcpy_toio(map->base + map->translate(map, to), from, len);
16828 -static struct map_info mtd_pci_map = {
16830 - .read8 = mtd_pci_read8,
16831 - .read16 = mtd_pci_read16,
16832 - .read32 = mtd_pci_read32,
16833 - .copy_from = mtd_pci_copyfrom,
16834 - .write8 = mtd_pci_write8,
16835 - .write16 = mtd_pci_write16,
16836 - .write32 = mtd_pci_write32,
16837 - .copy_to = mtd_pci_copyto,
16840 static int __devinit
16841 mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
16843 Index: linux-2.6.5/drivers/mtd/maps/pcmciamtd.c
16844 ===================================================================
16845 --- linux-2.6.5.orig/drivers/mtd/maps/pcmciamtd.c 2004-04-03 22:36:19.000000000 -0500
16846 +++ linux-2.6.5/drivers/mtd/maps/pcmciamtd.c 2005-02-01 17:11:17.000000000 -0500
16849 - * $Id: pcmciamtd.c,v 1.48 2003/06/24 07:14:38 spse Exp $
16850 + * $Id: pcmciamtd.c,v 1.51 2004/07/12 22:38:29 dwmw2 Exp $
16852 * pcmciamtd.c - MTD driver for PCMCIA flash memory cards
16857 #define DRIVER_DESC "PCMCIA Flash memory card driver"
16858 -#define DRIVER_VERSION "$Revision: 1.48 $"
16859 +#define DRIVER_VERSION "$Revision: 1.51 $"
16861 /* Size of the PCMCIA address space: 26 bits = 64 MB */
16862 #define MAX_PCMCIA_ADDR 0x4000000
16864 /* Module parameters */
16866 /* 2 = do 16-bit transfers, 1 = do 8-bit transfers */
16867 -static int buswidth = 2;
16868 +static int bankwidth = 2;
16870 /* Speed of memory accesses, in ns */
16871 static int mem_speed;
16873 MODULE_LICENSE("GPL");
16874 MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
16875 MODULE_DESCRIPTION(DRIVER_DESC);
16876 -MODULE_PARM(buswidth, "i");
16877 -MODULE_PARM_DESC(buswidth, "Set buswidth (1=8 bit, 2=16 bit, default=2)");
16878 +MODULE_PARM(bankwidth, "i");
16879 +MODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)");
16880 MODULE_PARM(mem_speed, "i");
16881 MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns");
16882 MODULE_PARM(force_size, "i");
16883 @@ -135,32 +135,32 @@
16887 -static u8 pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
16888 +static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
16892 + map_word d = {{0}};
16894 addr = remap_window(map, ofs);
16900 - DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, addr, d);
16901 + d.x[0] = readb(addr);
16902 + DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, addr, d.x[0]);
16907 -static u16 pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
16908 +static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
16912 + map_word d = {{0}};
16914 addr = remap_window(map, ofs);
16920 - DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, addr, d);
16921 + d.x[0] = readw(addr);
16922 + DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, addr, d.x[0]);
16926 @@ -191,26 +191,26 @@
16930 -static void pcmcia_write8_remap(struct map_info *map, u8 d, unsigned long adr)
16931 +static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long adr)
16933 caddr_t addr = remap_window(map, adr);
16938 - DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, addr, d);
16940 + DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, addr, d.x[0]);
16941 + writeb(d.x[0], addr);
16945 -static void pcmcia_write16_remap(struct map_info *map, u16 d, unsigned long adr)
16946 +static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long adr)
16948 caddr_t addr = remap_window(map, adr);
16952 - DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, addr, d);
16954 + DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, addr, d.x[0]);
16955 + writew(d.x[0], addr);
16959 @@ -244,30 +244,30 @@
16961 #define DEV_REMOVED(x) (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))
16963 -static u8 pcmcia_read8(struct map_info *map, unsigned long ofs)
16964 +static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
16966 caddr_t win_base = (caddr_t)map->map_priv_2;
16968 + map_word d = {{0}};
16970 if(DEV_REMOVED(map))
16974 - d = readb(win_base + ofs);
16975 - DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d);
16976 + d.x[0] = readb(win_base + ofs);
16977 + DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d.x[0]);
16982 -static u16 pcmcia_read16(struct map_info *map, unsigned long ofs)
16983 +static map_word pcmcia_read16(struct map_info *map, unsigned long ofs)
16985 caddr_t win_base = (caddr_t)map->map_priv_2;
16987 + map_word d = {{0}};
16989 if(DEV_REMOVED(map))
16993 - d = readw(win_base + ofs);
16994 - DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d);
16995 + d.x[0] = readw(win_base + ofs);
16996 + DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d.x[0]);
17000 @@ -439,9 +439,9 @@
17001 case CISTPL_DEVICE_GEO: {
17002 cistpl_device_geo_t *t = &parse.device_geo;
17004 - dev->pcmcia_map.buswidth = t->geo[0].buswidth;
17005 + dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
17006 for(i = 0; i < t->ngeo; i++) {
17007 - DEBUG(2, "region: %d buswidth = %u", i, t->geo[i].buswidth);
17008 + DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth);
17009 DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block);
17010 DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block);
17011 DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block);
17012 @@ -460,17 +460,17 @@
17013 if(!dev->pcmcia_map.size)
17014 dev->pcmcia_map.size = MAX_PCMCIA_ADDR;
17016 - if(!dev->pcmcia_map.buswidth)
17017 - dev->pcmcia_map.buswidth = 2;
17018 + if(!dev->pcmcia_map.bankwidth)
17019 + dev->pcmcia_map.bankwidth = 2;
17022 dev->pcmcia_map.size = force_size << 20;
17023 DEBUG(2, "size forced to %dM", force_size);
17027 - dev->pcmcia_map.buswidth = buswidth;
17028 - DEBUG(2, "buswidth forced to %d", buswidth);
17030 + dev->pcmcia_map.bankwidth = bankwidth;
17031 + DEBUG(2, "bankwidth forced to %d", bankwidth);
17034 dev->pcmcia_map.name = dev->mtd_name;
17035 @@ -480,7 +480,7 @@
17038 DEBUG(1, "Device: Size: %lu Width:%d Name: %s",
17039 - dev->pcmcia_map.size, dev->pcmcia_map.buswidth << 3, dev->mtd_name);
17040 + dev->pcmcia_map.size, dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
17044 @@ -522,12 +522,15 @@
17045 card_settings(dev, link, &new_name);
17047 dev->pcmcia_map.phys = NO_XIP;
17048 - dev->pcmcia_map.read8 = pcmcia_read8_remap;
17049 - dev->pcmcia_map.read16 = pcmcia_read16_remap;
17050 dev->pcmcia_map.copy_from = pcmcia_copy_from_remap;
17051 - dev->pcmcia_map.write8 = pcmcia_write8_remap;
17052 - dev->pcmcia_map.write16 = pcmcia_write16_remap;
17053 dev->pcmcia_map.copy_to = pcmcia_copy_to_remap;
17054 + if (dev->pcmcia_map.bankwidth == 1) {
17055 + dev->pcmcia_map.read = pcmcia_read8_remap;
17056 + dev->pcmcia_map.write = pcmcia_write8_remap;
17058 + dev->pcmcia_map.read = pcmcia_read16_remap;
17059 + dev->pcmcia_map.write = pcmcia_write16_remap;
17062 dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;
17064 @@ -536,7 +539,7 @@
17065 whole card - otherwise we try smaller windows until we succeed */
17067 req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE;
17068 - req.Attributes |= (dev->pcmcia_map.buswidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
17069 + req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
17071 req.AccessSpeed = mem_speed;
17072 link->win = (window_handle_t)link->handle;
17073 @@ -657,11 +660,14 @@
17074 DEBUG(1, "Using non remapping memory functions");
17075 dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state);
17076 dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
17077 - dev->pcmcia_map.read8 = pcmcia_read8;
17078 - dev->pcmcia_map.read16 = pcmcia_read16;
17079 + if (dev->pcmcia_map.bankwidth == 1) {
17080 + dev->pcmcia_map.read = pcmcia_read8;
17081 + dev->pcmcia_map.write = pcmcia_write8;
17083 + dev->pcmcia_map.read = pcmcia_read16;
17084 + dev->pcmcia_map.write = pcmcia_write16;
17086 dev->pcmcia_map.copy_from = pcmcia_copy_from;
17087 - dev->pcmcia_map.write8 = pcmcia_write8;
17088 - dev->pcmcia_map.write16 = pcmcia_write16;
17089 dev->pcmcia_map.copy_to = pcmcia_copy_to;
17092 @@ -828,9 +834,9 @@
17094 info(DRIVER_DESC " " DRIVER_VERSION);
17096 - if(buswidth && buswidth != 1 && buswidth != 2) {
17097 - info("bad buswidth (%d), using default", buswidth);
17099 + if(bankwidth && bankwidth != 1 && bankwidth != 2) {
17100 + info("bad bankwidth (%d), using default", bankwidth);
17103 if(force_size && (force_size < 1 || force_size > 64)) {
17104 info("bad force_size (%d), using default", force_size);
17105 Index: linux-2.6.5/drivers/mtd/maps/physmap.c
17106 ===================================================================
17107 --- linux-2.6.5.orig/drivers/mtd/maps/physmap.c 2004-04-03 22:37:25.000000000 -0500
17108 +++ linux-2.6.5/drivers/mtd/maps/physmap.c 2005-02-01 17:11:17.000000000 -0500
17111 - * $Id: physmap.c,v 1.29 2003/05/29 09:24:10 dwmw2 Exp $
17112 + * $Id: physmap.c,v 1.35 2004/09/16 23:27:13 gleixner Exp $
17114 * Normal mappings of chips in physical memory
17116 + * Copyright (C) 2003 MontaVista Software Inc.
17117 + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
17119 + * 031022 - [jsun] add run-time configure and partition setup
17122 #include <linux/module.h>
17123 @@ -15,62 +20,38 @@
17124 #include <linux/config.h>
17125 #include <linux/mtd/partitions.h>
17127 -#define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START
17128 -#define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN
17129 -#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH
17131 static struct mtd_info *mymtd;
17134 struct map_info physmap_map = {
17135 - .name = "Physically mapped flash",
17136 - .size = WINDOW_SIZE,
17137 - .buswidth = BUSWIDTH,
17138 - .phys = WINDOW_ADDR,
17139 + .name = "phys_mapped_flash",
17140 + .phys = CONFIG_MTD_PHYSMAP_START,
17141 + .size = CONFIG_MTD_PHYSMAP_LEN,
17142 + .bankwidth = CONFIG_MTD_PHYSMAP_BANKWIDTH,
17145 #ifdef CONFIG_MTD_PARTITIONS
17146 static struct mtd_partition *mtd_parts;
17147 static int mtd_parts_nb;
17149 -static struct mtd_partition physmap_partitions[] = {
17151 -/* Put your own partition definitions here */
17153 - .name = "bootROM",
17156 - .mask_flags = MTD_WRITEABLE, /* force read-only */
17158 - .name = "zImage",
17159 - .size = 0x100000,
17160 - .offset = MTDPART_OFS_APPEND,
17161 - .mask_flags = MTD_WRITEABLE, /* force read-only */
17163 - .name = "ramdisk.gz",
17164 - .size = 0x300000,
17165 - .offset = MTDPART_OFS_APPEND,
17166 - .mask_flags = MTD_WRITEABLE, /* force read-only */
17168 - .name = "User FS",
17169 - .size = MTDPART_SIZ_FULL,
17170 - .offset = MTDPART_OFS_APPEND,
17174 +static int num_physmap_partitions;
17175 +static struct mtd_partition *physmap_partitions;
17177 -#define NUM_PARTITIONS (sizeof(physmap_partitions)/sizeof(struct mtd_partition))
17178 -const char *part_probes[] = {"cmdlinepart", "RedBoot", NULL};
17179 +static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
17181 +void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
17183 + physmap_partitions=parts;
17184 + num_physmap_partitions=num_parts;
17186 #endif /* CONFIG_MTD_PARTITIONS */
17188 -int __init init_physmap(void)
17189 +static int __init init_physmap(void)
17191 - static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", 0 };
17192 + static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
17195 - printk(KERN_NOTICE "physmap flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
17196 - physmap_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
17197 + printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys);
17198 + physmap_map.virt = (void __iomem *)ioremap(physmap_map.phys, physmap_map.size);
17200 if (!physmap_map.virt) {
17201 printk("Failed to ioremap\n");
17204 simple_map_init(&physmap_map);
17208 type = rom_probe_types;
17209 for(; !mymtd && *type; type++) {
17210 mymtd = do_map_probe(*type, &physmap_map);
17211 @@ -97,11 +78,11 @@
17215 - if (NUM_PARTITIONS != 0)
17216 + if (num_physmap_partitions != 0)
17219 "Using physmap partition definition\n");
17220 - add_mtd_partitions (mymtd, physmap_partitions, NUM_PARTITIONS);
17221 + add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions);
17225 @@ -121,7 +102,7 @@
17226 if (mtd_parts_nb) {
17227 del_mtd_partitions(mymtd);
17229 - } else if (NUM_PARTITIONS) {
17230 + } else if (num_physmap_partitions) {
17231 del_mtd_partitions(mymtd);
17233 del_mtd_device(mymtd);
17234 Index: linux-2.6.5/drivers/mtd/maps/pnc2000.c
17235 ===================================================================
17236 --- linux-2.6.5.orig/drivers/mtd/maps/pnc2000.c 2004-04-03 22:37:06.000000000 -0500
17237 +++ linux-2.6.5/drivers/mtd/maps/pnc2000.c 2005-02-01 17:11:17.000000000 -0500
17242 - * $Id: pnc2000.c,v 1.14 2003/05/21 12:45:19 dwmw2 Exp $
17243 + * $Id: pnc2000.c,v 1.16 2004/09/16 23:27:13 gleixner Exp $
17246 #include <linux/module.h>
17248 struct map_info pnc_map = {
17249 .name = "PNC-2000",
17250 .size = WINDOW_SIZE,
17253 .phys = 0xFFFFFFFF,
17254 - .virt = WINDOW_ADDR,
17255 + .virt = (void __iomem *)WINDOW_ADDR,
17259 Index: linux-2.6.5/drivers/mtd/maps/redwood.c
17260 ===================================================================
17261 --- linux-2.6.5.orig/drivers/mtd/maps/redwood.c 2004-04-03 22:37:37.000000000 -0500
17262 +++ linux-2.6.5/drivers/mtd/maps/redwood.c 2005-02-01 17:11:17.000000000 -0500
17265 - * $Id: redwood.c,v 1.6 2003/05/21 12:45:19 dwmw2 Exp $
17266 + * $Id: redwood.c,v 1.9 2004/09/16 23:27:13 gleixner Exp $
17268 * drivers/mtd/maps/redwood.c
17270 * FLASH map for the IBM Redwood 4/5/6 boards.
17272 + * Author: MontaVista Software, Inc. <source@mvista.com>
17274 - * Author: Armin Kuster <akuster@mvista.com>
17276 - * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under
17277 + * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under
17278 * the terms of the GNU General Public License version 2. This program
17279 * is licensed "as is" without any warranty of any kind, whether express
17283 static struct mtd_partition redwood_flash_partitions[] = {
17285 - .name = "Redwood kernel",
17286 + .name = "Redwood filesystem",
17287 .offset = RW_PART0_OF,
17288 .size = RW_PART0_SZ
17291 .mask_flags = MTD_WRITEABLE /* force read-only */
17294 - .name = "Redwood filesystem",
17295 + .name = "Redwood kernel",
17296 .offset = RW_PART2_OF,
17297 .size = RW_PART2_SZ
17299 @@ -117,7 +116,7 @@
17300 struct map_info redwood_flash_map = {
17301 .name = "IBM Redwood",
17302 .size = WINDOW_SIZE,
17305 .phys = WINDOW_ADDR,
17308 @@ -133,7 +132,7 @@
17309 WINDOW_SIZE, WINDOW_ADDR);
17311 redwood_flash_map.virt =
17312 - (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
17313 + (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE);
17315 if (!redwood_flash_map.virt) {
17316 printk("init_redwood_flash: failed to ioremap\n");
17317 @@ -167,5 +166,5 @@
17318 module_exit(cleanup_redwood_flash);
17320 MODULE_LICENSE("GPL");
17321 -MODULE_AUTHOR("Armin Kuster <akuster@mvista.com>");
17322 +MODULE_AUTHOR("MontaVista Software <source@mvista.com>");
17323 MODULE_DESCRIPTION("MTD map driver for the IBM Redwood reference boards");
17324 Index: linux-2.6.5/drivers/mtd/maps/rpxlite.c
17325 ===================================================================
17326 --- linux-2.6.5.orig/drivers/mtd/maps/rpxlite.c 2004-04-03 22:38:23.000000000 -0500
17327 +++ linux-2.6.5/drivers/mtd/maps/rpxlite.c 2005-02-01 17:11:17.000000000 -0500
17330 - * $Id: rpxlite.c,v 1.19 2003/05/21 12:45:19 dwmw2 Exp $
17331 + * $Id: rpxlite.c,v 1.21 2004/09/16 23:27:13 gleixner Exp $
17333 * Handle mapping of the flash on the RPX Lite and CLLF boards
17335 @@ -21,14 +21,14 @@
17336 static struct map_info rpxlite_map = {
17338 .size = WINDOW_SIZE,
17341 .phys = WINDOW_ADDR,
17344 int __init init_rpxlite(void)
17346 printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR);
17347 - rpxlite_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
17348 + rpxlite_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
17350 if (!rpxlite_map.virt) {
17351 printk("Failed to ioremap\n");
17352 Index: linux-2.6.5/drivers/mtd/maps/sa1100-flash.c
17353 ===================================================================
17354 --- linux-2.6.5.orig/drivers/mtd/maps/sa1100-flash.c 2004-04-03 22:36:51.000000000 -0500
17355 +++ linux-2.6.5/drivers/mtd/maps/sa1100-flash.c 2005-02-01 17:11:17.000000000 -0500
17358 * (C) 2000 Nicolas Pitre <nico@cam.org>
17360 - * $Id: sa1100-flash.c,v 1.36 2003/05/29 08:59:35 dwmw2 Exp $
17361 + * $Id: sa1100-flash.c,v 1.41 2004/09/16 23:27:13 gleixner Exp $
17364 #include <linux/config.h>
17365 @@ -496,6 +496,32 @@
17369 +#ifdef CONFIG_SA1100_JORNADA56X
17370 +static struct mtd_partition jornada56x_partitions[] = {
17372 + .name = "bootldr",
17373 + .size = 0x00040000,
17375 + .mask_flags = MTD_WRITEABLE,
17377 + .name = "rootfs",
17378 + .size = MTDPART_SIZ_FULL,
17379 + .offset = MTDPART_OFS_APPEND,
17383 +static void jornada56x_set_vpp(struct map_info *map, int vpp)
17386 + GPSR = GPIO_GPIO26;
17388 + GPCR = GPIO_GPIO26;
17389 + GPDR |= GPIO_GPIO26;
17392 +#define jornada56x_set_vpp NULL
17395 #ifdef CONFIG_SA1100_JORNADA720
17396 static struct mtd_partition jornada720_partitions[] = {
17398 @@ -822,6 +848,12 @@
17399 nb_parts = ARRAY_SIZE(huw_webpanel_partitions);
17402 +#ifdef CONFIG_SA1100_JORNADA56X
17403 + if (machine_is_jornada56x()) {
17404 + *parts = jornada56x_partitions;
17405 + nb_parts = ARRAY_SIZE(jornada56x_partitions);
17408 #ifdef CONFIG_SA1100_JORNADA720
17409 if (machine_is_jornada720()) {
17410 *parts = jornada720_partitions;
17411 @@ -932,10 +964,10 @@
17415 - sa[i].map->virt = (unsigned long)sa[i].vbase;
17416 + sa[i].map->virt = (void __iomem *)sa[i].vbase;
17417 sa[i].map->phys = sa[i].base;
17418 sa[i].map->set_vpp = sa[i].set_vpp;
17419 - sa[i].map->buswidth = sa[i].width;
17420 + sa[i].map->bankwidth = sa[i].width;
17421 sa[i].map->size = sa[i].size;
17423 simple_map_init(sa[i].map);
17424 @@ -1066,10 +1098,10 @@
17428 - sa1100_probe_map.buswidth = msc & MSC_RBW ? 2 : 4;
17429 + sa1100_probe_map.bankwidth = msc & MSC_RBW ? 2 : 4;
17430 sa1100_probe_map.size = SZ_1M;
17431 sa1100_probe_map.phys = phys;
17432 - sa1100_probe_map.virt = (unsigned long)ioremap(phys, SZ_1M);
17433 + sa1100_probe_map.virt = (void __iomem *)ioremap(phys, SZ_1M);
17434 if (sa1100_probe_map.virt == 0)
17436 simple_map_init(&sa1100_probe_map);
17437 @@ -1160,7 +1192,7 @@
17438 info[0].size = SZ_16M;
17441 - if (machine_is_h3xxx()) {
17442 + if (machine_is_ipaq()) {
17443 info[0].set_vpp = h3xxx_set_vpp;
17444 info[0].base = SA1100_CS0_PHYS;
17445 info[0].size = SZ_32M;
17446 @@ -1176,6 +1208,12 @@
17447 info[0].size = SZ_32M;
17450 + if (machine_is_jornada56x()) {
17451 + info[0].set_vpp = jornada56x_set_vpp;
17452 + info[0].base = SA1100_CS0_PHYS;
17453 + info[0].size = SZ_32M;
17456 if (machine_is_jornada720()) {
17457 info[0].set_vpp = jornada720_set_vpp;
17458 info[0].base = SA1100_CS0_PHYS;
17459 @@ -1253,7 +1291,7 @@
17463 - * Retrieve the buswidth from the MSC registers.
17464 + * Retrieve the bankwidth from the MSC registers.
17465 * We currently only implement CS0 and CS1 here.
17467 for (i = 0; i < nr; i++) {
17468 Index: linux-2.6.5/drivers/mtd/maps/sbc8240.c
17469 ===================================================================
17470 --- linux-2.6.5.orig/drivers/mtd/maps/sbc8240.c 1969-12-31 19:00:00.000000000 -0500
17471 +++ linux-2.6.5/drivers/mtd/maps/sbc8240.c 2005-02-01 17:11:17.000000000 -0500
17474 + * Handle mapping of the flash memory access routines on the SBC8240 board.
17476 + * Carolyn Smith, Tektronix, Inc.
17478 + * This code is GPLed
17480 + * $Id: sbc8240.c,v 1.4 2004/07/12 22:38:29 dwmw2 Exp $
17485 + * The SBC8240 has 2 flash banks.
17486 + * Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors.
17487 + * It contains the U-Boot code (7 sectors) and the environment (1 sector).
17488 + * Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector,
17489 + * 2 x 8 KiB sectors, 1 x 16 KiB sectors.
17490 + * Both parts are JEDEC compatible.
17493 +#include <linux/config.h>
17494 +#include <linux/module.h>
17495 +#include <linux/types.h>
17496 +#include <linux/kernel.h>
17497 +#include <asm/io.h>
17499 +#include <linux/mtd/mtd.h>
17500 +#include <linux/mtd/map.h>
17501 +#include <linux/mtd/cfi.h>
17503 +#ifdef CONFIG_MTD_PARTITIONS
17504 +#include <linux/mtd/partitions.h>
17510 +# define debugk(fmt,args...) printk(fmt ,##args)
17512 +# define debugk(fmt,args...)
17516 +#define WINDOW_ADDR0 0xFFF00000 /* 512 KiB */
17517 +#define WINDOW_SIZE0 0x00080000
17518 +#define BUSWIDTH0 1
17520 +#define WINDOW_ADDR1 0xFF000000 /* 4 MiB */
17521 +#define WINDOW_SIZE1 0x00400000
17522 +#define BUSWIDTH1 8
17524 +#define MSG_PREFIX "sbc8240:" /* prefix for our printk()'s */
17525 +#define MTDID "sbc8240-%d" /* for mtdparts= partitioning */
17528 +static struct map_info sbc8240_map[2] = {
17530 + .name = "sbc8240 Flash Bank #0",
17531 + .size = WINDOW_SIZE0,
17532 + .bankwidth = BUSWIDTH0,
17535 + .name = "sbc8240 Flash Bank #1",
17536 + .size = WINDOW_SIZE1,
17537 + .bankwidth = BUSWIDTH1,
17541 +#define NUM_FLASH_BANKS (sizeof(sbc8240_map) / sizeof(struct map_info))
17544 + * The following defines the partition layout of SBC8240 boards.
17546 + * See include/linux/mtd/partitions.h for definition of the
17547 + * mtd_partition structure.
17549 + * The *_max_flash_size is the maximum possible mapped flash size
17550 + * which is not necessarily the actual flash size. It must correspond
17551 + * to the value specified in the mapping definition defined by the
17552 + * "struct map_desc *_io_desc" for the corresponding machine.
17555 +#ifdef CONFIG_MTD_PARTITIONS
17557 +static struct mtd_partition sbc8240_uboot_partitions [] = {
17560 + .name = "U-boot", /* U-Boot Firmware */
17562 + .size = 0x00070000, /* 7 x 64 KiB sectors */
17563 + .mask_flags = MTD_WRITEABLE, /* force read-only */
17566 + .name = "environment", /* U-Boot environment */
17567 + .offset = 0x00070000,
17568 + .size = 0x00010000, /* 1 x 64 KiB sector */
17572 +static struct mtd_partition sbc8240_fs_partitions [] = {
17574 + .name = "jffs", /* JFFS filesystem */
17576 + .size = 0x003C0000, /* 4 * 15 * 64KiB */
17580 + .offset = 0x003C0000,
17581 + .size = 0x00020000, /* 4 * 32KiB */
17585 + .offset = 0x003E0000,
17586 + .size = 0x00008000, /* 4 * 8KiB */
17590 + .offset = 0x003E8000,
17591 + .size = 0x00008000, /* 4 * 8KiB */
17595 + .offset = 0x003F0000,
17596 + .size = 0x00010000, /* 4 * 16KiB */
17600 +#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
17602 +/* trivial struct to describe partition information */
17603 +struct mtd_part_def
17606 + unsigned char *type;
17607 + struct mtd_partition* mtd_part;
17610 +static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS];
17611 +static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS];
17614 +#endif /* CONFIG_MTD_PARTITIONS */
17617 +int __init init_sbc8240_mtd (void)
17619 + static struct _cjs {
17622 + } pt[NUM_FLASH_BANKS] = {
17624 + .addr = WINDOW_ADDR0,
17625 + .size = WINDOW_SIZE0
17628 + .addr = WINDOW_ADDR1,
17629 + .size = WINDOW_SIZE1
17633 + int devicesfound = 0;
17636 + for (i = 0; i < NUM_FLASH_BANKS; i++) {
17637 + printk (KERN_NOTICE MSG_PREFIX
17638 + "Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr);
17640 + sbc8240_map[i].map_priv_1 =
17641 + (unsigned long) ioremap (pt[i].addr, pt[i].size);
17642 + if (!sbc8240_map[i].map_priv_1) {
17643 + printk (MSG_PREFIX "failed to ioremap\n");
17646 + simple_map_init(&sbc8240_mtd[i]);
17648 + sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]);
17650 + if (sbc8240_mtd[i]) {
17651 + sbc8240_mtd[i]->module = THIS_MODULE;
17656 + if (!devicesfound) {
17657 + printk(KERN_NOTICE MSG_PREFIX
17658 + "No suppported flash chips found!\n");
17662 +#ifdef CONFIG_MTD_PARTITIONS
17663 + sbc8240_part_banks[0].mtd_part = sbc8240_uboot_partitions;
17664 + sbc8240_part_banks[0].type = "static image";
17665 + sbc8240_part_banks[0].nums = NB_OF(sbc8240_uboot_partitions);
17666 + sbc8240_part_banks[1].mtd_part = sbc8240_fs_partitions;
17667 + sbc8240_part_banks[1].type = "static file system";
17668 + sbc8240_part_banks[1].nums = NB_OF(sbc8240_fs_partitions);
17670 + for (i = 0; i < NUM_FLASH_BANKS; i++) {
17672 + if (!sbc8240_mtd[i]) continue;
17673 + if (sbc8240_part_banks[i].nums == 0) {
17674 + printk (KERN_NOTICE MSG_PREFIX
17675 + "No partition info available, registering whole device\n");
17676 + add_mtd_device(sbc8240_mtd[i]);
17678 + printk (KERN_NOTICE MSG_PREFIX
17679 + "Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name);
17680 + add_mtd_partitions (sbc8240_mtd[i],
17681 + sbc8240_part_banks[i].mtd_part,
17682 + sbc8240_part_banks[i].nums);
17686 + printk(KERN_NOTICE MSG_PREFIX
17687 + "Registering %d flash banks at once\n", devicesfound);
17689 + for (i = 0; i < devicesfound; i++) {
17690 + add_mtd_device(sbc8240_mtd[i]);
17692 +#endif /* CONFIG_MTD_PARTITIONS */
17694 + return devicesfound == 0 ? -ENXIO : 0;
17697 +static void __exit cleanup_sbc8240_mtd (void)
17701 + for (i = 0; i < NUM_FLASH_BANKS; i++) {
17702 + if (sbc8240_mtd[i]) {
17703 + del_mtd_device (sbc8240_mtd[i]);
17704 + map_destroy (sbc8240_mtd[i]);
17706 + if (sbc8240_map[i].map_priv_1) {
17707 + iounmap ((void *) sbc8240_map[i].map_priv_1);
17708 + sbc8240_map[i].map_priv_1 = 0;
17713 +module_init (init_sbc8240_mtd);
17714 +module_exit (cleanup_sbc8240_mtd);
17716 +MODULE_LICENSE ("GPL");
17717 +MODULE_AUTHOR ("Carolyn Smith <carolyn.smith@tektronix.com>");
17718 +MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards");
17720 Index: linux-2.6.5/drivers/mtd/maps/sbc_gxx.c
17721 ===================================================================
17722 --- linux-2.6.5.orig/drivers/mtd/maps/sbc_gxx.c 2004-04-03 22:37:23.000000000 -0500
17723 +++ linux-2.6.5/drivers/mtd/maps/sbc_gxx.c 2005-02-01 17:11:17.000000000 -0500
17725 along with this program; if not, write to the Free Software
17726 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
17728 - $Id: sbc_gxx.c,v 1.26 2003/05/26 08:50:36 dwmw2 Exp $
17729 + $Id: sbc_gxx.c,v 1.30 2004/09/16 23:27:14 gleixner Exp $
17731 The SBC-MediaGX / SBC-GXx has up to 16 MiB of
17732 Intel StrataFlash (28F320/28F640) in x8 mode.
17736 static volatile int page_in_window = -1; // Current page in window.
17737 -static unsigned long iomapadr;
17738 +static void __iomem *iomapadr;
17739 static spinlock_t sbc_gxx_spin = SPIN_LOCK_UNLOCKED;
17741 /* partition_info gives details on the logical partitions that the split the
17742 @@ -114,32 +114,12 @@
17746 -static __u8 sbc_gxx_read8(struct map_info *map, unsigned long ofs)
17747 +static map_word sbc_gxx_read8(struct map_info *map, unsigned long ofs)
17751 spin_lock(&sbc_gxx_spin);
17752 sbc_gxx_page(map, ofs);
17753 - ret = readb(iomapadr + (ofs & WINDOW_MASK));
17754 - spin_unlock(&sbc_gxx_spin);
17758 -static __u16 sbc_gxx_read16(struct map_info *map, unsigned long ofs)
17761 - spin_lock(&sbc_gxx_spin);
17762 - sbc_gxx_page(map, ofs);
17763 - ret = readw(iomapadr + (ofs & WINDOW_MASK));
17764 - spin_unlock(&sbc_gxx_spin);
17768 -static __u32 sbc_gxx_read32(struct map_info *map, unsigned long ofs)
17771 - spin_lock(&sbc_gxx_spin);
17772 - sbc_gxx_page(map, ofs);
17773 - ret = readl(iomapadr + (ofs & WINDOW_MASK));
17774 + ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK));
17775 spin_unlock(&sbc_gxx_spin);
17778 @@ -161,27 +141,11 @@
17782 -static void sbc_gxx_write8(struct map_info *map, __u8 d, unsigned long adr)
17784 - spin_lock(&sbc_gxx_spin);
17785 - sbc_gxx_page(map, adr);
17786 - writeb(d, iomapadr + (adr & WINDOW_MASK));
17787 - spin_unlock(&sbc_gxx_spin);
17790 -static void sbc_gxx_write16(struct map_info *map, __u16 d, unsigned long adr)
17792 - spin_lock(&sbc_gxx_spin);
17793 - sbc_gxx_page(map, adr);
17794 - writew(d, iomapadr + (adr & WINDOW_MASK));
17795 - spin_unlock(&sbc_gxx_spin);
17798 -static void sbc_gxx_write32(struct map_info *map, __u32 d, unsigned long adr)
17799 +static void sbc_gxx_write8(struct map_info *map, map_word d, unsigned long adr)
17801 spin_lock(&sbc_gxx_spin);
17802 sbc_gxx_page(map, adr);
17803 - writel(d, iomapadr + (adr & WINDOW_MASK));
17804 + writeb(d.x[0], iomapadr + (adr & WINDOW_MASK));
17805 spin_unlock(&sbc_gxx_spin);
17808 @@ -208,14 +172,10 @@
17809 .size = MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount
17810 of flash so the cfi probe routines find all
17813 - .read8 = sbc_gxx_read8,
17814 - .read16 = sbc_gxx_read16,
17815 - .read32 = sbc_gxx_read32,
17817 + .read = sbc_gxx_read8,
17818 .copy_from = sbc_gxx_copy_from,
17819 - .write8 = sbc_gxx_write8,
17820 - .write16 = sbc_gxx_write16,
17821 - .write32 = sbc_gxx_write32,
17822 + .write = sbc_gxx_write8,
17823 .copy_to = sbc_gxx_copy_to
17826 @@ -235,7 +195,7 @@
17828 int __init init_sbc_gxx(void)
17830 - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
17831 + iomapadr = (void __iomem *)ioremap(WINDOW_START, WINDOW_LENGTH);
17833 printk( KERN_ERR"%s: failed to ioremap memory region\n",
17834 sbc_gxx_map.name );
17835 Index: linux-2.6.5/drivers/mtd/maps/sc520cdp.c
17836 ===================================================================
17837 --- linux-2.6.5.orig/drivers/mtd/maps/sc520cdp.c 2004-04-03 22:38:17.000000000 -0500
17838 +++ linux-2.6.5/drivers/mtd/maps/sc520cdp.c 2005-02-01 17:11:17.000000000 -0500
17840 * along with this program; if not, write to the Free Software
17841 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
17843 - * $Id: sc520cdp.c,v 1.15 2003/05/21 12:45:20 dwmw2 Exp $
17844 + * $Id: sc520cdp.c,v 1.17 2004/09/16 23:27:14 gleixner Exp $
17847 * The SC520CDP is an evaluation board for the Elan SC520 processor available
17848 @@ -90,19 +90,19 @@
17850 .name = "SC520CDP Flash Bank #0",
17851 .size = WINDOW_SIZE_0,
17854 .phys = WINDOW_ADDR_0
17857 .name = "SC520CDP Flash Bank #1",
17858 .size = WINDOW_SIZE_1,
17861 .phys = WINDOW_ADDR_1
17864 .name = "SC520CDP DIL Flash",
17865 .size = WINDOW_SIZE_2,
17868 .phys = WINDOW_ADDR_2
17871 @@ -241,7 +241,7 @@
17872 printk(KERN_NOTICE "SC520 CDP flash device: 0x%lx at 0x%lx\n",
17873 sc520cdp_map[i].size, sc520cdp_map[i].phys);
17875 - sc520cdp_map[i].virt = (unsigned long)ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size);
17876 + sc520cdp_map[i].virt = (void __iomem *)ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size);
17878 if (!sc520cdp_map[i].virt) {
17879 printk("Failed to ioremap_nocache\n");
17880 Index: linux-2.6.5/drivers/mtd/maps/scb2_flash.c
17881 ===================================================================
17882 --- linux-2.6.5.orig/drivers/mtd/maps/scb2_flash.c 2004-04-03 22:37:23.000000000 -0500
17883 +++ linux-2.6.5/drivers/mtd/maps/scb2_flash.c 2005-02-01 17:11:17.000000000 -0500
17886 * MTD map driver for BIOS Flash on Intel SCB2 boards
17887 - * $Id: scb2_flash.c,v 1.6 2003/05/21 12:45:20 dwmw2 Exp $
17888 + * $Id: scb2_flash.c,v 1.9 2004/09/16 23:27:14 gleixner Exp $
17889 * Copyright (C) 2002 Sun Microsystems, Inc.
17890 * Tim Hockin <thockin@sun.com>
17893 struct map_info scb2_map = {
17894 .name = "SCB2 BIOS Flash",
17899 static int region_fail;
17901 @@ -163,7 +163,7 @@
17904 scb2_map.phys = SCB2_ADDR;
17905 - scb2_map.virt = (unsigned long)scb2_ioaddr;
17906 + scb2_map.virt = (void __iomem *)scb2_ioaddr;
17907 scb2_map.size = SCB2_WINDOW;
17909 simple_map_init(&scb2_map);
17910 Index: linux-2.6.5/drivers/mtd/maps/scx200_docflash.c
17911 ===================================================================
17912 --- linux-2.6.5.orig/drivers/mtd/maps/scx200_docflash.c 2004-04-03 22:37:37.000000000 -0500
17913 +++ linux-2.6.5/drivers/mtd/maps/scx200_docflash.c 2005-02-01 17:11:17.000000000 -0500
17916 Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
17918 - $Id: scx200_docflash.c,v 1.5 2003/05/21 12:45:20 dwmw2 Exp $
17919 + $Id: scx200_docflash.c,v 1.7 2004/09/16 23:27:14 gleixner Exp $
17921 National Semiconductor SCx200 flash mapped with DOCCS
17923 @@ -173,14 +173,14 @@
17925 scx200_docflash_map.size = size;
17927 - scx200_docflash_map.buswidth = 1;
17928 + scx200_docflash_map.bankwidth = 1;
17930 - scx200_docflash_map.buswidth = 2;
17931 + scx200_docflash_map.bankwidth = 2;
17933 simple_map_init(&scx200_docflash_map);
17935 scx200_docflash_map.phys = docmem.start;
17936 - scx200_docflash_map.virt = (unsigned long)ioremap(docmem.start, scx200_docflash_map.size);
17937 + scx200_docflash_map.virt = (void __iomem *)ioremap(docmem.start, scx200_docflash_map.size);
17938 if (!scx200_docflash_map.virt) {
17939 printk(KERN_ERR NAME ": failed to ioremap the flash\n");
17940 release_resource(&docmem);
17941 Index: linux-2.6.5/drivers/mtd/maps/solutionengine.c
17942 ===================================================================
17943 --- linux-2.6.5.orig/drivers/mtd/maps/solutionengine.c 2004-04-03 22:38:18.000000000 -0500
17944 +++ linux-2.6.5/drivers/mtd/maps/solutionengine.c 2005-02-01 17:11:17.000000000 -0500
17947 - * $Id: solutionengine.c,v 1.10 2003/05/21 12:45:20 dwmw2 Exp $
17948 + * $Id: solutionengine.c,v 1.14 2004/09/16 23:27:14 gleixner Exp $
17950 * Flash and EPROM on Hitachi Solution Engine and similar boards.
17953 #include <linux/mtd/map.h>
17954 #include <linux/mtd/partitions.h>
17955 #include <linux/config.h>
17957 +#include <linux/errno.h>
17959 static struct mtd_info *flash_mtd;
17960 static struct mtd_info *eprom_mtd;
17961 @@ -27,13 +27,13 @@
17962 struct map_info soleng_eprom_map = {
17963 .name = "Solution Engine EPROM",
17969 struct map_info soleng_flash_map = {
17970 .name = "Solution Engine FLASH",
17976 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
17979 /* First probe at offset 0 */
17980 soleng_flash_map.phys = 0;
17981 - soleng_flash_map.virt = P2SEGADDR(0);
17982 + soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0);
17983 soleng_eprom_map.phys = 0x01000000;
17984 - soleng_eprom_map.virt = P1SEGADDR(0x01000000);
17985 + soleng_eprom_map.virt = (void __iomem *)P1SEGADDR(0x01000000);
17986 simple_map_init(&soleng_eprom_map);
17987 simple_map_init(&soleng_flash_map);
17989 Index: linux-2.6.5/drivers/mtd/maps/sun_uflash.c
17990 ===================================================================
17991 --- linux-2.6.5.orig/drivers/mtd/maps/sun_uflash.c 2004-04-03 22:37:36.000000000 -0500
17992 +++ linux-2.6.5/drivers/mtd/maps/sun_uflash.c 2005-02-01 17:11:17.000000000 -0500
17994 -/* $Id: sun_uflash.c,v 1.7 2003/05/20 20:59:32 dwmw2 Exp $
17995 +/* $Id: sun_uflash.c,v 1.10 2004/09/16 23:27:14 gleixner Exp $
17997 * sun_uflash - Driver implementation for user-programmable flash
17998 * present on many Sun Microsystems SME boardsets.
18000 struct map_info uflash_map_templ = {
18001 .name = "SUNW,???-????",
18002 .size = UFLASH_WINDOW_SIZE,
18003 - .buswidth = UFLASH_BUSWIDTH,
18004 + .bankwidth = UFLASH_BUSWIDTH,
18007 int uflash_devinit(struct linux_ebus_device* edev)
18010 pdev->map.phys = edev->resource[0].start;
18012 - (unsigned long)ioremap_nocache(edev->resource[0].start, pdev->map.size);
18013 + (void __iomem *)ioremap_nocache(edev->resource[0].start, pdev->map.size);
18014 if(0 == pdev->map.virt) {
18015 printk("%s: failed to map device\n", __FUNCTION__);
18017 Index: linux-2.6.5/drivers/mtd/maps/tqm8xxl.c
18018 ===================================================================
18019 --- linux-2.6.5.orig/drivers/mtd/maps/tqm8xxl.c 2004-04-03 22:36:26.000000000 -0500
18020 +++ linux-2.6.5/drivers/mtd/maps/tqm8xxl.c 2005-02-01 17:11:17.000000000 -0500
18022 * Handle mapping of the flash memory access routines
18023 * on TQM8xxL based devices.
18025 - * $Id: tqm8xxl.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $
18026 + * $Id: tqm8xxl.c,v 1.12 2004/09/16 23:27:14 gleixner Exp $
18028 * based on rpxlite.c
18030 @@ -105,7 +105,7 @@
18032 .offset = 0x00200000,
18033 .size = 0x00200000,
18034 - .//size = MTDPART_SIZ_FULL,
18035 + //.size = MTDPART_SIZ_FULL,
18039 @@ -151,11 +151,11 @@
18040 sprintf(map_banks[idx]->name, "TQM8xxL%d", idx);
18042 map_banks[idx]->size = flash_size;
18043 - map_banks[idx]->buswidth = 4;
18044 + map_banks[idx]->bankwidth = 4;
18046 simple_map_init(map_banks[idx]);
18048 - map_banks[idx]->virt = start_scan_addr;
18049 + map_banks[idx]->virt = (void __iomem *)start_scan_addr;
18050 map_banks[idx]->phys = flash_addr;
18051 /* FIXME: This looks utterly bogus, but I'm trying to
18052 preserve the behaviour of the original (shown here)...
18053 Index: linux-2.6.5/drivers/mtd/maps/tsunami_flash.c
18054 ===================================================================
18055 --- linux-2.6.5.orig/drivers/mtd/maps/tsunami_flash.c 2004-04-03 22:38:16.000000000 -0500
18056 +++ linux-2.6.5/drivers/mtd/maps/tsunami_flash.c 2005-02-01 17:11:17.000000000 -0500
18060 * flash chip on alpha ds10...
18061 - * $Id: tsunami_flash.c,v 1.6 2003/05/21 15:15:08 dwmw2 Exp $
18062 + * $Id: tsunami_flash.c,v 1.9 2004/07/14 09:52:55 dwmw2 Exp $
18064 #include <asm/io.h>
18065 #include <asm/core_tsunami.h>
18066 @@ -15,14 +15,16 @@
18067 #define FLASH_DISABLE_BYTE 0x00
18069 #define MAX_TIG_FLASH_SIZE (12*1024*1024)
18070 -static inline __u8 tsunami_flash_read8(struct map_info *map, unsigned long offset)
18071 +static inline map_word tsunami_flash_read8(struct map_info *map, unsigned long offset)
18073 - return tsunami_tig_readb(offset);
18075 + val.x[0] = tsunami_tig_readb(offset);
18079 -static void tsunami_flash_write8(struct map_info *map, __u8 value, unsigned long offset)
18080 +static void tsunami_flash_write8(struct map_info *map, map_word value, unsigned long offset)
18082 - tsunami_tig_writeb(value, offset);
18083 + tsunami_tig_writeb(value.x[0], offset);
18086 static void tsunami_flash_copy_from(
18087 @@ -61,10 +63,10 @@
18088 .name = "flash chip on the Tsunami TIG bus",
18089 .size = MAX_TIG_FLASH_SIZE,
18092 - .read8 = tsunami_flash_read8,
18094 + .read = tsunami_flash_read8,
18095 .copy_from = tsunami_flash_copy_from,
18096 - .write8 = tsunami_flash_write8,
18097 + .write = tsunami_flash_write8,
18098 .copy_to = tsunami_flash_copy_to,
18103 static int __init init_tsunami_flash(void)
18105 - static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", 0 };
18106 + static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
18109 tsunami_tig_writeb(FLASH_ENABLE_BYTE, FLASH_ENABLE_PORT);
18110 Index: linux-2.6.5/drivers/mtd/maps/uclinux.c
18111 ===================================================================
18112 --- linux-2.6.5.orig/drivers/mtd/maps/uclinux.c 2004-04-03 22:38:16.000000000 -0500
18113 +++ linux-2.6.5/drivers/mtd/maps/uclinux.c 2005-02-01 17:11:17.000000000 -0500
18116 * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
18118 - * $Id: uclinux.c,v 1.5 2003/05/20 20:59:32 dwmw2 Exp $
18119 + * $Id: uclinux.c,v 1.8 2004/09/16 23:27:14 gleixner Exp $
18122 /****************************************************************************/
18124 #include <linux/kernel.h>
18125 #include <linux/fs.h>
18126 #include <linux/major.h>
18127 +#include <linux/root_dev.h>
18128 #include <linux/mtd/mtd.h>
18129 #include <linux/mtd/map.h>
18130 #include <linux/mtd/partitions.h>
18131 @@ -63,12 +64,12 @@
18132 mapp = &uclinux_ram_map;
18133 mapp->phys = (unsigned long) &_ebss;
18134 mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8)));
18135 - mapp->buswidth = 4;
18136 + mapp->bankwidth = 4;
18138 printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
18139 (int) mapp->map_priv_2, (int) mapp->size);
18141 - mapp->virt = (unsigned long)
18142 + mapp->virt = (void __iomem *)
18143 ioremap_nocache(mapp->phys, mapp->size);
18145 if (mapp->virt == 0) {
18146 Index: linux-2.6.5/drivers/mtd/maps/vmax301.c
18147 ===================================================================
18148 --- linux-2.6.5.orig/drivers/mtd/maps/vmax301.c 2004-04-03 22:36:54.000000000 -0500
18149 +++ linux-2.6.5/drivers/mtd/maps/vmax301.c 2005-02-01 17:11:17.000000000 -0500
18151 -// $Id: vmax301.c,v 1.28 2003/05/21 15:15:08 dwmw2 Exp $
18152 +// $Id: vmax301.c,v 1.30 2004/07/12 22:38:29 dwmw2 Exp $
18153 /* ######################################################################
18155 Tempustech VMAX SBC301 MTD Driver.
18156 @@ -54,32 +54,12 @@
18157 __vmax301_page(map, page);
18160 -static __u8 vmax301_read8(struct map_info *map, unsigned long ofs)
18161 +static map_word vmax301_read8(struct map_info *map, unsigned long ofs)
18165 spin_lock(&vmax301_spin);
18166 vmax301_page(map, ofs);
18167 - ret = readb(map->map_priv_2 + (ofs & WINDOW_MASK));
18168 - spin_unlock(&vmax301_spin);
18172 -static __u16 vmax301_read16(struct map_info *map, unsigned long ofs)
18175 - spin_lock(&vmax301_spin);
18176 - vmax301_page(map, ofs);
18177 - ret = readw(map->map_priv_2 + (ofs & WINDOW_MASK));
18178 - spin_unlock(&vmax301_spin);
18182 -static __u32 vmax301_read32(struct map_info *map, unsigned long ofs)
18185 - spin_lock(&vmax301_spin);
18186 - vmax301_page(map, ofs);
18187 - ret = readl(map->map_priv_2 + (ofs & WINDOW_MASK));
18188 + ret.x[0] = readb(map->map_priv_2 + (ofs & WINDOW_MASK));
18189 spin_unlock(&vmax301_spin);
18192 @@ -100,27 +80,11 @@
18196 -static void vmax301_write8(struct map_info *map, __u8 d, unsigned long adr)
18198 - spin_lock(&vmax301_spin);
18199 - vmax301_page(map, adr);
18200 - writeb(d, map->map_priv_2 + (adr & WINDOW_MASK));
18201 - spin_unlock(&vmax301_spin);
18204 -static void vmax301_write16(struct map_info *map, __u16 d, unsigned long adr)
18206 - spin_lock(&vmax301_spin);
18207 - vmax301_page(map, adr);
18208 - writew(d, map->map_priv_2 + (adr & WINDOW_MASK));
18209 - spin_unlock(&vmax301_spin);
18212 -static void vmax301_write32(struct map_info *map, __u32 d, unsigned long adr)
18213 +static void vmax301_write8(struct map_info *map, map_word d, unsigned long adr)
18215 spin_lock(&vmax301_spin);
18216 vmax301_page(map, adr);
18217 - writel(d, map->map_priv_2 + (adr & WINDOW_MASK));
18218 + writeb(d.x[0], map->map_priv_2 + (adr & WINDOW_MASK));
18219 spin_unlock(&vmax301_spin);
18222 @@ -146,14 +110,10 @@
18223 .name = "VMAX301 Internal Flash",
18225 .size = 3*2*1024*1024,
18227 - .read8 = vmax301_read8,
18228 - .read16 = vmax301_read16,
18229 - .read32 = vmax301_read32,
18231 + .read = vmax301_read8,
18232 .copy_from = vmax301_copy_from,
18233 - .write8 = vmax301_write8,
18234 - .write16 = vmax301_write16,
18235 - .write32 = vmax301_write32,
18236 + .write = vmax301_write8,
18237 .copy_to = vmax301_copy_to,
18238 .map_priv_1 = WINDOW_START + WINDOW_LENGTH,
18239 .map_priv_2 = 0xFFFFFFFF
18240 @@ -162,14 +122,10 @@
18241 .name = "VMAX301 Socket",
18245 - .read8 = vmax301_read8,
18246 - .read16 = vmax301_read16,
18247 - .read32 = vmax301_read32,
18249 + .read = vmax301_read8,
18250 .copy_from = vmax301_copy_from,
18251 - .write8 = vmax301_write8,
18252 - .write16 = vmax301_write16,
18253 - .write32 = vmax301_write32,
18254 + .write = vmax301_write8,
18255 .copy_to = vmax301_copy_to,
18256 .map_priv_1 = WINDOW_START + (3*WINDOW_LENGTH),
18257 .map_priv_2 = 0xFFFFFFFF
18258 Index: linux-2.6.5/drivers/mtd/maps/wr_sbc82xx_flash.c
18259 ===================================================================
18260 --- linux-2.6.5.orig/drivers/mtd/maps/wr_sbc82xx_flash.c 1969-12-31 19:00:00.000000000 -0500
18261 +++ linux-2.6.5/drivers/mtd/maps/wr_sbc82xx_flash.c 2005-02-01 17:11:17.000000000 -0500
18264 + * $Id: wr_sbc82xx_flash.c,v 1.6 2004/09/16 23:27:14 gleixner Exp $
18266 + * Map for flash chips on Wind River PowerQUICC II SBC82xx board.
18268 + * Copyright (C) 2004 Red Hat, Inc.
18270 + * Author: David Woodhouse <dwmw2@infradead.org>
18274 +#include <linux/module.h>
18275 +#include <linux/types.h>
18276 +#include <linux/kernel.h>
18277 +#include <linux/init.h>
18278 +#include <linux/slab.h>
18279 +#include <asm/io.h>
18280 +#include <linux/mtd/mtd.h>
18281 +#include <linux/mtd/map.h>
18282 +#include <linux/config.h>
18283 +#include <linux/mtd/partitions.h>
18285 +#include <asm/immap_cpm2.h>
18287 +static struct mtd_info *sbcmtd[3];
18288 +static struct mtd_partition *sbcmtd_parts[3];
18290 +struct map_info sbc82xx_flash_map[3] = {
18291 + {.name = "Boot flash"},
18292 + {.name = "Alternate boot flash"},
18293 + {.name = "User flash"}
18296 +static struct mtd_partition smallflash_parts[] = {
18299 + .size = 0x100000,
18302 + .name = "bootloader",
18303 + .size = MTDPART_SIZ_FULL,
18304 + .offset = MTDPART_OFS_APPEND,
18308 +static struct mtd_partition bigflash_parts[] = {
18310 + .name = "bootloader",
18311 + .size = 0x00100000,
18314 + .name = "file system",
18315 + .size = 0x01f00000,
18316 + .offset = MTDPART_OFS_APPEND,
18318 + .name = "boot config",
18319 + .size = 0x00100000,
18320 + .offset = MTDPART_OFS_APPEND,
18323 + .size = 0x01f00000,
18324 + .offset = MTDPART_OFS_APPEND,
18328 +static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
18330 +#define init_sbc82xx_one_flash(map, br, or) \
18332 + (map).phys = (br & 1) ? (br & 0xffff8000) : 0; \
18333 + (map).size = (br & 1) ? (~(or & 0xffff8000) + 1) : 0; \
18334 + switch (br & 0x00001800) { \
18335 + case 0x00000000: \
18336 + case 0x00000800: (map).bankwidth = 1; break; \
18337 + case 0x00001000: (map).bankwidth = 2; break; \
18338 + case 0x00001800: (map).bankwidth = 4; break; \
18342 +int __init init_sbc82xx_flash(void)
18344 + volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl;
18348 +#ifdef CONFIG_SBC8560
18349 + mc = ioremap(0xff700000 + 0x5000, sizeof(memctl_cpm2_t));
18351 + mc = &cpm2_immr->im_memctl;
18355 + if ((mc->memc_br0 & 0x00001800) == 0x00001800)
18358 + init_sbc82xx_one_flash(sbc82xx_flash_map[0], mc->memc_br0, mc->memc_or0);
18359 + init_sbc82xx_one_flash(sbc82xx_flash_map[1], mc->memc_br6, mc->memc_or6);
18360 + init_sbc82xx_one_flash(sbc82xx_flash_map[2], mc->memc_br1, mc->memc_or1);
18362 +#ifdef CONFIG_SBC8560
18363 + iounmap((void *) mc);
18366 + for (i=0; i<3; i++) {
18367 + int8_t flashcs[3] = { 0, 6, 1 };
18370 + printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
18371 + sbc82xx_flash_map[i].name,
18372 + (sbc82xx_flash_map[i].size >> 20),
18374 + if (!sbc82xx_flash_map[i].phys) {
18375 + /* We know it can't be at zero. */
18376 + printk("): disabled by bootloader.\n");
18379 + printk(" at %08lx)\n", sbc82xx_flash_map[i].phys);
18381 + sbc82xx_flash_map[i].virt = (void __iomem *)ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size);
18383 + if (!sbc82xx_flash_map[i].virt) {
18384 + printk("Failed to ioremap\n");
18388 + simple_map_init(&sbc82xx_flash_map[i]);
18390 + sbcmtd[i] = do_map_probe("cfi_probe", &sbc82xx_flash_map[i]);
18395 + sbcmtd[i]->owner = THIS_MODULE;
18397 + nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes,
18398 + &sbcmtd_parts[i], 0);
18399 + if (nr_parts > 0) {
18400 + add_mtd_partitions (sbcmtd[i], sbcmtd_parts[i], nr_parts);
18404 + /* No partitioning detected. Use default */
18406 + add_mtd_device(sbcmtd[i]);
18407 + } else if (i == bigflash) {
18408 + add_mtd_partitions (sbcmtd[i], bigflash_parts, ARRAY_SIZE(bigflash_parts));
18410 + add_mtd_partitions (sbcmtd[i], smallflash_parts, ARRAY_SIZE(smallflash_parts));
18416 +static void __exit cleanup_sbc82xx_flash(void)
18420 + for (i=0; i<3; i++) {
18424 + if (i<2 || sbcmtd_parts[i])
18425 + del_mtd_partitions(sbcmtd[i]);
18427 + del_mtd_device(sbcmtd[i]);
18429 + kfree(sbcmtd_parts[i]);
18430 + map_destroy(sbcmtd[i]);
18432 + iounmap((void *)sbc82xx_flash_map[i].virt);
18433 + sbc82xx_flash_map[i].virt = 0;
18437 +module_init(init_sbc82xx_flash);
18438 +module_exit(cleanup_sbc82xx_flash);
18441 +MODULE_LICENSE("GPL");
18442 +MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
18443 +MODULE_DESCRIPTION("Flash map driver for WindRiver PowerQUICC II");
18444 Index: linux-2.6.5/drivers/mtd/mtd_blkdevs-24.c
18445 ===================================================================
18446 --- linux-2.6.5.orig/drivers/mtd/mtd_blkdevs-24.c 1969-12-31 19:00:00.000000000 -0500
18447 +++ linux-2.6.5/drivers/mtd/mtd_blkdevs-24.c 2005-02-01 17:11:17.000000000 -0500
18450 + * $Id: mtd_blkdevs-24.c,v 1.16 2004/08/11 15:29:24 dmarlin Exp $
18452 + * (C) 2003 David Woodhouse <dwmw2@infradead.org>
18454 + * Interface to Linux 2.4 block layer for MTD 'translation layers'.
18458 +#include <linux/kernel.h>
18459 +#include <linux/slab.h>
18460 +#include <linux/module.h>
18461 +#include <linux/list.h>
18462 +#include <linux/fs.h>
18463 +#include <linux/mtd/blktrans.h>
18464 +#include <linux/mtd/mtd.h>
18465 +#include <linux/blkdev.h>
18466 +#include <linux/blk.h>
18467 +#include <linux/blkpg.h>
18468 +#include <linux/spinlock.h>
18469 +#include <linux/hdreg.h>
18470 +#include <linux/init.h>
18471 +#include <asm/semaphore.h>
18472 +#include <asm/uaccess.h>
18474 +static LIST_HEAD(blktrans_majors);
18476 +extern struct semaphore mtd_table_mutex;
18477 +extern struct mtd_info *mtd_table[];
18479 +struct mtd_blkcore_priv {
18480 + devfs_handle_t devfs_dir_handle;
18481 + int blksizes[256];
18483 + struct hd_struct part_table[256];
18484 + struct gendisk gd;
18485 + spinlock_t devs_lock; /* See comment in _request function */
18486 + struct completion thread_dead;
18488 + wait_queue_head_t thread_wq;
18491 +static inline struct mtd_blktrans_dev *tr_get_dev(struct mtd_blktrans_ops *tr,
18494 + struct list_head *this;
18495 + struct mtd_blktrans_dev *d;
18497 + list_for_each(this, &tr->devs) {
18498 + d = list_entry(this, struct mtd_blktrans_dev, list);
18500 + if (d->devnum == devnum)
18506 +static inline struct mtd_blktrans_ops *get_tr(int major)
18508 + struct list_head *this;
18509 + struct mtd_blktrans_ops *t;
18511 + list_for_each(this, &blktrans_majors) {
18512 + t = list_entry(this, struct mtd_blktrans_ops, list);
18514 + if (t->major == major)
18520 +static int do_blktrans_request(struct mtd_blktrans_ops *tr,
18521 + struct mtd_blktrans_dev *dev,
18522 + struct request *req)
18524 + unsigned long block, nsect;
18528 + minor = MINOR(req->rq_dev);
18529 + block = req->sector;
18530 + nsect = req->current_nr_sectors;
18531 + buf = req->buffer;
18533 + if (block + nsect > tr->blkcore_priv->part_table[minor].nr_sects) {
18534 + printk(KERN_WARNING "Access beyond end of device.\n");
18537 + block += tr->blkcore_priv->part_table[minor].start_sect;
18539 + switch(req->cmd) {
18541 + for (; nsect > 0; nsect--, block++, buf += 512)
18542 + if (tr->readsect(dev, block, buf))
18547 + if (!tr->writesect)
18550 + for (; nsect > 0; nsect--, block++, buf += 512)
18551 + if (tr->writesect(dev, block, buf))
18556 + printk(KERN_NOTICE "Unknown request cmd %d\n", req->cmd);
18561 +static int mtd_blktrans_thread(void *arg)
18563 + struct mtd_blktrans_ops *tr = arg;
18564 + struct request_queue *rq = BLK_DEFAULT_QUEUE(tr->major);
18566 + /* we might get involved when memory gets low, so use PF_MEMALLOC */
18567 + current->flags |= PF_MEMALLOC;
18569 + snprintf(current->comm, sizeof(current->comm), "%sd", tr->name);
18571 + /* daemonize() doesn't do this for us since some kernel threads
18572 + actually want to deal with signals. We can't just call
18573 + exit_sighand() since that'll cause an oops when we finally
18575 + spin_lock_irq(¤t->sigmask_lock);
18576 + sigfillset(¤t->blocked);
18577 + recalc_sigpending();
18578 + spin_unlock_irq(¤t->sigmask_lock);
18580 + daemonize("%sd", tr->name);
18582 + while (!tr->blkcore_priv->exiting) {
18583 + struct request *req;
18584 + struct mtd_blktrans_dev *dev;
18587 + DECLARE_WAITQUEUE(wait, current);
18589 + spin_lock_irq(&io_request_lock);
18591 + if (list_empty(&rq->queue_head)) {
18593 + add_wait_queue(&tr->blkcore_priv->thread_wq, &wait);
18594 + set_current_state(TASK_INTERRUPTIBLE);
18596 + spin_unlock_irq(&io_request_lock);
18599 + remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait);
18604 + req = blkdev_entry_next_request(&rq->queue_head);
18606 + devnum = MINOR(req->rq_dev) >> tr->part_bits;
18608 + /* The ll_rw_blk code knows not to touch the request
18609 + at the head of the queue */
18610 + spin_unlock_irq(&io_request_lock);
18612 + /* FIXME: Where can we store the dev, on which
18613 + we already have a refcount anyway? We need to
18614 + lock against concurrent addition/removal of devices,
18615 + but if we use the mtd_table_mutex we deadlock when
18616 + grok_partitions is called from the registration
18618 + spin_lock(&tr->blkcore_priv->devs_lock);
18619 + dev = tr_get_dev(tr, devnum);
18620 + spin_unlock(&tr->blkcore_priv->devs_lock);
18624 + /* Ensure serialisation of requests */
18627 + res = do_blktrans_request(tr, dev, req);
18630 + if (!end_that_request_first(req, res, tr->name)) {
18631 + spin_lock_irq(&io_request_lock);
18632 + blkdev_dequeue_request(req);
18633 + end_that_request_last(req);
18634 + spin_unlock_irq(&io_request_lock);
18637 + complete_and_exit(&tr->blkcore_priv->thread_dead, 0);
18640 +static void mtd_blktrans_request(struct request_queue *rq)
18642 + struct mtd_blktrans_ops *tr = rq->queuedata;
18643 + wake_up(&tr->blkcore_priv->thread_wq);
18646 +int blktrans_open(struct inode *i, struct file *f)
18648 + struct mtd_blktrans_ops *tr = NULL;
18649 + struct mtd_blktrans_dev *dev = NULL;
18650 + int major_nr = MAJOR(i->i_rdev);
18651 + int minor_nr = MINOR(i->i_rdev);
18653 + int ret = -ENODEV;
18655 + if (is_read_only(i->i_rdev) && (f->f_mode & FMODE_WRITE))
18658 + down(&mtd_table_mutex);
18660 + tr = get_tr(major_nr);
18665 + devnum = minor_nr >> tr->part_bits;
18667 + dev = tr_get_dev(tr, devnum);
18672 + if (!tr->blkcore_priv->part_table[minor_nr].nr_sects) {
18677 + if (!try_inc_mod_count(dev->mtd->owner))
18680 + if (!try_inc_mod_count(tr->owner))
18683 + dev->mtd->usecount++;
18686 + if (tr->open && (ret = tr->open(dev))) {
18687 + dev->mtd->usecount--;
18688 + if (dev->mtd->owner)
18689 + __MOD_DEC_USE_COUNT(dev->mtd->owner);
18692 + __MOD_DEC_USE_COUNT(tr->owner);
18695 + up(&mtd_table_mutex);
18700 +int blktrans_release(struct inode *i, struct file *f)
18702 + struct mtd_blktrans_dev *dev;
18703 + struct mtd_blktrans_ops *tr;
18707 + down(&mtd_table_mutex);
18709 + tr = get_tr(MAJOR(i->i_rdev));
18711 + up(&mtd_table_mutex);
18715 + devnum = MINOR(i->i_rdev) >> tr->part_bits;
18716 + dev = tr_get_dev(tr, devnum);
18719 + up(&mtd_table_mutex);
18724 + ret = tr->release(dev);
18727 + dev->mtd->usecount--;
18728 + if (dev->mtd->owner)
18729 + __MOD_DEC_USE_COUNT(dev->mtd->owner);
18731 + __MOD_DEC_USE_COUNT(tr->owner);
18734 + up(&mtd_table_mutex);
18739 +static int mtd_blktrans_rrpart(kdev_t rdev, struct mtd_blktrans_ops *tr,
18740 + struct mtd_blktrans_dev *dev)
18742 + struct gendisk *gd = &(tr->blkcore_priv->gd);
18744 + int minor = MINOR(rdev);
18746 + if (minor & ((1<<tr->part_bits)-1) || !tr->part_bits) {
18747 + /* BLKRRPART on a partition. Go away. */
18751 + if (!capable(CAP_SYS_ADMIN))
18754 + /* We are required to prevent simultaneous open() ourselves.
18755 + The core doesn't do that for us. Did I ever mention how
18756 + much the Linux block layer sucks? Sledgehammer approach... */
18757 + down(&mtd_table_mutex);
18759 + for (i=0; i < (1<<tr->part_bits); i++) {
18760 + invalidate_device(MKDEV(tr->major, minor+i), 1);
18761 + gd->part[minor + i].start_sect = 0;
18762 + gd->part[minor + i].nr_sects = 0;
18765 + grok_partitions(gd, minor, 1 << tr->part_bits,
18766 + tr->blkcore_priv->sizes[minor]);
18767 + up(&mtd_table_mutex);
18772 +static int blktrans_ioctl(struct inode *inode, struct file *file,
18773 + unsigned int cmd, unsigned long arg)
18775 + struct mtd_blktrans_dev *dev;
18776 + struct mtd_blktrans_ops *tr;
18781 + case BLKGETSIZE64:
18791 + return blk_ioctl(inode->i_rdev, cmd, arg);
18794 + down(&mtd_table_mutex);
18796 + tr = get_tr(MAJOR(inode->i_rdev));
18798 + up(&mtd_table_mutex);
18802 + devnum = MINOR(inode->i_rdev) >> tr->part_bits;
18803 + dev = tr_get_dev(tr, devnum);
18805 + up(&mtd_table_mutex);
18812 + return mtd_blktrans_rrpart(inode->i_rdev, tr, dev);
18815 + blk_ioctl(inode->i_rdev, cmd, arg);
18817 + return tr->flush(dev);
18818 + /* The core code did the work, we had nothing to do. */
18821 + case HDIO_GETGEO:
18822 + if (tr->getgeo) {
18823 + struct hd_geometry g;
18824 + struct gendisk *gd = &(tr->blkcore_priv->gd);
18827 + memset(&g, 0, sizeof(g));
18828 + ret = tr->getgeo(dev, &g);
18832 + g.start = gd->part[MINOR(inode->i_rdev)].start_sect;
18833 + if (copy_to_user((void *)arg, &g, sizeof(g)))
18842 +struct block_device_operations mtd_blktrans_ops = {
18843 + .owner = THIS_MODULE,
18844 + .open = blktrans_open,
18845 + .release = blktrans_release,
18846 + .ioctl = blktrans_ioctl,
18849 +int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
18851 + struct mtd_blktrans_ops *tr = new->tr;
18852 + struct list_head *this;
18853 + int last_devnum = -1;
18856 + if (!down_trylock(&mtd_table_mutex)) {
18857 + up(&mtd_table_mutex);
18861 + spin_lock(&tr->blkcore_priv->devs_lock);
18863 + list_for_each(this, &tr->devs) {
18864 + struct mtd_blktrans_dev *d = list_entry(this, struct mtd_blktrans_dev, list);
18865 + if (new->devnum == -1) {
18866 + /* Use first free number */
18867 + if (d->devnum != last_devnum+1) {
18868 + /* Found a free devnum. Plug it in here */
18869 + new->devnum = last_devnum+1;
18870 + list_add_tail(&new->list, &d->list);
18873 + } else if (d->devnum == new->devnum) {
18874 + /* Required number taken */
18875 + spin_unlock(&tr->blkcore_priv->devs_lock);
18877 + } else if (d->devnum > new->devnum) {
18878 + /* Required number was free */
18879 + list_add_tail(&new->list, &d->list);
18882 + last_devnum = d->devnum;
18884 + if (new->devnum == -1)
18885 + new->devnum = last_devnum+1;
18887 + if ((new->devnum << tr->part_bits) > 256) {
18888 + spin_unlock(&tr->blkcore_priv->devs_lock);
18892 + init_MUTEX(&new->sem);
18893 + list_add_tail(&new->list, &tr->devs);
18895 + spin_unlock(&tr->blkcore_priv->devs_lock);
18897 + if (!tr->writesect)
18898 + new->readonly = 1;
18900 + for (i = new->devnum << tr->part_bits;
18901 + i < (new->devnum+1) << tr->part_bits;
18903 + set_device_ro(MKDEV(tr->major, i), new->readonly);
18904 + tr->blkcore_priv->blksizes[i] = new->blksize;
18905 + tr->blkcore_priv->sizes[i] = 0;
18906 + tr->blkcore_priv->part_table[i].nr_sects = 0;
18907 + tr->blkcore_priv->part_table[i].start_sect = 0;
18911 + <viro_zzz> dwmw2: BLOCK_SIZE_BITS has nothing to do with block devices
18912 + <viro> dwmw2: any code which sets blk_size[][] should be
18913 + size >> 10 /+ 2.4 and its dumb units */
18915 + tr->blkcore_priv->sizes[new->devnum << tr->part_bits] =
18916 + (new->size * new->blksize) >> 10; /* 2.4 and its dumb units */
18918 + /* But this is still in device's sectors? $DEITY knows */
18919 + tr->blkcore_priv->part_table[new->devnum << tr->part_bits].nr_sects = new->size;
18921 + if (tr->part_bits) {
18922 + grok_partitions(&tr->blkcore_priv->gd, new->devnum,
18923 + 1 << tr->part_bits, new->size);
18925 +#ifdef CONFIG_DEVFS_FS
18926 + if (!tr->part_bits) {
18929 + name[0] = '0' + new->devnum;
18932 + new->blkcore_priv =
18933 + devfs_register(tr->blkcore_priv->devfs_dir_handle,
18934 + name, DEVFS_FL_DEFAULT, tr->major,
18935 + new->devnum, S_IFBLK|S_IRUGO|S_IWUGO,
18936 + &mtd_blktrans_ops, NULL);
18942 +int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
18944 + struct mtd_blktrans_ops *tr = old->tr;
18947 + if (!down_trylock(&mtd_table_mutex)) {
18948 + up(&mtd_table_mutex);
18952 +#ifdef CONFIG_DEVFS_FS
18953 + if (!tr->part_bits) {
18954 + devfs_unregister(old->blkcore_priv);
18955 + old->blkcore_priv = NULL;
18957 + devfs_register_partitions(&tr->blkcore_priv->gd,
18958 + old->devnum << tr->part_bits, 1);
18961 + spin_lock(&tr->blkcore_priv->devs_lock);
18962 + list_del(&old->list);
18963 + spin_unlock(&tr->blkcore_priv->devs_lock);
18965 + for (i = (old->devnum << tr->part_bits);
18966 + i < ((old->devnum+1) << tr->part_bits); i++) {
18967 + tr->blkcore_priv->sizes[i] = 0;
18968 + tr->blkcore_priv->part_table[i].nr_sects = 0;
18969 + tr->blkcore_priv->part_table[i].start_sect = 0;
18975 +void blktrans_notify_remove(struct mtd_info *mtd)
18977 + struct list_head *this, *this2, *next;
18979 + list_for_each(this, &blktrans_majors) {
18980 + struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
18982 + list_for_each_safe(this2, next, &tr->devs) {
18983 + struct mtd_blktrans_dev *dev = list_entry(this2, struct mtd_blktrans_dev, list);
18985 + if (dev->mtd == mtd)
18986 + tr->remove_dev(dev);
18991 +void blktrans_notify_add(struct mtd_info *mtd)
18993 + struct list_head *this;
18995 + if (mtd->type == MTD_ABSENT)
18998 + list_for_each(this, &blktrans_majors) {
18999 + struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
19001 + tr->add_mtd(tr, mtd);
19006 +static struct mtd_notifier blktrans_notifier = {
19007 + .add = blktrans_notify_add,
19008 + .remove = blktrans_notify_remove,
19011 +int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
19015 + /* Register the notifier if/when the first device type is
19016 + registered, to prevent the link/init ordering from fucking
19018 + if (!blktrans_notifier.list.next)
19019 + register_mtd_user(&blktrans_notifier);
19021 + tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);
19022 + if (!tr->blkcore_priv)
19025 + memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv));
19027 + down(&mtd_table_mutex);
19029 + ret = devfs_register_blkdev(tr->major, tr->name, &mtd_blktrans_ops);
19031 + printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",
19032 + tr->name, tr->major, ret);
19033 + kfree(tr->blkcore_priv);
19034 + up(&mtd_table_mutex);
19038 + blk_init_queue(BLK_DEFAULT_QUEUE(tr->major), &mtd_blktrans_request);
19039 + (BLK_DEFAULT_QUEUE(tr->major))->queuedata = tr;
19041 + init_completion(&tr->blkcore_priv->thread_dead);
19042 + init_waitqueue_head(&tr->blkcore_priv->thread_wq);
19044 + ret = kernel_thread(mtd_blktrans_thread, tr,
19045 + CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
19047 + blk_cleanup_queue(BLK_DEFAULT_QUEUE(tr->major));
19048 + devfs_unregister_blkdev(tr->major, tr->name);
19049 + kfree(tr->blkcore_priv);
19050 + up(&mtd_table_mutex);
19054 + tr->blkcore_priv->devfs_dir_handle =
19055 + devfs_mk_dir(NULL, tr->name, NULL);
19057 + blksize_size[tr->major] = tr->blkcore_priv->blksizes;
19058 + blk_size[tr->major] = tr->blkcore_priv->sizes;
19060 + tr->blkcore_priv->gd.major = tr->major;
19061 + tr->blkcore_priv->gd.major_name = tr->name;
19062 + tr->blkcore_priv->gd.minor_shift = tr->part_bits;
19063 + tr->blkcore_priv->gd.max_p = (1<<tr->part_bits) - 1;
19064 + tr->blkcore_priv->gd.part = tr->blkcore_priv->part_table;
19065 + tr->blkcore_priv->gd.sizes = tr->blkcore_priv->sizes;
19066 + tr->blkcore_priv->gd.nr_real = 256 >> tr->part_bits;
19068 + spin_lock_init(&tr->blkcore_priv->devs_lock);
19070 + add_gendisk(&tr->blkcore_priv->gd);
19072 + INIT_LIST_HEAD(&tr->devs);
19073 + list_add(&tr->list, &blktrans_majors);
19075 + for (i=0; i<MAX_MTD_DEVICES; i++) {
19076 + if (mtd_table[i] && mtd_table[i]->type != MTD_ABSENT)
19077 + tr->add_mtd(tr, mtd_table[i]);
19079 + up(&mtd_table_mutex);
19084 +int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
19086 + struct list_head *this, *next;
19088 + down(&mtd_table_mutex);
19090 + /* Clean up the kernel thread */
19091 + tr->blkcore_priv->exiting = 1;
19092 + wake_up(&tr->blkcore_priv->thread_wq);
19093 + wait_for_completion(&tr->blkcore_priv->thread_dead);
19095 + /* Remove it from the list of active majors */
19096 + list_del(&tr->list);
19098 + /* Remove each of its devices */
19099 + list_for_each_safe(this, next, &tr->devs) {
19100 + struct mtd_blktrans_dev *dev = list_entry(this, struct mtd_blktrans_dev, list);
19101 + tr->remove_dev(dev);
19104 + blksize_size[tr->major] = NULL;
19105 + blk_size[tr->major] = NULL;
19107 + del_gendisk(&tr->blkcore_priv->gd);
19109 + blk_cleanup_queue(BLK_DEFAULT_QUEUE(tr->major));
19110 + devfs_unregister_blkdev(tr->major, tr->name);
19112 + devfs_unregister(tr->blkcore_priv->devfs_dir_handle);
19114 + up(&mtd_table_mutex);
19116 + kfree(tr->blkcore_priv);
19118 + if (!list_empty(&tr->devs))
19123 +static void __exit mtd_blktrans_exit(void)
19125 + /* No race here -- if someone's currently in register_mtd_blktrans
19126 + we're screwed anyway. */
19127 + if (blktrans_notifier.list.next)
19128 + unregister_mtd_user(&blktrans_notifier);
19131 +module_exit(mtd_blktrans_exit);
19133 +EXPORT_SYMBOL_GPL(register_mtd_blktrans);
19134 +EXPORT_SYMBOL_GPL(deregister_mtd_blktrans);
19135 +EXPORT_SYMBOL_GPL(add_mtd_blktrans_dev);
19136 +EXPORT_SYMBOL_GPL(del_mtd_blktrans_dev);
19138 +MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
19139 +MODULE_LICENSE("GPL");
19140 +MODULE_DESCRIPTION("Common interface to block layer for MTD 'translation layers'");
19141 Index: linux-2.6.5/drivers/mtd/mtd_blkdevs.c
19142 ===================================================================
19143 --- linux-2.6.5.orig/drivers/mtd/mtd_blkdevs.c 2004-04-03 22:36:14.000000000 -0500
19144 +++ linux-2.6.5/drivers/mtd/mtd_blkdevs.c 2005-02-01 17:11:17.000000000 -0500
19147 - * $Id: mtd_blkdevs.c,v 1.16 2003/06/23 13:34:43 dwmw2 Exp $
19148 + * $Id: mtd_blkdevs.c,v 1.23 2004/08/19 01:54:36 tpoynor Exp $
19150 * (C) 2003 David Woodhouse <dwmw2@infradead.org>
19152 @@ -220,7 +220,7 @@
19155 g.start = get_start_sect(inode->i_bdev);
19156 - if (copy_to_user((void *)arg, &g, sizeof(g)))
19157 + if (copy_to_user((void __user *)arg, &g, sizeof(g)))
19161 @@ -295,7 +295,10 @@
19162 snprintf(gd->devfs_name, sizeof(gd->devfs_name),
19163 "%s/%c", tr->name, (tr->part_bits?'a':'0') + new->devnum);
19165 - set_capacity(gd, new->size);
19166 + /* 2.5 has capacity in units of 512 bytes while still
19167 + having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */
19168 + set_capacity(gd, (new->size * new->blksize) >> 9);
19170 gd->private_data = new;
19171 new->blkcore_priv = gd;
19172 gd->queue = tr->blkcore_priv->rq;
19173 Index: linux-2.6.5/drivers/mtd/mtdblock.c
19174 ===================================================================
19175 --- linux-2.6.5.orig/drivers/mtd/mtdblock.c 2004-04-03 22:36:56.000000000 -0500
19176 +++ linux-2.6.5/drivers/mtd/mtdblock.c 2005-02-01 17:11:17.000000000 -0500
19179 * Direct MTD block device access
19181 - * $Id: mtdblock.c,v 1.63 2003/06/23 12:00:08 dwmw2 Exp $
19182 + * $Id: mtdblock.c,v 1.64 2003/10/04 17:14:14 dwmw2 Exp $
19184 * (C) 2000-2003 Nicolas Pitre <nico@cam.org>
19185 * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
19186 @@ -275,7 +275,7 @@
19188 /* OK, it's not open. Create cache info for it */
19189 mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
19194 memset(mtdblk, 0, sizeof(*mtdblk));
19195 Index: linux-2.6.5/drivers/mtd/mtdchar.c
19196 ===================================================================
19197 --- linux-2.6.5.orig/drivers/mtd/mtdchar.c 2005-02-01 16:55:50.000000000 -0500
19198 +++ linux-2.6.5/drivers/mtd/mtdchar.c 2005-02-01 17:11:17.000000000 -0500
19201 - * $Id: mtdchar.c,v 1.54 2003/05/21 10:50:43 dwmw2 Exp $
19202 + * $Id: mtdchar.c,v 1.64 2004/08/09 13:59:46 dwmw2 Exp $
19204 * Character-device access to raw MTD devices.
19207 #include <linux/kernel.h>
19208 #include <linux/module.h>
19209 #include <linux/mtd/mtd.h>
19210 +#include <linux/mtd/compatmac.h>
19211 #include <linux/slab.h>
19212 #include <linux/init.h>
19213 #include <linux/fs.h>
19214 @@ -16,22 +17,52 @@
19216 #ifdef CONFIG_DEVFS_FS
19217 #include <linux/devfs_fs_kernel.h>
19218 -static void mtd_notify_add(struct mtd_info* mtd);
19219 -static void mtd_notify_remove(struct mtd_info* mtd);
19221 +static void mtd_notify_add(struct mtd_info* mtd)
19226 + devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
19227 + S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index);
19229 + devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
19230 + S_IFCHR | S_IRUGO, "mtd/%dro", mtd->index);
19233 +static void mtd_notify_remove(struct mtd_info* mtd)
19237 + devfs_remove("mtd/%d", mtd->index);
19238 + devfs_remove("mtd/%dro", mtd->index);
19241 static struct mtd_notifier notifier = {
19242 .add = mtd_notify_add,
19243 .remove = mtd_notify_remove,
19246 +static inline void mtdchar_devfs_init(void)
19248 + devfs_mk_dir("mtd");
19249 + register_mtd_user(¬ifier);
19252 +static inline void mtdchar_devfs_exit(void)
19254 + unregister_mtd_user(¬ifier);
19255 + devfs_remove("mtd");
19257 +#else /* !DEVFS */
19258 +#define mtdchar_devfs_init() do { } while(0)
19259 +#define mtdchar_devfs_exit() do { } while(0)
19262 static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
19264 struct mtd_info *mtd=(struct mtd_info *)file->private_data;
19267 - down(&mtd->mutex);
19271 @@ -46,16 +77,14 @@
19272 file->f_pos =mtd->size + offset;
19279 - /* XXX Should return -EINVAL surely ?? */
19280 if (file->f_pos < 0)
19282 else if (file->f_pos >= mtd->size)
19283 file->f_pos = mtd->size - 1;
19286 return file->f_pos;
19289 @@ -120,7 +149,7 @@
19291 #define MAX_KMALLOC_SIZE 0x20000
19293 -static ssize_t mtd_read(struct file *file, char *buf, size_t count,loff_t *ppos)
19294 +static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)
19296 struct mtd_info *mtd = (struct mtd_info *)file->private_data;
19298 @@ -131,16 +160,11 @@
19300 DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
19302 - down(&mtd->mutex);
19304 - if (count > mtd->size - *ppos)
19305 + if (*ppos + count > mtd->size)
19306 count = mtd->size - *ppos;
19314 /* FIXME: Use kiovec in 2.5 to lock down the user's buffers
19315 and pass them directly to the MTD functions */
19316 @@ -152,18 +176,13 @@
19318 kbuf=kmalloc(len,GFP_KERNEL);
19322 - /* API error - should return I/O done so far if > 0 */
19326 ret = MTD_READ(mtd, *ppos, len, &retlen, kbuf);
19329 if (copy_to_user(buf, kbuf, retlen)) {
19332 - /* API error - should return I/O done so far if > 0 */
19336 @@ -174,17 +193,16 @@
19348 return total_retlen;
19351 -static ssize_t mtd_write(struct file *file, const char *buf, size_t count,loff_t *ppos)
19352 +static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos)
19354 struct mtd_info *mtd = (struct mtd_info *)file->private_data;
19356 @@ -194,22 +212,15 @@
19359 DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
19361 - down(&mtd->mutex);
19362 - if (*ppos >= mtd->size)
19366 + if (*ppos == mtd->size)
19370 - if (count > mtd->size - *ppos)
19371 + if (*ppos + count > mtd->size)
19372 count = mtd->size - *ppos;
19381 if (count > MAX_KMALLOC_SIZE)
19382 @@ -219,14 +230,11 @@
19384 kbuf=kmalloc(len,GFP_KERNEL);
19386 -// printk("kmalloc is null\n");
19387 - /* API bug should report I/O completed */
19389 + printk("kmalloc is null\n");
19393 if (copy_from_user(kbuf, buf, len)) {
19398 @@ -239,15 +247,13 @@
19412 return total_retlen;
19415 @@ -256,7 +262,7 @@
19416 IOCTL calls for getting device parameters.
19418 ======================================================================*/
19419 -static void mtd_erase_callback (struct erase_info *instr)
19420 +static void mtdchar_erase_callback (struct erase_info *instr)
19422 wake_up((wait_queue_head_t *)instr->priv);
19424 @@ -265,6 +271,7 @@
19425 u_int cmd, u_long arg)
19427 struct mtd_info *mtd = (struct mtd_info *)file->private_data;
19428 + void __user *argp = (void __user *)arg;
19432 @@ -272,17 +279,17 @@
19434 size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
19435 if (cmd & IOC_IN) {
19436 - ret = verify_area(VERIFY_READ, (char *)arg, size);
19437 + ret = verify_area(VERIFY_READ, argp, size);
19438 if (ret) return ret;
19440 if (cmd & IOC_OUT) {
19441 - ret = verify_area(VERIFY_WRITE, (char *)arg, size);
19442 + ret = verify_area(VERIFY_WRITE, argp, size);
19443 if (ret) return ret;
19447 case MEMGETREGIONCOUNT:
19448 - if (copy_to_user((int *) arg, &(mtd->numeraseregions), sizeof(int)))
19449 + if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
19453 @@ -290,24 +297,19 @@
19455 struct region_info_user ur;
19457 - if (copy_from_user( &ur,
19458 - (struct region_info_user *)arg,
19459 - sizeof(struct region_info_user))) {
19460 + if (copy_from_user(&ur, argp, sizeof(struct region_info_user)))
19464 if (ur.regionindex >= mtd->numeraseregions)
19466 - if (copy_to_user((struct mtd_erase_region_info *) arg,
19467 - &(mtd->eraseregions[ur.regionindex]),
19468 + if (copy_to_user(argp, &(mtd->eraseregions[ur.regionindex]),
19469 sizeof(struct mtd_erase_region_info)))
19475 - if (copy_to_user((struct mtd_info *)arg, mtd,
19476 - sizeof(struct mtd_info_user)))
19477 + if (copy_to_user(argp, mtd, sizeof(struct mtd_info_user)))
19481 @@ -328,13 +330,13 @@
19482 init_waitqueue_head(&waitq);
19484 memset (erase,0,sizeof(struct erase_info));
19485 - if (copy_from_user(&erase->addr, (u_long *)arg,
19486 - 2 * sizeof(u_long))) {
19487 + if (copy_from_user(&erase->addr, argp,
19488 + sizeof(struct erase_info_user))) {
19493 - erase->callback = mtd_erase_callback;
19494 + erase->callback = mtdchar_erase_callback;
19495 erase->priv = (unsigned long)&waitq;
19498 @@ -372,7 +374,7 @@
19499 if(!(file->f_mode & 2))
19502 - if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)))
19503 + if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
19506 if (buf.length > 0x4096)
19507 @@ -381,7 +383,7 @@
19508 if (!mtd->write_oob)
19511 - ret = verify_area(VERIFY_READ, (char *)buf.ptr, buf.length);
19512 + ret = verify_area(VERIFY_READ, buf.ptr, buf.length);
19516 @@ -397,7 +399,7 @@
19518 ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf);
19520 - if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t)))
19521 + if (copy_to_user(argp + sizeof(uint32_t), &retlen, sizeof(uint32_t)))
19525 @@ -411,7 +413,7 @@
19529 - if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)))
19530 + if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
19533 if (buf.length > 0x4096)
19534 @@ -420,7 +422,7 @@
19535 if (!mtd->read_oob)
19538 - ret = verify_area(VERIFY_WRITE, (char *)buf.ptr, buf.length);
19539 + ret = verify_area(VERIFY_WRITE, buf.ptr, buf.length);
19543 @@ -431,7 +433,7 @@
19545 ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf);
19547 - if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t)))
19548 + if (put_user(retlen, (uint32_t __user *)argp))
19550 else if (retlen && copy_to_user(buf.ptr, databuf, retlen))
19552 @@ -442,41 +444,73 @@
19556 - unsigned long adrs[2];
19557 + struct erase_info_user info;
19559 - if (copy_from_user(adrs ,(void *)arg, 2* sizeof(unsigned long)))
19560 + if (copy_from_user(&info, argp, sizeof(info)))
19566 - ret = mtd->lock(mtd, adrs[0], adrs[1]);
19567 + ret = mtd->lock(mtd, info.start, info.length);
19573 - unsigned long adrs[2];
19574 + struct erase_info_user info;
19576 - if (copy_from_user(adrs, (void *)arg, 2* sizeof(unsigned long)))
19577 + if (copy_from_user(&info, argp, sizeof(info)))
19583 - ret = mtd->unlock(mtd, adrs[0], adrs[1]);
19584 + ret = mtd->unlock(mtd, info.start, info.length);
19590 - if (copy_from_user(&mtd->oobinfo ,(void *)arg, sizeof(struct nand_oobinfo)))
19591 + if (copy_from_user(&mtd->oobinfo, argp, sizeof(struct nand_oobinfo)))
19596 + case MEMGETOOBSEL:
19598 + if (copy_to_user(argp, &(mtd->oobinfo), sizeof(struct nand_oobinfo)))
19603 + case MEMGETBADBLOCK:
19607 + if (copy_from_user(&offs, argp, sizeof(loff_t)))
19609 + if (!mtd->block_isbad)
19610 + ret = -EOPNOTSUPP;
19612 + return mtd->block_isbad(mtd, offs);
19616 + case MEMSETBADBLOCK:
19620 + if (copy_from_user(&offs, argp, sizeof(loff_t)))
19622 + if (!mtd->block_markbad)
19623 + ret = -EOPNOTSUPP;
19625 + return mtd->block_markbad(mtd, offs);
19630 - DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %x)\n", cmd, MEMGETINFO);
19634 @@ -493,30 +527,6 @@
19635 .release = mtd_close,
19639 -#ifdef CONFIG_DEVFS_FS
19640 -/* Notification that a new device has been added. Create the devfs entry for
19643 -static void mtd_notify_add(struct mtd_info* mtd)
19647 - devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
19648 - S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index);
19649 - devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
19650 - S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%dro", mtd->index);
19653 -static void mtd_notify_remove(struct mtd_info* mtd)
19657 - devfs_remove("mtd/%d", mtd->index);
19658 - devfs_remove("mtd/%dro", mtd->index);
19662 static int __init init_mtdchar(void)
19664 if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) {
19665 @@ -525,20 +535,13 @@
19669 -#ifdef CONFIG_DEVFS_FS
19670 - devfs_mk_dir("mtd");
19672 - register_mtd_user(¬ifier);
19674 + mtdchar_devfs_init();
19678 static void __exit cleanup_mtdchar(void)
19680 -#ifdef CONFIG_DEVFS_FS
19681 - unregister_mtd_user(¬ifier);
19682 - devfs_remove("mtd");
19684 + mtdchar_devfs_exit();
19685 unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
19688 Index: linux-2.6.5/drivers/mtd/mtdconcat.c
19689 ===================================================================
19690 --- linux-2.6.5.orig/drivers/mtd/mtdconcat.c 2004-04-03 22:37:37.000000000 -0500
19691 +++ linux-2.6.5/drivers/mtd/mtdconcat.c 2005-02-01 17:11:17.000000000 -0500
19696 - * $Id: mtdconcat.c,v 1.4 2003/03/07 17:44:59 rkaiser Exp $
19697 + * $Id: mtdconcat.c,v 1.9 2004/06/30 15:17:41 dbrown Exp $
19700 #include <linux/module.h>
19703 struct mtd_concat {
19704 struct mtd_info mtd;
19707 struct mtd_info **subdev;
19710 @@ -37,21 +37,20 @@
19711 #define SIZEOF_STRUCT_MTD_CONCAT(num_subdev) \
19712 ((sizeof(struct mtd_concat) + (num_subdev) * sizeof(struct mtd_info *)))
19716 * Given a pointer to the MTD object in the mtd_concat structure,
19717 * we can retrieve the pointer to that structure with this macro.
19719 #define CONCAT(x) ((struct mtd_concat *)(x))
19723 * MTD methods which look up the relevant subdevice, translate the
19724 * effective address and pass through to the subdevice.
19727 -static int concat_read (struct mtd_info *mtd, loff_t from, size_t len,
19728 - size_t *retlen, u_char *buf)
19730 +concat_read(struct mtd_info *mtd, loff_t from, size_t len,
19731 + size_t * retlen, u_char * buf)
19733 struct mtd_concat *concat = CONCAT(mtd);
19735 @@ -59,43 +58,43 @@
19739 - for(i = 0; i < concat->num_subdev; i++)
19741 + for (i = 0; i < concat->num_subdev; i++) {
19742 struct mtd_info *subdev = concat->subdev[i];
19743 size_t size, retsize;
19745 - if (from >= subdev->size)
19746 - { /* Not destined for this subdev */
19748 + if (from >= subdev->size) {
19749 + /* Not destined for this subdev */
19751 from -= subdev->size;
19754 + if (from + len > subdev->size)
19755 + /* First part goes into this subdev */
19756 + size = subdev->size - from;
19759 - if (from + len > subdev->size)
19760 - size = subdev->size - from; /* First part goes into this subdev */
19762 - size = len; /* Entire transaction goes into this subdev */
19764 - err = subdev->read(subdev, from, size, &retsize, buf);
19769 - *retlen += retsize;
19773 + /* Entire transaction goes into this subdev */
19780 + err = subdev->read(subdev, from, size, &retsize, buf);
19785 + *retlen += retsize;
19797 -static int concat_write (struct mtd_info *mtd, loff_t to, size_t len,
19798 - size_t *retlen, const u_char *buf)
19800 +concat_write(struct mtd_info *mtd, loff_t to, size_t len,
19801 + size_t * retlen, const u_char * buf)
19803 struct mtd_concat *concat = CONCAT(mtd);
19805 @@ -106,46 +105,44 @@
19809 - for(i = 0; i < concat->num_subdev; i++)
19811 + for (i = 0; i < concat->num_subdev; i++) {
19812 struct mtd_info *subdev = concat->subdev[i];
19813 size_t size, retsize;
19815 - if (to >= subdev->size)
19818 + if (to >= subdev->size) {
19820 to -= subdev->size;
19823 + if (to + len > subdev->size)
19824 + size = subdev->size - to;
19827 - if (to + len > subdev->size)
19828 - size = subdev->size - to;
19832 - if (!(subdev->flags & MTD_WRITEABLE))
19835 - err = subdev->write(subdev, to, size, &retsize, buf);
19840 - *retlen += retsize;
19850 + if (!(subdev->flags & MTD_WRITEABLE))
19853 + err = subdev->write(subdev, to, size, &retsize, buf);
19858 + *retlen += retsize;
19870 -static int concat_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
19871 - size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel)
19873 +concat_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
19874 + size_t * retlen, u_char * buf, u_char * eccbuf,
19875 + struct nand_oobinfo *oobsel)
19877 struct mtd_concat *concat = CONCAT(mtd);
19879 @@ -153,53 +150,56 @@
19883 - for(i = 0; i < concat->num_subdev; i++)
19885 + for (i = 0; i < concat->num_subdev; i++) {
19886 struct mtd_info *subdev = concat->subdev[i];
19887 size_t size, retsize;
19889 - if (from >= subdev->size)
19890 - { /* Not destined for this subdev */
19893 + if (from >= subdev->size) {
19894 + /* Not destined for this subdev */
19896 from -= subdev->size;
19900 + if (from + len > subdev->size)
19901 + /* First part goes into this subdev */
19902 + size = subdev->size - from;
19905 - if (from + len > subdev->size)
19906 - size = subdev->size - from; /* First part goes into this subdev */
19908 - size = len; /* Entire transaction goes into this subdev */
19910 - if (subdev->read_ecc)
19911 - err = subdev->read_ecc(subdev, from, size, &retsize, buf, eccbuf, oobsel);
19918 - *retlen += retsize;
19922 + /* Entire transaction goes into this subdev */
19925 + if (subdev->read_ecc)
19926 + err = subdev->read_ecc(subdev, from, size,
19927 + &retsize, buf, eccbuf, oobsel);
19933 - eccbuf += subdev->oobsize;
19934 - /* in nand.c at least, eccbufs are tagged with 2 (int)eccstatus',
19935 - we must account for these */
19936 - eccbuf += 2 * (sizeof(int));
19943 + *retlen += retsize;
19951 + eccbuf += subdev->oobsize;
19952 + /* in nand.c at least, eccbufs are
19953 + tagged with 2 (int)eccstatus'; we
19954 + must account for these */
19955 + eccbuf += 2 * (sizeof (int));
19962 -static int concat_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
19963 - size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel)
19965 +concat_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
19966 + size_t * retlen, const u_char * buf, u_char * eccbuf,
19967 + struct nand_oobinfo *oobsel)
19969 struct mtd_concat *concat = CONCAT(mtd);
19971 @@ -210,50 +210,48 @@
19975 - for(i = 0; i < concat->num_subdev; i++)
19977 + for (i = 0; i < concat->num_subdev; i++) {
19978 struct mtd_info *subdev = concat->subdev[i];
19979 size_t size, retsize;
19981 - if (to >= subdev->size)
19985 + if (to >= subdev->size) {
19987 to -= subdev->size;
19990 + if (to + len > subdev->size)
19991 + size = subdev->size - to;
19994 - if (to + len > subdev->size)
19995 - size = subdev->size - to;
19999 - if (!(subdev->flags & MTD_WRITEABLE))
20001 - else if (subdev->write_ecc)
20002 - err = subdev->write_ecc(subdev, to, size, &retsize, buf, eccbuf, oobsel);
20009 - *retlen += retsize;
20015 + if (!(subdev->flags & MTD_WRITEABLE))
20017 + else if (subdev->write_ecc)
20018 + err = subdev->write_ecc(subdev, to, size,
20019 + &retsize, buf, eccbuf, oobsel);
20024 - eccbuf += subdev->oobsize;
20031 + *retlen += retsize;
20039 + eccbuf += subdev->oobsize;
20045 -static int concat_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
20046 - size_t *retlen, u_char *buf)
20048 +concat_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
20049 + size_t * retlen, u_char * buf)
20051 struct mtd_concat *concat = CONCAT(mtd);
20053 @@ -261,46 +259,47 @@
20057 - for(i = 0; i < concat->num_subdev; i++)
20059 + for (i = 0; i < concat->num_subdev; i++) {
20060 struct mtd_info *subdev = concat->subdev[i];
20061 size_t size, retsize;
20063 - if (from >= subdev->size)
20064 - { /* Not destined for this subdev */
20067 + if (from >= subdev->size) {
20068 + /* Not destined for this subdev */
20070 from -= subdev->size;
20073 + if (from + len > subdev->size)
20074 + /* First part goes into this subdev */
20075 + size = subdev->size - from;
20077 + /* Entire transaction goes into this subdev */
20080 + if (subdev->read_oob)
20081 + err = subdev->read_oob(subdev, from, size,
20085 - if (from + len > subdev->size)
20086 - size = subdev->size - from; /* First part goes into this subdev */
20088 - size = len; /* Entire transaction goes into this subdev */
20090 - if (subdev->read_oob)
20091 - err = subdev->read_oob(subdev, from, size, &retsize, buf);
20098 - *retlen += retsize;
20111 + *retlen += retsize;
20123 -static int concat_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
20124 - size_t *retlen, const u_char *buf)
20126 +concat_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
20127 + size_t * retlen, const u_char * buf)
20129 struct mtd_concat *concat = CONCAT(mtd);
20131 @@ -311,50 +310,46 @@
20135 - for(i = 0; i < concat->num_subdev; i++)
20137 + for (i = 0; i < concat->num_subdev; i++) {
20138 struct mtd_info *subdev = concat->subdev[i];
20139 size_t size, retsize;
20141 - if (to >= subdev->size)
20145 + if (to >= subdev->size) {
20147 to -= subdev->size;
20150 + if (to + len > subdev->size)
20151 + size = subdev->size - to;
20154 - if (to + len > subdev->size)
20155 - size = subdev->size - to;
20159 - if (!(subdev->flags & MTD_WRITEABLE))
20161 - else if (subdev->write_oob)
20162 - err = subdev->write_oob(subdev, to, size, &retsize, buf);
20169 - *retlen += retsize;
20175 + if (!(subdev->flags & MTD_WRITEABLE))
20177 + else if (subdev->write_oob)
20178 + err = subdev->write_oob(subdev, to, size, &retsize,
20189 + *retlen += retsize;
20202 -static void concat_erase_callback (struct erase_info *instr)
20203 +static void concat_erase_callback(struct erase_info *instr)
20205 - wake_up((wait_queue_head_t *)instr->priv);
20206 + wake_up((wait_queue_head_t *) instr->priv);
20209 static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
20210 @@ -370,18 +365,18 @@
20213 erase->callback = concat_erase_callback;
20214 - erase->priv = (unsigned long)&waitq;
20216 + erase->priv = (unsigned long) &waitq;
20219 * FIXME: Allow INTERRUPTIBLE. Which means
20220 * not having the wait_queue head on the stack.
20222 err = mtd->erase(mtd, erase);
20226 set_current_state(TASK_UNINTERRUPTIBLE);
20227 add_wait_queue(&waitq, &wait);
20228 - if (erase->state != MTD_ERASE_DONE && erase->state != MTD_ERASE_FAILED)
20229 + if (erase->state != MTD_ERASE_DONE
20230 + && erase->state != MTD_ERASE_FAILED)
20232 remove_wait_queue(&waitq, &wait);
20233 set_current_state(TASK_RUNNING);
20234 @@ -391,21 +386,21 @@
20238 -static int concat_erase (struct mtd_info *mtd, struct erase_info *instr)
20239 +static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
20241 struct mtd_concat *concat = CONCAT(mtd);
20242 struct mtd_info *subdev;
20244 - u_int32_t length;
20245 + u_int32_t length, offset = 0;
20246 struct erase_info *erase;
20248 if (!(mtd->flags & MTD_WRITEABLE))
20251 - if(instr->addr > concat->mtd.size)
20252 + if (instr->addr > concat->mtd.size)
20255 - if(instr->len + instr->addr > concat->mtd.size)
20256 + if (instr->len + instr->addr > concat->mtd.size)
20260 @@ -414,23 +409,22 @@
20261 * region info rather than looking at each particular sub-device
20264 - if (!concat->mtd.numeraseregions)
20265 - { /* the easy case: device has uniform erase block size */
20266 - if(instr->addr & (concat->mtd.erasesize - 1))
20267 + if (!concat->mtd.numeraseregions) {
20268 + /* the easy case: device has uniform erase block size */
20269 + if (instr->addr & (concat->mtd.erasesize - 1))
20271 - if(instr->len & (concat->mtd.erasesize - 1))
20272 + if (instr->len & (concat->mtd.erasesize - 1))
20276 - { /* device has variable erase size */
20277 - struct mtd_erase_region_info *erase_regions = concat->mtd.eraseregions;
20279 + /* device has variable erase size */
20280 + struct mtd_erase_region_info *erase_regions =
20281 + concat->mtd.eraseregions;
20284 * Find the erase region where the to-be-erased area begins:
20286 - for(i = 0; i < concat->mtd.numeraseregions &&
20287 - instr->addr >= erase_regions[i].offset; i++)
20289 + for (i = 0; i < concat->mtd.numeraseregions &&
20290 + instr->addr >= erase_regions[i].offset; i++) ;
20294 @@ -438,25 +432,28 @@
20295 * to-be-erased area begins. Verify that the starting
20296 * offset is aligned to this region's erase size:
20298 - if (instr->addr & (erase_regions[i].erasesize-1))
20299 + if (instr->addr & (erase_regions[i].erasesize - 1))
20303 * now find the erase region where the to-be-erased area ends:
20305 - for(; i < concat->mtd.numeraseregions &&
20306 - (instr->addr + instr->len) >= erase_regions[i].offset ; ++i)
20308 + for (; i < concat->mtd.numeraseregions &&
20309 + (instr->addr + instr->len) >= erase_regions[i].offset;
20313 * check if the ending offset is aligned to this region's erase size
20315 - if ((instr->addr + instr->len) & (erase_regions[i].erasesize-1))
20316 + if ((instr->addr + instr->len) & (erase_regions[i].erasesize -
20321 + instr->fail_addr = 0xffffffff;
20323 /* make a local copy of instr to avoid modifying the caller's struct */
20324 - erase = kmalloc(sizeof(struct erase_info),GFP_KERNEL);
20325 + erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL);
20329 @@ -468,39 +465,44 @@
20330 * find the subdevice where the to-be-erased area begins, adjust
20331 * starting offset to be relative to the subdevice start
20333 - for(i = 0; i < concat->num_subdev; i++)
20335 + for (i = 0; i < concat->num_subdev; i++) {
20336 subdev = concat->subdev[i];
20337 - if(subdev->size <= erase->addr)
20338 + if (subdev->size <= erase->addr) {
20339 erase->addr -= subdev->size;
20341 + offset += subdev->size;
20345 - if(i >= concat->num_subdev) /* must never happen since size */
20346 - BUG(); /* limit has been verified above */
20350 + /* must never happen since size limit has been verified above */
20351 + if (i >= concat->num_subdev)
20354 /* now do the erase: */
20356 - for(;length > 0; i++) /* loop for all subevices affected by this request */
20358 - subdev = concat->subdev[i]; /* get current subdevice */
20359 + for (; length > 0; i++) {
20360 + /* loop for all subdevices affected by this request */
20361 + subdev = concat->subdev[i]; /* get current subdevice */
20363 /* limit length to subdevice's size: */
20364 - if(erase->addr + length > subdev->size)
20365 + if (erase->addr + length > subdev->size)
20366 erase->len = subdev->size - erase->addr;
20368 erase->len = length;
20370 - if (!(subdev->flags & MTD_WRITEABLE))
20372 + if (!(subdev->flags & MTD_WRITEABLE)) {
20376 length -= erase->len;
20377 - if ((err = concat_dev_erase(subdev, erase)))
20379 - if(err == -EINVAL) /* sanity check: must never happen since */
20380 - BUG(); /* block alignment has been checked above */
20381 + if ((err = concat_dev_erase(subdev, erase))) {
20382 + /* sanity check: should never happen since
20383 + * block alignment has been checked above */
20384 + if (err == -EINVAL)
20386 + if (erase->fail_addr != 0xffffffff)
20387 + instr->fail_addr = erase->fail_addr + offset;
20391 @@ -512,96 +514,91 @@
20392 * current subdevice, i.e. at offset zero.
20395 + offset += subdev->size;
20397 + instr->state = erase->state;
20402 - instr->state = MTD_ERASE_DONE;
20403 if (instr->callback)
20404 instr->callback(instr);
20408 -static int concat_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
20409 +static int concat_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
20411 struct mtd_concat *concat = CONCAT(mtd);
20412 int i, err = -EINVAL;
20414 - if ((len + ofs) > mtd->size)
20415 + if ((len + ofs) > mtd->size)
20418 - for(i = 0; i < concat->num_subdev; i++)
20420 + for (i = 0; i < concat->num_subdev; i++) {
20421 struct mtd_info *subdev = concat->subdev[i];
20424 - if (ofs >= subdev->size)
20427 + if (ofs >= subdev->size) {
20429 ofs -= subdev->size;
20432 + if (ofs + len > subdev->size)
20433 + size = subdev->size - ofs;
20436 - if (ofs + len > subdev->size)
20437 - size = subdev->size - ofs;
20441 - err = subdev->lock(subdev, ofs, size);
20454 + err = subdev->lock(subdev, ofs, size);
20470 -static int concat_unlock (struct mtd_info *mtd, loff_t ofs, size_t len)
20471 +static int concat_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
20473 struct mtd_concat *concat = CONCAT(mtd);
20476 - if ((len + ofs) > mtd->size)
20477 + if ((len + ofs) > mtd->size)
20480 - for(i = 0; i < concat->num_subdev; i++)
20482 + for (i = 0; i < concat->num_subdev; i++) {
20483 struct mtd_info *subdev = concat->subdev[i];
20486 - if (ofs >= subdev->size)
20489 + if (ofs >= subdev->size) {
20491 ofs -= subdev->size;
20494 + if (ofs + len > subdev->size)
20495 + size = subdev->size - ofs;
20498 - if (ofs + len > subdev->size)
20499 - size = subdev->size - ofs;
20503 - err = subdev->unlock(subdev, ofs, size);
20516 + err = subdev->unlock(subdev, ofs, size);
20532 @@ -610,8 +607,7 @@
20533 struct mtd_concat *concat = CONCAT(mtd);
20536 - for(i = 0; i < concat->num_subdev; i++)
20538 + for (i = 0; i < concat->num_subdev; i++) {
20539 struct mtd_info *subdev = concat->subdev[i];
20540 subdev->sync(subdev);
20542 @@ -622,10 +618,9 @@
20543 struct mtd_concat *concat = CONCAT(mtd);
20546 - for(i = 0; i < concat->num_subdev; i++)
20548 + for (i = 0; i < concat->num_subdev; i++) {
20549 struct mtd_info *subdev = concat->subdev[i];
20550 - if((rc = subdev->suspend(subdev)) < 0)
20551 + if ((rc = subdev->suspend(subdev)) < 0)
20555 @@ -636,8 +631,7 @@
20556 struct mtd_concat *concat = CONCAT(mtd);
20559 - for(i = 0; i < concat->num_subdev; i++)
20561 + for (i = 0; i < concat->num_subdev; i++) {
20562 struct mtd_info *subdev = concat->subdev[i];
20563 subdev->resume(subdev);
20565 @@ -649,11 +643,10 @@
20566 * stored to *new_dev upon success. This function does _not_
20567 * register any devices: this is the caller's responsibility.
20569 -struct mtd_info *mtd_concat_create(
20570 - struct mtd_info *subdev[], /* subdevices to concatenate */
20571 - int num_devs, /* number of subdevices */
20572 - char *name) /* name for the new device */
20574 +struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to concatenate */
20575 + int num_devs, /* number of subdevices */
20577 +{ /* name for the new device */
20580 struct mtd_concat *concat;
20581 @@ -661,94 +654,103 @@
20582 int num_erase_region;
20584 printk(KERN_NOTICE "Concatenating MTD devices:\n");
20585 - for(i = 0; i < num_devs; i++)
20586 + for (i = 0; i < num_devs; i++)
20587 printk(KERN_NOTICE "(%d): \"%s\"\n", i, subdev[i]->name);
20588 printk(KERN_NOTICE "into device \"%s\"\n", name);
20590 /* allocate the device structure */
20591 size = SIZEOF_STRUCT_MTD_CONCAT(num_devs);
20592 - concat = kmalloc (size, GFP_KERNEL);
20595 - printk ("memory allocation error while creating concatenated device \"%s\"\n",
20598 + concat = kmalloc(size, GFP_KERNEL);
20601 + ("memory allocation error while creating concatenated device \"%s\"\n",
20605 memset(concat, 0, size);
20606 - concat->subdev = (struct mtd_info **)(concat + 1);
20607 + concat->subdev = (struct mtd_info **) (concat + 1);
20610 * Set up the new "super" device's MTD object structure, check for
20611 * incompatibilites between the subdevices.
20613 - concat->mtd.type = subdev[0]->type;
20614 - concat->mtd.flags = subdev[0]->flags;
20615 - concat->mtd.size = subdev[0]->size;
20616 + concat->mtd.type = subdev[0]->type;
20617 + concat->mtd.flags = subdev[0]->flags;
20618 + concat->mtd.size = subdev[0]->size;
20619 concat->mtd.erasesize = subdev[0]->erasesize;
20620 - concat->mtd.oobblock = subdev[0]->oobblock;
20621 - concat->mtd.oobsize = subdev[0]->oobsize;
20622 - concat->mtd.ecctype = subdev[0]->ecctype;
20623 - concat->mtd.eccsize = subdev[0]->eccsize;
20625 - concat->subdev[0] = subdev[0];
20627 - for(i = 1; i < num_devs; i++)
20629 - if(concat->mtd.type != subdev[i]->type)
20631 + concat->mtd.oobblock = subdev[0]->oobblock;
20632 + concat->mtd.oobsize = subdev[0]->oobsize;
20633 + concat->mtd.ecctype = subdev[0]->ecctype;
20634 + concat->mtd.eccsize = subdev[0]->eccsize;
20635 + if (subdev[0]->read_ecc)
20636 + concat->mtd.read_ecc = concat_read_ecc;
20637 + if (subdev[0]->write_ecc)
20638 + concat->mtd.write_ecc = concat_write_ecc;
20639 + if (subdev[0]->read_oob)
20640 + concat->mtd.read_oob = concat_read_oob;
20641 + if (subdev[0]->write_oob)
20642 + concat->mtd.write_oob = concat_write_oob;
20644 + concat->subdev[0] = subdev[0];
20646 + for (i = 1; i < num_devs; i++) {
20647 + if (concat->mtd.type != subdev[i]->type) {
20649 - printk ("Incompatible device type on \"%s\"\n", subdev[i]->name);
20650 + printk("Incompatible device type on \"%s\"\n",
20651 + subdev[i]->name);
20654 - if(concat->mtd.flags != subdev[i]->flags)
20656 - * Expect all flags except MTD_WRITEABLE to be equal on
20657 - * all subdevices.
20658 + if (concat->mtd.flags != subdev[i]->flags) {
20660 + * Expect all flags except MTD_WRITEABLE to be
20661 + * equal on all subdevices.
20663 - if((concat->mtd.flags ^ subdev[i]->flags) & ~MTD_WRITEABLE)
20665 + if ((concat->mtd.flags ^ subdev[i]->
20666 + flags) & ~MTD_WRITEABLE) {
20668 - printk ("Incompatible device flags on \"%s\"\n", subdev[i]->name);
20669 + printk("Incompatible device flags on \"%s\"\n",
20670 + subdev[i]->name);
20673 - else /* if writeable attribute differs, make super device writeable */
20674 - concat->mtd.flags |= subdev[i]->flags & MTD_WRITEABLE;
20676 + /* if writeable attribute differs,
20677 + make super device writeable */
20678 + concat->mtd.flags |=
20679 + subdev[i]->flags & MTD_WRITEABLE;
20681 concat->mtd.size += subdev[i]->size;
20682 - if(concat->mtd.oobblock != subdev[i]->oobblock ||
20683 - concat->mtd.oobsize != subdev[i]->oobsize ||
20684 - concat->mtd.ecctype != subdev[i]->ecctype ||
20685 - concat->mtd.eccsize != subdev[i]->eccsize)
20687 + if (concat->mtd.oobblock != subdev[i]->oobblock ||
20688 + concat->mtd.oobsize != subdev[i]->oobsize ||
20689 + concat->mtd.ecctype != subdev[i]->ecctype ||
20690 + concat->mtd.eccsize != subdev[i]->eccsize ||
20691 + !concat->mtd.read_ecc != !subdev[i]->read_ecc ||
20692 + !concat->mtd.write_ecc != !subdev[i]->write_ecc ||
20693 + !concat->mtd.read_oob != !subdev[i]->read_oob ||
20694 + !concat->mtd.write_oob != !subdev[i]->write_oob) {
20696 - printk ("Incompatible OOB or ECC data on \"%s\"\n", subdev[i]->name);
20697 + printk("Incompatible OOB or ECC data on \"%s\"\n",
20698 + subdev[i]->name);
20701 concat->subdev[i] = subdev[i];
20706 - concat->num_subdev = num_devs;
20707 - concat->mtd.name = name;
20708 + concat->num_subdev = num_devs;
20709 + concat->mtd.name = name;
20712 * NOTE: for now, we do not provide any readv()/writev() methods
20713 * because they are messy to implement and they are not
20714 * used to a great extent anyway.
20716 - concat->mtd.erase = concat_erase;
20717 - concat->mtd.read = concat_read;
20718 - concat->mtd.write = concat_write;
20719 - concat->mtd.read_ecc = concat_read_ecc;
20720 - concat->mtd.write_ecc = concat_write_ecc;
20721 - concat->mtd.read_oob = concat_read_oob;
20722 - concat->mtd.write_oob = concat_write_oob;
20723 - concat->mtd.sync = concat_sync;
20724 - concat->mtd.lock = concat_lock;
20725 - concat->mtd.unlock = concat_unlock;
20726 - concat->mtd.suspend = concat_suspend;
20727 - concat->mtd.resume = concat_resume;
20729 + concat->mtd.erase = concat_erase;
20730 + concat->mtd.read = concat_read;
20731 + concat->mtd.write = concat_write;
20732 + concat->mtd.sync = concat_sync;
20733 + concat->mtd.lock = concat_lock;
20734 + concat->mtd.unlock = concat_unlock;
20735 + concat->mtd.suspend = concat_suspend;
20736 + concat->mtd.resume = concat_resume;
20739 * Combine the erase block size info of the subdevices:
20740 @@ -758,44 +760,44 @@
20742 max_erasesize = curr_erasesize = subdev[0]->erasesize;
20743 num_erase_region = 1;
20744 - for(i = 0; i < num_devs; i++)
20746 - if(subdev[i]->numeraseregions == 0)
20747 - { /* current subdevice has uniform erase size */
20748 - if(subdev[i]->erasesize != curr_erasesize)
20749 - { /* if it differs from the last subdevice's erase size, count it */
20750 + for (i = 0; i < num_devs; i++) {
20751 + if (subdev[i]->numeraseregions == 0) {
20752 + /* current subdevice has uniform erase size */
20753 + if (subdev[i]->erasesize != curr_erasesize) {
20754 + /* if it differs from the last subdevice's erase size, count it */
20755 ++num_erase_region;
20756 curr_erasesize = subdev[i]->erasesize;
20757 - if(curr_erasesize > max_erasesize)
20758 + if (curr_erasesize > max_erasesize)
20759 max_erasesize = curr_erasesize;
20763 - { /* current subdevice has variable erase size */
20765 + /* current subdevice has variable erase size */
20767 - for(j = 0; j < subdev[i]->numeraseregions; j++)
20768 - { /* walk the list of erase regions, count any changes */
20769 - if(subdev[i]->eraseregions[j].erasesize != curr_erasesize)
20771 + for (j = 0; j < subdev[i]->numeraseregions; j++) {
20773 + /* walk the list of erase regions, count any changes */
20774 + if (subdev[i]->eraseregions[j].erasesize !=
20775 + curr_erasesize) {
20776 ++num_erase_region;
20777 - curr_erasesize = subdev[i]->eraseregions[j].erasesize;
20778 - if(curr_erasesize > max_erasesize)
20780 + subdev[i]->eraseregions[j].
20782 + if (curr_erasesize > max_erasesize)
20783 max_erasesize = curr_erasesize;
20789 - if(num_erase_region == 1)
20791 + if (num_erase_region == 1) {
20793 * All subdevices have the same uniform erase size.
20796 concat->mtd.erasesize = curr_erasesize;
20797 concat->mtd.numeraseregions = 0;
20803 * erase block size varies across the subdevices: allocate
20804 * space to store the data describing the variable erase regions
20806 @@ -804,13 +806,14 @@
20808 concat->mtd.erasesize = max_erasesize;
20809 concat->mtd.numeraseregions = num_erase_region;
20810 - concat->mtd.eraseregions = erase_region_p = kmalloc (
20811 - num_erase_region * sizeof(struct mtd_erase_region_info), GFP_KERNEL);
20812 - if(!erase_region_p)
20814 + concat->mtd.eraseregions = erase_region_p =
20815 + kmalloc(num_erase_region *
20816 + sizeof (struct mtd_erase_region_info), GFP_KERNEL);
20817 + if (!erase_region_p) {
20819 - printk ("memory allocation error while creating erase region list"
20820 - " for device \"%s\"\n", name);
20822 + ("memory allocation error while creating erase region list"
20823 + " for device \"%s\"\n", name);
20827 @@ -820,46 +823,53 @@
20829 curr_erasesize = subdev[0]->erasesize;
20830 begin = position = 0;
20831 - for(i = 0; i < num_devs; i++)
20833 - if(subdev[i]->numeraseregions == 0)
20834 - { /* current subdevice has uniform erase size */
20835 - if(subdev[i]->erasesize != curr_erasesize)
20837 + for (i = 0; i < num_devs; i++) {
20838 + if (subdev[i]->numeraseregions == 0) {
20839 + /* current subdevice has uniform erase size */
20840 + if (subdev[i]->erasesize != curr_erasesize) {
20842 * fill in an mtd_erase_region_info structure for the area
20843 * we have walked so far:
20845 - erase_region_p->offset = begin;
20846 - erase_region_p->erasesize = curr_erasesize;
20847 - erase_region_p->numblocks = (position - begin) / curr_erasesize;
20848 + erase_region_p->offset = begin;
20849 + erase_region_p->erasesize =
20851 + erase_region_p->numblocks =
20852 + (position - begin) / curr_erasesize;
20855 curr_erasesize = subdev[i]->erasesize;
20858 position += subdev[i]->size;
20861 - { /* current subdevice has variable erase size */
20863 + /* current subdevice has variable erase size */
20865 - for(j = 0; j < subdev[i]->numeraseregions; j++)
20866 - { /* walk the list of erase regions, count any changes */
20867 - if(subdev[i]->eraseregions[j].erasesize != curr_erasesize)
20869 - erase_region_p->offset = begin;
20870 - erase_region_p->erasesize = curr_erasesize;
20871 - erase_region_p->numblocks = (position - begin) / curr_erasesize;
20872 + for (j = 0; j < subdev[i]->numeraseregions; j++) {
20873 + /* walk the list of erase regions, count any changes */
20874 + if (subdev[i]->eraseregions[j].
20875 + erasesize != curr_erasesize) {
20876 + erase_region_p->offset = begin;
20877 + erase_region_p->erasesize =
20879 + erase_region_p->numblocks =
20881 + begin) / curr_erasesize;
20884 - curr_erasesize = subdev[i]->eraseregions[j].erasesize;
20886 + subdev[i]->eraseregions[j].
20890 - position += subdev[i]->eraseregions[j].numblocks * curr_erasesize;
20892 + subdev[i]->eraseregions[j].
20893 + numblocks * curr_erasesize;
20897 /* Now write the final entry */
20898 - erase_region_p->offset = begin;
20899 + erase_region_p->offset = begin;
20900 erase_region_p->erasesize = curr_erasesize;
20901 erase_region_p->numblocks = (position - begin) / curr_erasesize;
20903 @@ -874,16 +884,14 @@
20904 void mtd_concat_destroy(struct mtd_info *mtd)
20906 struct mtd_concat *concat = CONCAT(mtd);
20907 - if(concat->mtd.numeraseregions)
20908 + if (concat->mtd.numeraseregions)
20909 kfree(concat->mtd.eraseregions);
20914 EXPORT_SYMBOL(mtd_concat_create);
20915 EXPORT_SYMBOL(mtd_concat_destroy);
20918 MODULE_LICENSE("GPL");
20919 MODULE_AUTHOR("Robert Kaiser <rkaiser@sysgo.de>");
20920 MODULE_DESCRIPTION("Generic support for concatenating of MTD devices");
20921 Index: linux-2.6.5/drivers/mtd/mtdcore.c
20922 ===================================================================
20923 --- linux-2.6.5.orig/drivers/mtd/mtdcore.c 2005-02-01 16:55:50.000000000 -0500
20924 +++ linux-2.6.5/drivers/mtd/mtdcore.c 2005-02-01 17:11:17.000000000 -0500
20927 - * $Id: mtdcore.c,v 1.39 2003/05/21 15:15:03 dwmw2 Exp $
20928 + * $Id: mtdcore.c,v 1.43 2004/07/23 15:20:46 dwmw2 Exp $
20930 * Core registration and callback routines for MTD
20931 * drivers and users.
20935 -#include <linux/version.h>
20936 #include <linux/config.h>
20937 #include <linux/module.h>
20938 #include <linux/kernel.h>
20940 mtd_table[i] = mtd;
20943 - init_MUTEX(&mtd->mutex);
20945 DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name);
20946 /* No need to get a refcount on the module containing
20947 @@ -233,7 +231,7 @@
20948 * dont implement their own
20951 -int default_mtd_writev(struct mtd_info *mtd, const struct iovec *vecs,
20952 +int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
20953 unsigned long count, loff_t to, size_t *retlen)
20956 @@ -263,7 +261,7 @@
20957 * implement their own
20960 -int default_mtd_readv(struct mtd_info *mtd, struct iovec *vecs,
20961 +int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
20962 unsigned long count, loff_t from, size_t *retlen)
20965 @@ -335,10 +333,7 @@
20966 /* Support for /proc/mtd */
20968 #ifdef CONFIG_PROC_FS
20970 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
20971 static struct proc_dir_entry *proc_mtd;
20974 static inline int mtd_proc_info (char *buf, int i)
20976 @@ -351,13 +346,8 @@
20977 this->erasesize, this->name);
20980 -static int mtd_read_proc ( char *page, char **start, off_t off,int count
20981 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
20982 - ,int *eof, void *data_unused
20987 +static int mtd_read_proc (char *page, char **start, off_t off, int count,
20988 + int *eof, void *data_unused)
20992 @@ -377,9 +367,7 @@
20996 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
21001 up(&mtd_table_mutex);
21002 @@ -389,18 +377,6 @@
21003 return ((count < begin+len-off) ? count : begin+len-off);
21006 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)
21007 -struct proc_dir_entry mtd_proc_entry = {
21008 - 0, /* low_ino: the inode -- dynamic */
21009 - 3, "mtd", /* len of name and name */
21010 - S_IFREG | S_IRUGO, /* mode */
21011 - 1, 0, 0, /* nlinks, owner, group */
21012 - 0, NULL, /* size - unused; operations -- use default */
21013 - &mtd_read_proc, /* function used to read data */
21014 - /* nothing more */
21018 #endif /* CONFIG_PROC_FS */
21020 /*====================================================================*/
21021 @@ -409,16 +385,8 @@
21022 int __init init_mtd(void)
21024 #ifdef CONFIG_PROC_FS
21025 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
21026 - if ((proc_mtd = create_proc_entry( "mtd", 0, 0 )))
21027 - proc_mtd->read_proc = mtd_read_proc;
21029 - proc_register_dynamic(&proc_root,&mtd_proc_entry);
21033 -#if LINUX_VERSION_CODE < 0x20212
21034 - init_mtd_devices();
21035 + if ((proc_mtd = create_proc_entry( "mtd", 0, NULL )))
21036 + proc_mtd->read_proc = mtd_read_proc;
21040 @@ -437,12 +405,8 @@
21043 #ifdef CONFIG_PROC_FS
21044 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
21046 - remove_proc_entry( "mtd", 0);
21048 - proc_unregister(&proc_root,mtd_proc_entry.low_ino);
21050 + remove_proc_entry( "mtd", NULL);
21054 Index: linux-2.6.5/drivers/mtd/mtdpart.c
21055 ===================================================================
21056 --- linux-2.6.5.orig/drivers/mtd/mtdpart.c 2004-04-03 22:37:38.000000000 -0500
21057 +++ linux-2.6.5/drivers/mtd/mtdpart.c 2005-02-01 17:11:17.000000000 -0500
21062 - * $Id: mtdpart.c,v 1.41 2003/06/18 14:53:02 dwmw2 Exp $
21063 + * $Id: mtdpart.c,v 1.50 2004/08/10 16:18:34 dwmw2 Exp $
21065 * 02-21-2002 Thomas Gleixner <gleixner@autronix.de>
21066 * added support for read_oob, write_oob
21067 @@ -182,7 +182,7 @@
21071 -static int part_writev (struct mtd_info *mtd, const struct iovec *vecs,
21072 +static int part_writev (struct mtd_info *mtd, const struct kvec *vecs,
21073 unsigned long count, loff_t to, size_t *retlen)
21075 struct mtd_part *part = PART(mtd);
21076 @@ -197,7 +197,7 @@
21077 NULL, &mtd->oobinfo);
21080 -static int part_readv (struct mtd_info *mtd, struct iovec *vecs,
21081 +static int part_readv (struct mtd_info *mtd, struct kvec *vecs,
21082 unsigned long count, loff_t from, size_t *retlen)
21084 struct mtd_part *part = PART(mtd);
21085 @@ -210,7 +210,7 @@
21086 NULL, &mtd->oobinfo);
21089 -static int part_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs,
21090 +static int part_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs,
21091 unsigned long count, loff_t to, size_t *retlen,
21092 u_char *eccbuf, struct nand_oobinfo *oobsel)
21094 @@ -224,7 +224,7 @@
21098 -static int part_readv_ecc (struct mtd_info *mtd, struct iovec *vecs,
21099 +static int part_readv_ecc (struct mtd_info *mtd, struct kvec *vecs,
21100 unsigned long count, loff_t from, size_t *retlen,
21101 u_char *eccbuf, struct nand_oobinfo *oobsel)
21103 @@ -239,13 +239,29 @@
21104 static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
21106 struct mtd_part *part = PART(mtd);
21108 if (!(mtd->flags & MTD_WRITEABLE))
21110 if (instr->addr >= mtd->size)
21112 instr->addr += part->offset;
21113 - return part->master->erase(part->master, instr);
21114 + ret = part->master->erase(part->master, instr);
21118 +void mtd_erase_callback(struct erase_info *instr)
21120 + if (instr->mtd->erase == part_erase) {
21121 + struct mtd_part *part = PART(instr->mtd);
21123 + if (instr->fail_addr != 0xffffffff)
21124 + instr->fail_addr -= part->offset;
21125 + instr->addr -= part->offset;
21127 + if (instr->callback)
21128 + instr->callback(instr);
21130 +EXPORT_SYMBOL_GPL(mtd_erase_callback);
21132 static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
21134 @@ -281,6 +297,26 @@
21135 part->master->resume(part->master);
21138 +static int part_block_isbad (struct mtd_info *mtd, loff_t ofs)
21140 + struct mtd_part *part = PART(mtd);
21141 + if (ofs >= mtd->size)
21143 + ofs += part->offset;
21144 + return part->master->block_isbad(part->master, ofs);
21147 +static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
21149 + struct mtd_part *part = PART(mtd);
21150 + if (!(mtd->flags & MTD_WRITEABLE))
21152 + if (ofs >= mtd->size)
21154 + ofs += part->offset;
21155 + return part->master->block_markbad(part->master, ofs);
21159 * This function unregisters and destroy all slave MTD objects which are
21160 * attached to the given master MTD object.
21161 @@ -316,7 +352,7 @@
21164 int add_mtd_partitions(struct mtd_info *master,
21165 - struct mtd_partition *parts,
21166 + const struct mtd_partition *parts,
21169 struct mtd_part *slave;
21170 @@ -391,6 +427,10 @@
21171 slave->mtd.lock = part_lock;
21172 if (master->unlock)
21173 slave->mtd.unlock = part_unlock;
21174 + if (master->block_isbad)
21175 + slave->mtd.block_isbad = part_block_isbad;
21176 + if (master->block_markbad)
21177 + slave->mtd.block_markbad = part_block_markbad;
21178 slave->mtd.erase = part_erase;
21179 slave->master = master;
21180 slave->offset = parts[i].offset;
21181 @@ -461,6 +501,9 @@
21185 + /* copy oobinfo from master */
21186 + memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo));
21189 { /* store the object pointer (caller may or may not register it */
21190 *parts[i].mtdp = &slave->mtd;
21191 Index: linux-2.6.5/drivers/mtd/nand/Kconfig
21192 ===================================================================
21193 --- linux-2.6.5.orig/drivers/mtd/nand/Kconfig 2004-04-03 22:37:41.000000000 -0500
21194 +++ linux-2.6.5/drivers/mtd/nand/Kconfig 2005-02-01 17:11:17.000000000 -0500
21196 # drivers/mtd/nand/Kconfig
21197 -# $Id: Kconfig,v 1.4 2003/05/28 10:04:23 dwmw2 Exp $
21198 +# $Id: Kconfig,v 1.19 2004/09/16 23:23:42 gleixner Exp $
21200 menu "NAND Flash Device Drivers"
21205 This enables support for accessing all type of NAND flash
21206 - devices with an 8-bit data bus interface. For further
21207 - information see www.linux-mtd.infradead.org/tech/nand.html.
21208 + devices. For further information see
21209 + <http://www.linux-mtd.infradead.org/tech/nand.html>.
21211 config MTD_NAND_VERIFY_WRITE
21212 bool "Verify NAND page writes"
21213 @@ -36,16 +36,129 @@
21214 This enables the driver for the Cirrus Logic EBD7312 evaluation
21215 board to access the onboard NAND Flash.
21217 +config MTD_NAND_H1900
21218 + tristate "iPAQ H1900 flash"
21219 + depends on ARM && MTD_NAND && ARCH_PXA && MTD_PARTITIONS
21221 + This enables the driver for the iPAQ h1900 flash.
21223 config MTD_NAND_SPIA
21224 tristate "NAND Flash device on SPIA board"
21225 depends on ARM && ARCH_P720T && MTD_NAND
21227 If you had to ask, you don't have one. Say 'N'.
21229 +config MTD_NAND_TOTO
21230 + tristate "NAND Flash device on TOTO board"
21231 + depends on ARM && ARCH_OMAP && MTD_NAND
21233 + Support for NAND flash on Texas Instruments Toto platform.
21235 config MTD_NAND_IDS
21237 default y if MTD_NAND = y || MTD_DOC2000 = y || MTD_DOC2001 = y || MTD_DOC2001PLUS = y
21238 default m if MTD_NAND = m || MTD_DOC2000 = m || MTD_DOC2001 = m || MTD_DOC2001PLUS = m
21242 +config MTD_NAND_TX4925NDFMC
21243 + tristate "SmartMedia Card on Toshiba RBTX4925 reference board"
21244 + depends on TOSHIBA_RBTX4925 && MTD_NAND && TOSHIBA_RBTX4925_MPLEX_NAND
21246 + This enables the driver for the NAND flash device found on the
21247 + Toshiba RBTX4925 reference board, which is a SmartMediaCard.
21249 +config MTD_NAND_TX4938NDFMC
21250 + tristate "NAND Flash device on Toshiba RBTX4938 reference board"
21251 + depends on TOSHIBA_RBTX4938 && MTD_NAND && TOSHIBA_RBTX4938_MPLEX_NAND
21253 + This enables the driver for the NAND flash device found on the
21254 + Toshiba RBTX4938 reference board.
21256 +config MTD_NAND_AU1550
21257 + tristate "Au1550 NAND support"
21258 + depends on SOC_AU1550 && MTD_NAND
21260 + This enables the driver for the NAND flash controller on the
21261 + AMD/Alchemy 1550 SOC.
21263 +config MTD_NAND_RTC_FROM4
21264 + tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)"
21265 + depends on MTD_NAND && SH_SOLUTION_ENGINE
21267 + This enables the driver for the Renesas Technology AG-AND
21268 + flash interface board (FROM_BOARD4)
21270 +config MTD_NAND_PPCHAMELEONEVB
21271 + tristate "NAND Flash device on PPChameleonEVB board"
21272 + depends on PPCHAMELEONEVB && MTD_NAND
21274 + This enables the NAND flash driver on the PPChameleon EVB Board.
21276 +config MTD_NAND_DISKONCHIP
21277 + tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
21278 + depends on MTD_NAND && EXPERIMENTAL
21279 + select REED_SOLOMON
21281 + This is a reimplementation of M-Systems DiskOnChip 2000,
21282 + Millennium and Millennium Plus as a standard NAND device driver,
21283 + as opposed to the earlier self-contained MTD device drivers.
21284 + This should enable, among other things, proper JFFS2 operation on
21287 +config MTD_NAND_DISKONCHIP_PROBE_ADVANCED
21288 + bool "Advanced detection options for DiskOnChip"
21289 + depends on MTD_NAND_DISKONCHIP
21291 + This option allows you to specify nonstandard address at which to
21292 + probe for a DiskOnChip, or to change the detection options. You
21293 + are unlikely to need any of this unless you are using LinuxBIOS.
21296 +config MTD_NAND_DISKONCHIP_PROBE_ADDRESS
21297 + hex "Physical address of DiskOnChip" if MTD_NAND_DISKONCHIP_PROBE_ADVANCED
21298 + depends on MTD_NAND_DISKONCHIP
21301 + By default, the probe for DiskOnChip devices will look for a
21302 + DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
21303 + This option allows you to specify a single address at which to probe
21304 + for the device, which is useful if you have other devices in that
21305 + range which get upset when they are probed.
21307 + (Note that on PowerPC, the normal probe will only check at
21310 + Normally, you should leave this set to zero, to allow the probe at
21311 + the normal addresses.
21313 +config MTD_NAND_DISKONCHIP_PROBE_HIGH
21314 + bool "Probe high addresses"
21315 + depends on MTD_NAND_DISKONCHIP_PROBE_ADVANCED
21317 + By default, the probe for DiskOnChip devices will look for a
21318 + DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
21319 + This option changes to make it probe between 0xFFFC8000 and
21320 + 0xFFFEE000. Unless you are using LinuxBIOS, this is unlikely to be
21321 + useful to you. Say 'N'.
21323 +config MTD_NAND_DISKONCHIP_BBTWRITE
21324 + bool "Allow BBT writes on DiskOnChip Millennium and 2000TSOP"
21325 + depends on MTD_NAND_DISKONCHIP
21327 + On DiskOnChip devices shipped with the INFTL filesystem (Millennium
21328 + and 2000 TSOP/Alon), Linux reserves some space at the end of the
21329 + device for the Bad Block Table (BBT). If you have existing INFTL
21330 + data on your device (created by non-Linux tools such as M-Systems'
21331 + DOS drivers), your data might overlap the area Linux wants to use for
21332 + the BBT. If this is a concern for you, leave this option disabled and
21333 + Linux will not write BBT data into this area.
21334 + The downside of leaving this option disabled is that if bad blocks
21335 + are detected by Linux, they will not be recorded in the BBT, which
21336 + could cause future problems.
21337 + Once you enable this option, new filesystems (INFTL or others, created
21338 + in Linux or other operating systems) will not use the reserved area.
21339 + The only reason not to enable this option is to prevent damage to
21340 + preexisting filesystems.
21341 + Even if you leave this disabled, you can enable BBT writes at module
21342 + load time (assuming you build diskonchip as a module) with the module
21343 + parameter "inftl_bbt_write=1".
21345 Index: linux-2.6.5/drivers/mtd/nand/Makefile
21346 ===================================================================
21347 --- linux-2.6.5.orig/drivers/mtd/nand/Makefile 2004-04-03 22:36:14.000000000 -0500
21348 +++ linux-2.6.5/drivers/mtd/nand/Makefile 2005-02-01 17:11:17.000000000 -0500
21351 # linux/drivers/nand/Makefile
21353 -# $Id: Makefile.common,v 1.2 2003/05/28 11:38:54 dwmw2 Exp $
21354 +# $Id: Makefile.common,v 1.11 2004/09/16 23:23:42 gleixner Exp $
21356 -obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o
21357 -obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
21358 -obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
21359 -obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o
21360 -obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
21361 +obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o
21362 +obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
21364 +obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
21365 +obj-$(CONFIG_MTD_NAND_TOTO) += toto.o
21366 +obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
21367 +obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o
21368 +obj-$(CONFIG_MTD_NAND_TX4925NDFMC) += tx4925ndfmc.o
21369 +obj-$(CONFIG_MTD_NAND_TX4938NDFMC) += tx4938ndfmc.o
21370 +obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
21371 +obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
21372 +obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o
21373 +obj-$(CONFIG_MTD_NAND_H1900) += h1910.o
21374 +obj-$(CONFIG_MTD_NAND_FROM4) += rtc_from4.o
21376 +nand-objs = nand_base.o nand_bbt.o
21377 Index: linux-2.6.5/drivers/mtd/nand/au1550nd.c
21378 ===================================================================
21379 --- linux-2.6.5.orig/drivers/mtd/nand/au1550nd.c 1969-12-31 19:00:00.000000000 -0500
21380 +++ linux-2.6.5/drivers/mtd/nand/au1550nd.c 2005-02-01 17:11:17.000000000 -0500
21383 + * drivers/mtd/nand/au1550nd.c
21385 + * Copyright (C) 2004 Embedded Edge, LLC
21387 + * $Id: au1550nd.c,v 1.8 2004/09/16 23:27:14 gleixner Exp $
21389 + * This program is free software; you can redistribute it and/or modify
21390 + * it under the terms of the GNU General Public License version 2 as
21391 + * published by the Free Software Foundation.
21395 +#include <linux/slab.h>
21396 +#include <linux/init.h>
21397 +#include <linux/module.h>
21398 +#include <linux/mtd/mtd.h>
21399 +#include <linux/mtd/nand.h>
21400 +#include <linux/mtd/partitions.h>
21401 +#include <asm/io.h>
21402 +#include <asm/au1000.h>
21403 +#ifdef CONFIG_MIPS_PB1550
21404 +#include <asm/pb1550.h>
21406 +#ifdef CONFIG_MIPS_DB1550
21407 +#include <asm/db1x00.h>
21412 + * MTD structure for NAND controller
21414 +static struct mtd_info *au1550_mtd = NULL;
21415 +static void __iomem *p_nand;
21416 +static int nand_width = 1; /* default x8*/
21419 + * Define partitions for flash device
21421 +const static struct mtd_partition partition_info[] = {
21422 +#ifdef CONFIG_MIPS_PB1550
21423 +#define NUM_PARTITIONS 2
21425 + .name = "Pb1550 NAND FS 0",
21427 + .size = 8*1024*1024
21430 + .name = "Pb1550 NAND FS 1",
21431 + .offset = MTDPART_OFS_APPEND,
21432 + .size = MTDPART_SIZ_FULL
21435 +#ifdef CONFIG_MIPS_DB1550
21436 +#define NUM_PARTITIONS 2
21438 + .name = "Db1550 NAND FS 0",
21440 + .size = 8*1024*1024
21443 + .name = "Db1550 NAND FS 1",
21444 + .offset = MTDPART_OFS_APPEND,
21445 + .size = MTDPART_SIZ_FULL
21452 + * au_read_byte - read one byte from the chip
21453 + * @mtd: MTD device structure
21455 + * read function for 8bit buswith
21457 +static u_char au_read_byte(struct mtd_info *mtd)
21459 + struct nand_chip *this = mtd->priv;
21460 + u_char ret = readb(this->IO_ADDR_R);
21466 + * au_write_byte - write one byte to the chip
21467 + * @mtd: MTD device structure
21468 + * @byte: pointer to data byte to write
21470 + * write function for 8it buswith
21472 +static void au_write_byte(struct mtd_info *mtd, u_char byte)
21474 + struct nand_chip *this = mtd->priv;
21475 + writeb(byte, this->IO_ADDR_W);
21480 + * au_read_byte16 - read one byte endianess aware from the chip
21481 + * @mtd: MTD device structure
21483 + * read function for 16bit buswith with
21484 + * endianess conversion
21486 +static u_char au_read_byte16(struct mtd_info *mtd)
21488 + struct nand_chip *this = mtd->priv;
21489 + u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
21495 + * au_write_byte16 - write one byte endianess aware to the chip
21496 + * @mtd: MTD device structure
21497 + * @byte: pointer to data byte to write
21499 + * write function for 16bit buswith with
21500 + * endianess conversion
21502 +static void au_write_byte16(struct mtd_info *mtd, u_char byte)
21504 + struct nand_chip *this = mtd->priv;
21505 + writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
21510 + * au_read_word - read one word from the chip
21511 + * @mtd: MTD device structure
21513 + * read function for 16bit buswith without
21514 + * endianess conversion
21516 +static u16 au_read_word(struct mtd_info *mtd)
21518 + struct nand_chip *this = mtd->priv;
21519 + u16 ret = readw(this->IO_ADDR_R);
21525 + * au_write_word - write one word to the chip
21526 + * @mtd: MTD device structure
21527 + * @word: data word to write
21529 + * write function for 16bit buswith without
21530 + * endianess conversion
21532 +static void au_write_word(struct mtd_info *mtd, u16 word)
21534 + struct nand_chip *this = mtd->priv;
21535 + writew(word, this->IO_ADDR_W);
21540 + * au_write_buf - write buffer to chip
21541 + * @mtd: MTD device structure
21542 + * @buf: data buffer
21543 + * @len: number of bytes to write
21545 + * write function for 8bit buswith
21547 +static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
21550 + struct nand_chip *this = mtd->priv;
21552 + for (i=0; i<len; i++) {
21553 + writeb(buf[i], this->IO_ADDR_W);
21559 + * au_read_buf - read chip data into buffer
21560 + * @mtd: MTD device structure
21561 + * @buf: buffer to store date
21562 + * @len: number of bytes to read
21564 + * read function for 8bit buswith
21566 +static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
21569 + struct nand_chip *this = mtd->priv;
21571 + for (i=0; i<len; i++) {
21572 + buf[i] = readb(this->IO_ADDR_R);
21578 + * au_verify_buf - Verify chip data against buffer
21579 + * @mtd: MTD device structure
21580 + * @buf: buffer containing the data to compare
21581 + * @len: number of bytes to compare
21583 + * verify function for 8bit buswith
21585 +static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
21588 + struct nand_chip *this = mtd->priv;
21590 + for (i=0; i<len; i++) {
21591 + if (buf[i] != readb(this->IO_ADDR_R))
21600 + * au_write_buf16 - write buffer to chip
21601 + * @mtd: MTD device structure
21602 + * @buf: data buffer
21603 + * @len: number of bytes to write
21605 + * write function for 16bit buswith
21607 +static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
21610 + struct nand_chip *this = mtd->priv;
21611 + u16 *p = (u16 *) buf;
21614 + for (i=0; i<len; i++) {
21615 + writew(p[i], this->IO_ADDR_W);
21622 + * au_read_buf16 - read chip data into buffer
21623 + * @mtd: MTD device structure
21624 + * @buf: buffer to store date
21625 + * @len: number of bytes to read
21627 + * read function for 16bit buswith
21629 +static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
21632 + struct nand_chip *this = mtd->priv;
21633 + u16 *p = (u16 *) buf;
21636 + for (i=0; i<len; i++) {
21637 + p[i] = readw(this->IO_ADDR_R);
21643 + * au_verify_buf16 - Verify chip data against buffer
21644 + * @mtd: MTD device structure
21645 + * @buf: buffer containing the data to compare
21646 + * @len: number of bytes to compare
21648 + * verify function for 16bit buswith
21650 +static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
21653 + struct nand_chip *this = mtd->priv;
21654 + u16 *p = (u16 *) buf;
21657 + for (i=0; i<len; i++) {
21658 + if (p[i] != readw(this->IO_ADDR_R))
21666 +static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
21668 + register struct nand_chip *this = mtd->priv;
21672 + case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break;
21673 + case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break;
21675 + case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break;
21676 + case NAND_CTL_CLRALE:
21677 + this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
21678 + /* FIXME: Nobody knows why this is neccecary,
21679 + * but it works onlythat way */
21683 + case NAND_CTL_SETNCE:
21684 + /* assert (force assert) chip enable */
21685 + au_writel(au_readl(MEM_STNDCTL) | 0x20 , MEM_STNDCTL);
21688 + case NAND_CTL_CLRNCE:
21689 + /* deassert chip enable */
21690 + au_writel(au_readl(MEM_STNDCTL) & ~0x20 , MEM_STNDCTL);
21694 + this->IO_ADDR_R = this->IO_ADDR_W;
21696 + /* Drain the writebuffer */
21700 +int au1550_device_ready(struct mtd_info *mtd)
21702 + int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;
21708 + * Main initialization routine
21710 +int __init au1550_init (void)
21712 + struct nand_chip *this;
21713 + u16 boot_swapboot = 0; /* default value */
21717 + /* Allocate memory for MTD device structure and private data */
21718 + au1550_mtd = kmalloc (sizeof(struct mtd_info) +
21719 + sizeof (struct nand_chip), GFP_KERNEL);
21720 + if (!au1550_mtd) {
21721 + printk ("Unable to allocate NAND MTD dev structure.\n");
21725 + /* Get pointer to private data */
21726 + this = (struct nand_chip *) (&au1550_mtd[1]);
21728 + /* Initialize structures */
21729 + memset((char *) au1550_mtd, 0, sizeof(struct mtd_info));
21730 + memset((char *) this, 0, sizeof(struct nand_chip));
21732 + /* Link the private data with the MTD structure */
21733 + au1550_mtd->priv = this;
21735 + /* disable interrupts */
21736 + au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL);
21738 + /* disable NAND boot */
21739 + au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL);
21741 +#ifdef CONFIG_MIPS_PB1550
21742 + /* set gpio206 high */
21743 + au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR);
21745 + boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
21746 + ((bcsr->status >> 6) & 0x1);
21747 + switch (boot_swapboot) {
21753 + /* x16 NAND Flash */
21761 + /* x8 NAND Flash */
21765 + printk("Pb1550 NAND: bad boot:swap\n");
21766 + retval = -EINVAL;
21770 + /* Configure RCE1 - should be done by YAMON */
21771 + au_writel(0x5 | (nand_width << 22), MEM_STCFG1);
21772 + au_writel(NAND_TIMING, MEM_STTIME1);
21773 + mem_time = au_readl(MEM_STTIME1);
21776 + /* setup and enable chip select */
21777 + /* we really need to decode offsets only up till 0x20 */
21778 + au_writel((1<<28) | (NAND_PHYS_ADDR>>4) |
21779 + (((NAND_PHYS_ADDR + 0x1000)-1) & (0x3fff<<18)>>18),
21784 +#ifdef CONFIG_MIPS_DB1550
21785 + /* FIXME: should be done by the bootloader
21787 + * tglx: stcfg1 was set to 0x00400005. I changed
21788 + * this as it does not work with all chips.
21789 + * someone should look into the correct timing
21790 + * values, as bit 8 does a clock / 4 prescale
21792 + au_writel(0x00400105, MEM_STCFG1);
21793 + au_writel(0x00007774, MEM_STTIME1);
21794 + au_writel(0x12003FFF, MEM_STADDR1);
21797 + p_nand = (void __iomem *)ioremap(NAND_PHYS_ADDR, 0x1000);
21799 + /* Set address of hardware control function */
21800 + this->hwcontrol = au1550_hwcontrol;
21801 + this->dev_ready = au1550_device_ready;
21802 + /* 30 us command delay time */
21803 + this->chip_delay = 30;
21804 + this->eccmode = NAND_ECC_SOFT;
21806 + this->options = NAND_NO_AUTOINCR;
21809 + this->options |= NAND_BUSWIDTH_16;
21811 + this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte;
21812 + this->write_byte = (!nand_width) ? au_write_byte16 : au_write_byte;
21813 + this->write_word = au_write_word;
21814 + this->read_word = au_read_word;
21815 + this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf;
21816 + this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf;
21817 + this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf;
21819 + /* Scan to find existence of the device */
21820 + if (nand_scan (au1550_mtd, 1)) {
21825 + /* Register the partitions */
21826 + add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS);
21831 + iounmap ((void *)p_nand);
21834 + kfree (au1550_mtd);
21838 +module_init(au1550_init);
21841 + * Clean up routine
21844 +static void __exit au1550_cleanup (void)
21846 + struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1];
21848 + /* Release resources, unregister device */
21849 + nand_release (au1550_mtd);
21851 + /* Free the MTD device structure */
21852 + kfree (au1550_mtd);
21855 + iounmap ((void *)p_nand);
21857 +module_exit(au1550_cleanup);
21860 +MODULE_LICENSE("GPL");
21861 +MODULE_AUTHOR("Embedded Edge, LLC");
21862 +MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Pb1550 board");
21863 Index: linux-2.6.5/drivers/mtd/nand/autcpu12.c
21864 ===================================================================
21865 --- linux-2.6.5.orig/drivers/mtd/nand/autcpu12.c 2004-04-03 22:36:25.000000000 -0500
21866 +++ linux-2.6.5/drivers/mtd/nand/autcpu12.c 2005-02-01 17:11:17.000000000 -0500
21868 * Derived from drivers/mtd/spia.c
21869 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
21871 - * $Id: autcpu12.c,v 1.11 2003/06/04 17:04:09 gleixner Exp $
21872 + * $Id: autcpu12.c,v 1.21 2004/09/16 23:27:14 gleixner Exp $
21874 * This program is free software; you can redistribute it and/or modify
21875 * it under the terms of the GNU General Public License version 2 as
21878 * This is a device driver for the NAND flash device found on the
21879 * autronix autcpu12 board, which is a SmartMediaCard. It supports
21880 - * 16MB, 32MB and 64MB cards.
21881 + * 16MiB, 32MiB and 64MiB cards.
21884 * 02-12-2002 TG Cleanup of module params
21885 @@ -44,19 +44,11 @@
21887 static struct mtd_info *autcpu12_mtd = NULL;
21892 -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
21893 -#define autcpu12_init init_module
21894 -#define autcpu12_cleanup cleanup_module
21897 static int autcpu12_io_base = CS89712_VIRT_BASE;
21898 static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC;
21899 static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET;
21900 static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET;
21901 -static int autcpu12_fio_base;
21902 +static void __iomem * autcpu12_fio_base;
21905 MODULE_PARM(autcpu12_fio_pbase, "i");
21906 @@ -71,42 +63,40 @@
21908 * Define partitions for flash devices
21910 -extern struct nand_oobinfo jffs2_oobinfo;
21912 static struct mtd_partition partition_info16k[] = {
21913 - { .name = "AUTCPU12 flash partition 1",
21915 - .size = 8 * SZ_1M },
21916 - { .name = "AUTCPU12 flash partition 2",
21917 - .offset = 8 * SZ_1M,
21918 - .size = 8 * SZ_1M },
21919 + { .name = "AUTCPU12 flash partition 1",
21921 + .size = 8 * SZ_1M },
21922 + { .name = "AUTCPU12 flash partition 2",
21923 + .offset = 8 * SZ_1M,
21924 + .size = 8 * SZ_1M },
21927 static struct mtd_partition partition_info32k[] = {
21928 - { .name = "AUTCPU12 flash partition 1",
21930 - .size = 8 * SZ_1M },
21931 - { .name = "AUTCPU12 flash partition 2",
21932 - .offset = 8 * SZ_1M,
21933 - .size = 24 * SZ_1M },
21934 + { .name = "AUTCPU12 flash partition 1",
21936 + .size = 8 * SZ_1M },
21937 + { .name = "AUTCPU12 flash partition 2",
21938 + .offset = 8 * SZ_1M,
21939 + .size = 24 * SZ_1M },
21942 static struct mtd_partition partition_info64k[] = {
21943 - { .name = "AUTCPU12 flash partition 1",
21945 - .size = 16 * SZ_1M },
21946 - { .name = "AUTCPU12 flash partition 2",
21947 - .offset = 16 * SZ_1M,
21948 - .size = 48 * SZ_1M },
21949 + { .name = "AUTCPU12 flash partition 1",
21951 + .size = 16 * SZ_1M },
21952 + { .name = "AUTCPU12 flash partition 2",
21953 + .offset = 16 * SZ_1M,
21954 + .size = 48 * SZ_1M },
21957 static struct mtd_partition partition_info128k[] = {
21958 - { .name = "AUTCPU12 flash partition 1",
21960 - .size = 16 * SZ_1M },
21961 - { .name = "AUTCPU12 flash partition 2",
21962 - .offset = 16 * SZ_1M,
21963 - .size = 112 * SZ_1M },
21964 + { .name = "AUTCPU12 flash partition 1",
21966 + .size = 16 * SZ_1M },
21967 + { .name = "AUTCPU12 flash partition 2",
21968 + .offset = 16 * SZ_1M,
21969 + .size = 112 * SZ_1M },
21972 #define NUM_PARTITIONS16K 2
21973 @@ -116,7 +106,7 @@
21975 * hardware specific access to control-lines
21977 -void autcpu12_hwcontrol(int cmd)
21978 +static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd)
21982 @@ -135,12 +125,13 @@
21984 * read device ready pin
21986 -int autcpu12_device_ready(void)
21987 +int autcpu12_device_ready(struct mtd_info *mtd)
21990 return ( (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0;
21995 * Main initialization routine
21997 @@ -159,7 +150,7 @@
22000 /* map physical adress */
22001 - autcpu12_fio_base=(unsigned long)ioremap(autcpu12_fio_pbase,SZ_1K);
22002 + autcpu12_fio_base=(void __iomem *)ioremap(autcpu12_fio_pbase,SZ_1K);
22003 if(!autcpu12_fio_base){
22004 printk("Ioremap autcpu12 SmartMedia Card failed\n");
22006 @@ -185,20 +176,18 @@
22007 this->chip_delay = 20;
22008 this->eccmode = NAND_ECC_SOFT;
22010 + /* Enable the following for a flash based bad block table */
22012 + this->options = NAND_USE_FLASH_BBT;
22014 + this->options = NAND_USE_FLASH_BBT;
22016 /* Scan to find existance of the device */
22017 - if (nand_scan (autcpu12_mtd)) {
22018 + if (nand_scan (autcpu12_mtd, 1)) {
22023 - /* Allocate memory for internal data buffer */
22024 - this->data_buf = kmalloc (sizeof(u_char) * (autcpu12_mtd->oobblock + autcpu12_mtd->oobsize), GFP_KERNEL);
22025 - if (!this->data_buf) {
22026 - printk ("Unable to allocate NAND data buffer for AUTCPU12.\n");
22032 /* Register the partitions */
22033 switch(autcpu12_mtd->size){
22034 case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break;
22035 @@ -208,13 +197,11 @@
22037 printk ("Unsupported SmartMedia device\n");
22046 - kfree (this->data_buf);
22048 iounmap((void *)autcpu12_fio_base);
22050 @@ -231,20 +218,12 @@
22052 static void __exit autcpu12_cleanup (void)
22054 - struct nand_chip *this = (struct nand_chip *) &autcpu12_mtd[1];
22056 - /* Unregister partitions */
22057 - del_mtd_partitions(autcpu12_mtd);
22059 - /* Unregister the device */
22060 - del_mtd_device (autcpu12_mtd);
22062 - /* Free internal data buffers */
22063 - kfree (this->data_buf);
22064 + /* Release resources, unregister device */
22065 + nand_release (autcpu12_mtd);
22067 /* unmap physical adress */
22068 iounmap((void *)autcpu12_fio_base);
22071 /* Free the MTD device structure */
22072 kfree (autcpu12_mtd);
22074 Index: linux-2.6.5/drivers/mtd/nand/diskonchip.c
22075 ===================================================================
22076 --- linux-2.6.5.orig/drivers/mtd/nand/diskonchip.c 1969-12-31 19:00:00.000000000 -0500
22077 +++ linux-2.6.5/drivers/mtd/nand/diskonchip.c 2005-02-01 17:11:17.000000000 -0500
22080 + * drivers/mtd/nand/diskonchip.c
22082 + * (C) 2003 Red Hat, Inc.
22083 + * (C) 2004 Dan Brown <dan_brown@ieee.org>
22084 + * (C) 2004 Kalev Lember <kalev@smartlink.ee>
22086 + * Author: David Woodhouse <dwmw2@infradead.org>
22087 + * Additional Diskonchip 2000 and Millennium support by Dan Brown <dan_brown@ieee.org>
22088 + * Diskonchip Millennium Plus support by Kalev Lember <kalev@smartlink.ee>
22090 + * Interface to generic NAND code for M-Systems DiskOnChip devices
22092 + * $Id: diskonchip.c,v 1.35 2004/09/16 23:27:14 gleixner Exp $
22095 +#include <linux/kernel.h>
22096 +#include <linux/init.h>
22097 +#include <linux/sched.h>
22098 +#include <linux/delay.h>
22099 +#include <asm/io.h>
22101 +#include <linux/mtd/mtd.h>
22102 +#include <linux/mtd/nand.h>
22103 +#include <linux/mtd/doc2000.h>
22104 +#include <linux/mtd/compatmac.h>
22105 +#include <linux/mtd/partitions.h>
22106 +#include <linux/mtd/inftl.h>
22108 +/* Where to look for the devices? */
22109 +#ifndef CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS
22110 +#define CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 0
22113 +static unsigned long __initdata doc_locations[] = {
22114 +#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
22115 +#ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH
22116 + 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
22117 + 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
22118 + 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
22119 + 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
22120 + 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
22121 +#else /* CONFIG_MTD_DOCPROBE_HIGH */
22122 + 0xc8000, 0xca000, 0xcc000, 0xce000,
22123 + 0xd0000, 0xd2000, 0xd4000, 0xd6000,
22124 + 0xd8000, 0xda000, 0xdc000, 0xde000,
22125 + 0xe0000, 0xe2000, 0xe4000, 0xe6000,
22126 + 0xe8000, 0xea000, 0xec000, 0xee000,
22127 +#endif /* CONFIG_MTD_DOCPROBE_HIGH */
22128 +#elif defined(__PPC__)
22130 +#elif defined(CONFIG_MOMENCO_OCELOT)
22133 +#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
22136 +#warning Unknown architecture for DiskOnChip. No default probe locations defined
22140 +static struct mtd_info *doclist = NULL;
22143 + void __iomem *virtadr;
22144 + unsigned long physadr;
22146 + u_char CDSNControl;
22147 + int chips_per_floor; /* The number of chips detected on each floor */
22152 + struct mtd_info *nextdoc;
22155 +/* Max number of eraseblocks to scan (from start of device) for the (I)NFTL
22156 + MediaHeader. The spec says to just keep going, I think, but that's just
22158 +#define MAX_MEDIAHEADER_SCAN 8
22160 +/* This is the syndrome computed by the HW ecc generator upon reading an empty
22161 + page, one with all 0xff for data and stored ecc code. */
22162 +static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a };
22163 +/* This is the ecc value computed by the HW ecc generator upon writing an empty
22164 + page, one with all 0xff for data. */
22165 +static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
22167 +#define INFTL_BBT_RESERVED_BLOCKS 4
22169 +#define DoC_is_MillenniumPlus(doc) ((doc)->ChipID == DOC_ChipID_DocMilPlus16 || (doc)->ChipID == DOC_ChipID_DocMilPlus32)
22170 +#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
22171 +#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
22173 +static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd);
22174 +static void doc200x_select_chip(struct mtd_info *mtd, int chip);
22176 +static int debug=0;
22177 +MODULE_PARM(debug, "i");
22179 +static int try_dword=1;
22180 +MODULE_PARM(try_dword, "i");
22182 +static int no_ecc_failures=0;
22183 +MODULE_PARM(no_ecc_failures, "i");
22185 +#ifdef CONFIG_MTD_PARTITIONS
22186 +static int no_autopart=0;
22187 +MODULE_PARM(no_autopart, "i");
22190 +#ifdef MTD_NAND_DISKONCHIP_BBTWRITE
22191 +static int inftl_bbt_write=1;
22193 +static int inftl_bbt_write=0;
22195 +MODULE_PARM(inftl_bbt_write, "i");
22197 +static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS;
22198 +MODULE_PARM(doc_config_location, "l");
22199 +MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
22201 +static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
22203 + volatile char dummy;
22206 + for (i = 0; i < cycles; i++) {
22207 + if (DoC_is_Millennium(doc))
22208 + dummy = ReadDOC(doc->virtadr, NOP);
22209 + else if (DoC_is_MillenniumPlus(doc))
22210 + dummy = ReadDOC(doc->virtadr, Mplus_NOP);
22212 + dummy = ReadDOC(doc->virtadr, DOCStatus);
22217 +#define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)
22219 +/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
22220 +static int _DoC_WaitReady(struct doc_priv *doc)
22222 + void __iomem *docptr = doc->virtadr;
22223 + unsigned long timeo = jiffies + (HZ * 10);
22225 + if(debug) printk("_DoC_WaitReady...\n");
22226 + /* Out-of-line routine to wait for chip response */
22227 + if (DoC_is_MillenniumPlus(doc)) {
22228 + while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) {
22229 + if (time_after(jiffies, timeo)) {
22230 + printk("_DoC_WaitReady timed out.\n");
22237 + while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
22238 + if (time_after(jiffies, timeo)) {
22239 + printk("_DoC_WaitReady timed out.\n");
22250 +static inline int DoC_WaitReady(struct doc_priv *doc)
22252 + void __iomem *docptr = doc->virtadr;
22255 + if (DoC_is_MillenniumPlus(doc)) {
22256 + DoC_Delay(doc, 4);
22258 + if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK)
22259 + /* Call the out-of-line routine to wait */
22260 + ret = _DoC_WaitReady(doc);
22262 + DoC_Delay(doc, 4);
22264 + if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
22265 + /* Call the out-of-line routine to wait */
22266 + ret = _DoC_WaitReady(doc);
22267 + DoC_Delay(doc, 2);
22270 + if(debug) printk("DoC_WaitReady OK\n");
22274 +static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
22276 + struct nand_chip *this = mtd->priv;
22277 + struct doc_priv *doc = (void *)this->priv;
22278 + void __iomem *docptr = doc->virtadr;
22280 + if(debug)printk("write_byte %02x\n", datum);
22281 + WriteDOC(datum, docptr, CDSNSlowIO);
22282 + WriteDOC(datum, docptr, 2k_CDSN_IO);
22285 +static u_char doc2000_read_byte(struct mtd_info *mtd)
22287 + struct nand_chip *this = mtd->priv;
22288 + struct doc_priv *doc = (void *)this->priv;
22289 + void __iomem *docptr = doc->virtadr;
22292 + ReadDOC(docptr, CDSNSlowIO);
22293 + DoC_Delay(doc, 2);
22294 + ret = ReadDOC(docptr, 2k_CDSN_IO);
22295 + if (debug) printk("read_byte returns %02x\n", ret);
22299 +static void doc2000_writebuf(struct mtd_info *mtd,
22300 + const u_char *buf, int len)
22302 + struct nand_chip *this = mtd->priv;
22303 + struct doc_priv *doc = (void *)this->priv;
22304 + void __iomem *docptr = doc->virtadr;
22306 + if (debug)printk("writebuf of %d bytes: ", len);
22307 + for (i=0; i < len; i++) {
22308 + WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i);
22309 + if (debug && i < 16)
22310 + printk("%02x ", buf[i]);
22312 + if (debug) printk("\n");
22315 +static void doc2000_readbuf(struct mtd_info *mtd,
22316 + u_char *buf, int len)
22318 + struct nand_chip *this = mtd->priv;
22319 + struct doc_priv *doc = (void *)this->priv;
22320 + void __iomem *docptr = doc->virtadr;
22323 + if (debug)printk("readbuf of %d bytes: ", len);
22325 + for (i=0; i < len; i++) {
22326 + buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i);
22330 +static void doc2000_readbuf_dword(struct mtd_info *mtd,
22331 + u_char *buf, int len)
22333 + struct nand_chip *this = mtd->priv;
22334 + struct doc_priv *doc = (void *)this->priv;
22335 + void __iomem *docptr = doc->virtadr;
22338 + if (debug) printk("readbuf_dword of %d bytes: ", len);
22340 + if (unlikely((((unsigned long)buf)|len) & 3)) {
22341 + for (i=0; i < len; i++) {
22342 + *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i);
22345 + for (i=0; i < len; i+=4) {
22346 + *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i);
22351 +static int doc2000_verifybuf(struct mtd_info *mtd,
22352 + const u_char *buf, int len)
22354 + struct nand_chip *this = mtd->priv;
22355 + struct doc_priv *doc = (void *)this->priv;
22356 + void __iomem *docptr = doc->virtadr;
22359 + for (i=0; i < len; i++)
22360 + if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO))
22365 +static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
22367 + struct nand_chip *this = mtd->priv;
22368 + struct doc_priv *doc = (void *)this->priv;
22371 + doc200x_select_chip(mtd, nr);
22372 + doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
22373 + this->write_byte(mtd, NAND_CMD_READID);
22374 + doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
22375 + doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
22376 + this->write_byte(mtd, 0);
22377 + doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
22379 + ret = this->read_byte(mtd) << 8;
22380 + ret |= this->read_byte(mtd);
22382 + if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) {
22383 + /* First chip probe. See if we get same results by 32-bit access */
22388 + void __iomem *docptr = doc->virtadr;
22390 + doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
22391 + doc2000_write_byte(mtd, NAND_CMD_READID);
22392 + doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
22393 + doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
22394 + doc2000_write_byte(mtd, 0);
22395 + doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
22397 + ident.dword = readl(docptr + DoC_2k_CDSN_IO);
22398 + if (((ident.byte[0] << 8) | ident.byte[1]) == ret) {
22399 + printk(KERN_INFO "DiskOnChip 2000 responds to DWORD access\n");
22400 + this->read_buf = &doc2000_readbuf_dword;
22407 +static void __init doc2000_count_chips(struct mtd_info *mtd)
22409 + struct nand_chip *this = mtd->priv;
22410 + struct doc_priv *doc = (void *)this->priv;
22414 + /* Max 4 chips per floor on DiskOnChip 2000 */
22415 + doc->chips_per_floor = 4;
22417 + /* Find out what the first chip is */
22418 + mfrid = doc200x_ident_chip(mtd, 0);
22420 + /* Find how many chips in each floor. */
22421 + for (i = 1; i < 4; i++) {
22422 + if (doc200x_ident_chip(mtd, i) != mfrid)
22425 + doc->chips_per_floor = i;
22426 + printk(KERN_DEBUG "Detected %d chips per floor.\n", i);
22429 +static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
22431 + struct doc_priv *doc = (void *)this->priv;
22435 + DoC_WaitReady(doc);
22436 + this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
22437 + DoC_WaitReady(doc);
22438 + status = (int)this->read_byte(mtd);
22443 +static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
22445 + struct nand_chip *this = mtd->priv;
22446 + struct doc_priv *doc = (void *)this->priv;
22447 + void __iomem *docptr = doc->virtadr;
22449 + WriteDOC(datum, docptr, CDSNSlowIO);
22450 + WriteDOC(datum, docptr, Mil_CDSN_IO);
22451 + WriteDOC(datum, docptr, WritePipeTerm);
22454 +static u_char doc2001_read_byte(struct mtd_info *mtd)
22456 + struct nand_chip *this = mtd->priv;
22457 + struct doc_priv *doc = (void *)this->priv;
22458 + void __iomem *docptr = doc->virtadr;
22460 + //ReadDOC(docptr, CDSNSlowIO);
22461 + /* 11.4.5 -- delay twice to allow extended length cycle */
22462 + DoC_Delay(doc, 2);
22463 + ReadDOC(docptr, ReadPipeInit);
22464 + //return ReadDOC(docptr, Mil_CDSN_IO);
22465 + return ReadDOC(docptr, LastDataRead);
22468 +static void doc2001_writebuf(struct mtd_info *mtd,
22469 + const u_char *buf, int len)
22471 + struct nand_chip *this = mtd->priv;
22472 + struct doc_priv *doc = (void *)this->priv;
22473 + void __iomem *docptr = doc->virtadr;
22476 + for (i=0; i < len; i++)
22477 + WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);
22478 + /* Terminate write pipeline */
22479 + WriteDOC(0x00, docptr, WritePipeTerm);
22482 +static void doc2001_readbuf(struct mtd_info *mtd,
22483 + u_char *buf, int len)
22485 + struct nand_chip *this = mtd->priv;
22486 + struct doc_priv *doc = (void *)this->priv;
22487 + void __iomem *docptr = doc->virtadr;
22490 + /* Start read pipeline */
22491 + ReadDOC(docptr, ReadPipeInit);
22493 + for (i=0; i < len-1; i++)
22494 + buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff));
22496 + /* Terminate read pipeline */
22497 + buf[i] = ReadDOC(docptr, LastDataRead);
22500 +static int doc2001_verifybuf(struct mtd_info *mtd,
22501 + const u_char *buf, int len)
22503 + struct nand_chip *this = mtd->priv;
22504 + struct doc_priv *doc = (void *)this->priv;
22505 + void __iomem *docptr = doc->virtadr;
22508 + /* Start read pipeline */
22509 + ReadDOC(docptr, ReadPipeInit);
22511 + for (i=0; i < len-1; i++)
22512 + if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
22513 + ReadDOC(docptr, LastDataRead);
22516 + if (buf[i] != ReadDOC(docptr, LastDataRead))
22521 +static u_char doc2001plus_read_byte(struct mtd_info *mtd)
22523 + struct nand_chip *this = mtd->priv;
22524 + struct doc_priv *doc = (void *)this->priv;
22525 + void __iomem *docptr = doc->virtadr;
22528 + ReadDOC(docptr, Mplus_ReadPipeInit);
22529 + ReadDOC(docptr, Mplus_ReadPipeInit);
22530 + ret = ReadDOC(docptr, Mplus_LastDataRead);
22531 + if (debug) printk("read_byte returns %02x\n", ret);
22535 +static void doc2001plus_writebuf(struct mtd_info *mtd,
22536 + const u_char *buf, int len)
22538 + struct nand_chip *this = mtd->priv;
22539 + struct doc_priv *doc = (void *)this->priv;
22540 + void __iomem *docptr = doc->virtadr;
22543 + if (debug)printk("writebuf of %d bytes: ", len);
22544 + for (i=0; i < len; i++) {
22545 + WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);
22546 + if (debug && i < 16)
22547 + printk("%02x ", buf[i]);
22549 + if (debug) printk("\n");
22552 +static void doc2001plus_readbuf(struct mtd_info *mtd,
22553 + u_char *buf, int len)
22555 + struct nand_chip *this = mtd->priv;
22556 + struct doc_priv *doc = (void *)this->priv;
22557 + void __iomem *docptr = doc->virtadr;
22560 + if (debug)printk("readbuf of %d bytes: ", len);
22562 + /* Start read pipeline */
22563 + ReadDOC(docptr, Mplus_ReadPipeInit);
22564 + ReadDOC(docptr, Mplus_ReadPipeInit);
22566 + for (i=0; i < len-2; i++) {
22567 + buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
22568 + if (debug && i < 16)
22569 + printk("%02x ", buf[i]);
22572 + /* Terminate read pipeline */
22573 + buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead);
22574 + if (debug && i < 16)
22575 + printk("%02x ", buf[len-2]);
22576 + buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead);
22577 + if (debug && i < 16)
22578 + printk("%02x ", buf[len-1]);
22579 + if (debug) printk("\n");
22582 +static int doc2001plus_verifybuf(struct mtd_info *mtd,
22583 + const u_char *buf, int len)
22585 + struct nand_chip *this = mtd->priv;
22586 + struct doc_priv *doc = (void *)this->priv;
22587 + void __iomem *docptr = doc->virtadr;
22590 + if (debug)printk("verifybuf of %d bytes: ", len);
22592 + /* Start read pipeline */
22593 + ReadDOC(docptr, Mplus_ReadPipeInit);
22594 + ReadDOC(docptr, Mplus_ReadPipeInit);
22596 + for (i=0; i < len-2; i++)
22597 + if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
22598 + ReadDOC(docptr, Mplus_LastDataRead);
22599 + ReadDOC(docptr, Mplus_LastDataRead);
22602 + if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead))
22604 + if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead))
22609 +static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
22611 + struct nand_chip *this = mtd->priv;
22612 + struct doc_priv *doc = (void *)this->priv;
22613 + void __iomem *docptr = doc->virtadr;
22616 + if(debug)printk("select chip (%d)\n", chip);
22618 + if (chip == -1) {
22619 + /* Disable flash internally */
22620 + WriteDOC(0, docptr, Mplus_FlashSelect);
22624 + floor = chip / doc->chips_per_floor;
22625 + chip -= (floor * doc->chips_per_floor);
22627 + /* Assert ChipEnable and deassert WriteProtect */
22628 + WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect);
22629 + this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
22631 + doc->curchip = chip;
22632 + doc->curfloor = floor;
22635 +static void doc200x_select_chip(struct mtd_info *mtd, int chip)
22637 + struct nand_chip *this = mtd->priv;
22638 + struct doc_priv *doc = (void *)this->priv;
22639 + void __iomem *docptr = doc->virtadr;
22642 + if(debug)printk("select chip (%d)\n", chip);
22647 + floor = chip / doc->chips_per_floor;
22648 + chip -= (floor * doc->chips_per_floor);
22650 + /* 11.4.4 -- deassert CE before changing chip */
22651 + doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE);
22653 + WriteDOC(floor, docptr, FloorSelect);
22654 + WriteDOC(chip, docptr, CDSNDeviceSelect);
22656 + doc200x_hwcontrol(mtd, NAND_CTL_SETNCE);
22658 + doc->curchip = chip;
22659 + doc->curfloor = floor;
22662 +static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd)
22664 + struct nand_chip *this = mtd->priv;
22665 + struct doc_priv *doc = (void *)this->priv;
22666 + void __iomem *docptr = doc->virtadr;
22669 + case NAND_CTL_SETNCE:
22670 + doc->CDSNControl |= CDSN_CTRL_CE;
22672 + case NAND_CTL_CLRNCE:
22673 + doc->CDSNControl &= ~CDSN_CTRL_CE;
22675 + case NAND_CTL_SETCLE:
22676 + doc->CDSNControl |= CDSN_CTRL_CLE;
22678 + case NAND_CTL_CLRCLE:
22679 + doc->CDSNControl &= ~CDSN_CTRL_CLE;
22681 + case NAND_CTL_SETALE:
22682 + doc->CDSNControl |= CDSN_CTRL_ALE;
22684 + case NAND_CTL_CLRALE:
22685 + doc->CDSNControl &= ~CDSN_CTRL_ALE;
22687 + case NAND_CTL_SETWP:
22688 + doc->CDSNControl |= CDSN_CTRL_WP;
22690 + case NAND_CTL_CLRWP:
22691 + doc->CDSNControl &= ~CDSN_CTRL_WP;
22694 + if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
22695 + WriteDOC(doc->CDSNControl, docptr, CDSNControl);
22696 + /* 11.4.3 -- 4 NOPs after CSDNControl write */
22697 + DoC_Delay(doc, 4);
22700 +static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
22702 + struct nand_chip *this = mtd->priv;
22703 + struct doc_priv *doc = (void *)this->priv;
22704 + void __iomem *docptr = doc->virtadr;
22707 + * Must terminate write pipeline before sending any commands
22710 + if (command == NAND_CMD_PAGEPROG) {
22711 + WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
22712 + WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
22716 + * Write out the command to the device.
22718 + if (command == NAND_CMD_SEQIN) {
22721 + if (column >= mtd->oobblock) {
22723 + column -= mtd->oobblock;
22724 + readcmd = NAND_CMD_READOOB;
22725 + } else if (column < 256) {
22726 + /* First 256 bytes --> READ0 */
22727 + readcmd = NAND_CMD_READ0;
22730 + readcmd = NAND_CMD_READ1;
22732 + WriteDOC(readcmd, docptr, Mplus_FlashCmd);
22734 + WriteDOC(command, docptr, Mplus_FlashCmd);
22735 + WriteDOC(0, docptr, Mplus_WritePipeTerm);
22736 + WriteDOC(0, docptr, Mplus_WritePipeTerm);
22738 + if (column != -1 || page_addr != -1) {
22739 + /* Serially input address */
22740 + if (column != -1) {
22741 + /* Adjust columns for 16 bit buswidth */
22742 + if (this->options & NAND_BUSWIDTH_16)
22744 + WriteDOC(column, docptr, Mplus_FlashAddress);
22746 + if (page_addr != -1) {
22747 + WriteDOC((unsigned char) (page_addr & 0xff), docptr, Mplus_FlashAddress);
22748 + WriteDOC((unsigned char) ((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress);
22749 + /* One more address cycle for higher density devices */
22750 + if (this->chipsize & 0x0c000000) {
22751 + WriteDOC((unsigned char) ((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress);
22752 + printk("high density\n");
22755 + WriteDOC(0, docptr, Mplus_WritePipeTerm);
22756 + WriteDOC(0, docptr, Mplus_WritePipeTerm);
22757 + /* deassert ALE */
22758 + if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || command == NAND_CMD_READOOB || command == NAND_CMD_READID)
22759 + WriteDOC(0, docptr, Mplus_FlashControl);
22763 + * program and erase have their own busy handlers
22764 + * status and sequential in needs no delay
22766 + switch (command) {
22768 + case NAND_CMD_PAGEPROG:
22769 + case NAND_CMD_ERASE1:
22770 + case NAND_CMD_ERASE2:
22771 + case NAND_CMD_SEQIN:
22772 + case NAND_CMD_STATUS:
22775 + case NAND_CMD_RESET:
22776 + if (this->dev_ready)
22778 + udelay(this->chip_delay);
22779 + WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd);
22780 + WriteDOC(0, docptr, Mplus_WritePipeTerm);
22781 + WriteDOC(0, docptr, Mplus_WritePipeTerm);
22782 + while ( !(this->read_byte(mtd) & 0x40));
22785 + /* This applies to read commands */
22788 + * If we don't have access to the busy pin, we apply the given
22791 + if (!this->dev_ready) {
22792 + udelay (this->chip_delay);
22797 + /* Apply this short delay always to ensure that we do wait tWB in
22798 + * any case on any machine. */
22800 + /* wait until command is processed */
22801 + while (!this->dev_ready(mtd));
22804 +static int doc200x_dev_ready(struct mtd_info *mtd)
22806 + struct nand_chip *this = mtd->priv;
22807 + struct doc_priv *doc = (void *)this->priv;
22808 + void __iomem *docptr = doc->virtadr;
22810 + if (DoC_is_MillenniumPlus(doc)) {
22811 + /* 11.4.2 -- must NOP four times before checking FR/B# */
22812 + DoC_Delay(doc, 4);
22813 + if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) {
22815 + printk("not ready\n");
22818 + if (debug)printk("was ready\n");
22821 + /* 11.4.2 -- must NOP four times before checking FR/B# */
22822 + DoC_Delay(doc, 4);
22823 + if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
22825 + printk("not ready\n");
22828 + /* 11.4.2 -- Must NOP twice if it's ready */
22829 + DoC_Delay(doc, 2);
22830 + if (debug)printk("was ready\n");
22835 +static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
22837 + /* This is our last resort if we couldn't find or create a BBT. Just
22838 + pretend all blocks are good. */
22842 +static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
22844 + struct nand_chip *this = mtd->priv;
22845 + struct doc_priv *doc = (void *)this->priv;
22846 + void __iomem *docptr = doc->virtadr;
22848 + /* Prime the ECC engine */
22850 + case NAND_ECC_READ:
22851 + WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
22852 + WriteDOC(DOC_ECC_EN, docptr, ECCConf);
22854 + case NAND_ECC_WRITE:
22855 + WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
22856 + WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
22861 +static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
22863 + struct nand_chip *this = mtd->priv;
22864 + struct doc_priv *doc = (void *)this->priv;
22865 + void __iomem *docptr = doc->virtadr;
22867 + /* Prime the ECC engine */
22869 + case NAND_ECC_READ:
22870 + WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
22871 + WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
22873 + case NAND_ECC_WRITE:
22874 + WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
22875 + WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
22880 +/* This code is only called on write */
22881 +static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
22882 + unsigned char *ecc_code)
22884 + struct nand_chip *this = mtd->priv;
22885 + struct doc_priv *doc = (void *)this->priv;
22886 + void __iomem *docptr = doc->virtadr;
22888 + int emptymatch = 1;
22890 + /* flush the pipeline */
22891 + if (DoC_is_2000(doc)) {
22892 + WriteDOC(doc->CDSNControl & ~CDSN_CTRL_FLASH_IO, docptr, CDSNControl);
22893 + WriteDOC(0, docptr, 2k_CDSN_IO);
22894 + WriteDOC(0, docptr, 2k_CDSN_IO);
22895 + WriteDOC(0, docptr, 2k_CDSN_IO);
22896 + WriteDOC(doc->CDSNControl, docptr, CDSNControl);
22897 + } else if (DoC_is_MillenniumPlus(doc)) {
22898 + WriteDOC(0, docptr, Mplus_NOP);
22899 + WriteDOC(0, docptr, Mplus_NOP);
22900 + WriteDOC(0, docptr, Mplus_NOP);
22902 + WriteDOC(0, docptr, NOP);
22903 + WriteDOC(0, docptr, NOP);
22904 + WriteDOC(0, docptr, NOP);
22907 + for (i = 0; i < 6; i++) {
22908 + if (DoC_is_MillenniumPlus(doc))
22909 + ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i);
22911 + ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
22912 + if (ecc_code[i] != empty_write_ecc[i])
22915 + if (DoC_is_MillenniumPlus(doc))
22916 + WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
22918 + WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
22920 + /* If emptymatch=1, we might have an all-0xff data buffer. Check. */
22921 + if (emptymatch) {
22922 + /* Note: this somewhat expensive test should not be triggered
22923 + often. It could be optimized away by examining the data in
22924 + the writebuf routine, and remembering the result. */
22925 + for (i = 0; i < 512; i++) {
22926 + if (dat[i] == 0xff) continue;
22931 + /* If emptymatch still =1, we do have an all-0xff data buffer.
22932 + Return all-0xff ecc value instead of the computed one, so
22933 + it'll look just like a freshly-erased page. */
22934 + if (emptymatch) memset(ecc_code, 0xff, 6);
22939 +static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
22942 + struct nand_chip *this = mtd->priv;
22943 + struct doc_priv *doc = (void *)this->priv;
22944 + void __iomem *docptr = doc->virtadr;
22945 + volatile u_char dummy;
22946 + int emptymatch = 1;
22948 + /* flush the pipeline */
22949 + if (DoC_is_2000(doc)) {
22950 + dummy = ReadDOC(docptr, 2k_ECCStatus);
22951 + dummy = ReadDOC(docptr, 2k_ECCStatus);
22952 + dummy = ReadDOC(docptr, 2k_ECCStatus);
22953 + } else if (DoC_is_MillenniumPlus(doc)) {
22954 + dummy = ReadDOC(docptr, Mplus_ECCConf);
22955 + dummy = ReadDOC(docptr, Mplus_ECCConf);
22956 + dummy = ReadDOC(docptr, Mplus_ECCConf);
22958 + dummy = ReadDOC(docptr, ECCConf);
22959 + dummy = ReadDOC(docptr, ECCConf);
22960 + dummy = ReadDOC(docptr, ECCConf);
22963 + /* Error occured ? */
22964 + if (dummy & 0x80) {
22965 + for (i = 0; i < 6; i++) {
22966 + if (DoC_is_MillenniumPlus(doc))
22967 + calc_ecc[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i);
22969 + calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
22970 + if (calc_ecc[i] != empty_read_syndrome[i])
22973 + /* If emptymatch=1, the read syndrome is consistent with an
22974 + all-0xff data and stored ecc block. Check the stored ecc. */
22975 + if (emptymatch) {
22976 + for (i = 0; i < 6; i++) {
22977 + if (read_ecc[i] == 0xff) continue;
22982 + /* If emptymatch still =1, check the data block. */
22983 + if (emptymatch) {
22984 + /* Note: this somewhat expensive test should not be triggered
22985 + often. It could be optimized away by examining the data in
22986 + the readbuf routine, and remembering the result. */
22987 + for (i = 0; i < 512; i++) {
22988 + if (dat[i] == 0xff) continue;
22993 + /* If emptymatch still =1, this is almost certainly a freshly-
22994 + erased block, in which case the ECC will not come out right.
22995 + We'll suppress the error and tell the caller everything's
22996 + OK. Because it is. */
22997 + if (!emptymatch) ret = doc_decode_ecc (dat, calc_ecc);
22999 + printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
23001 + if (DoC_is_MillenniumPlus(doc))
23002 + WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
23004 + WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
23005 + if (no_ecc_failures && (ret == -1)) {
23006 + printk(KERN_ERR "suppressing ECC failure\n");
23012 +//u_char mydatabuf[528];
23014 +static struct nand_oobinfo doc200x_oobinfo = {
23015 + .useecc = MTD_NANDECC_AUTOPLACE,
23017 + .eccpos = {0, 1, 2, 3, 4, 5},
23018 + .oobfree = { {8, 8} }
23021 +/* Find the (I)NFTL Media Header, and optionally also the mirror media header.
23022 + On sucessful return, buf will contain a copy of the media header for
23023 + further processing. id is the string to scan for, and will presumably be
23024 + either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media
23025 + header. The page #s of the found media headers are placed in mh0_page and
23026 + mh1_page in the DOC private structure. */
23027 +static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
23028 + const char *id, int findmirror)
23030 + struct nand_chip *this = mtd->priv;
23031 + struct doc_priv *doc = (void *)this->priv;
23032 + unsigned offs, end = (MAX_MEDIAHEADER_SCAN << this->phys_erase_shift);
23036 + end = min(end, mtd->size); // paranoia
23037 + for (offs = 0; offs < end; offs += mtd->erasesize) {
23038 + ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
23039 + if (retlen != mtd->oobblock) continue;
23041 + printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n",
23044 + if (memcmp(buf, id, 6)) continue;
23045 + printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs);
23046 + if (doc->mh0_page == -1) {
23047 + doc->mh0_page = offs >> this->page_shift;
23048 + if (!findmirror) return 1;
23051 + doc->mh1_page = offs >> this->page_shift;
23054 + if (doc->mh0_page == -1) {
23055 + printk(KERN_WARNING "DiskOnChip %s Media Header not found.\n", id);
23058 + /* Only one mediaheader was found. We want buf to contain a
23059 + mediaheader on return, so we'll have to re-read the one we found. */
23060 + offs = doc->mh0_page << this->page_shift;
23061 + ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
23062 + if (retlen != mtd->oobblock) {
23063 + /* Insanity. Give up. */
23064 + printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n");
23070 +static inline int __init nftl_partscan(struct mtd_info *mtd,
23071 + struct mtd_partition *parts)
23073 + struct nand_chip *this = mtd->priv;
23074 + struct doc_priv *doc = (void *)this->priv;
23077 + struct NFTLMediaHeader *mh;
23078 + const unsigned psize = 1 << this->page_shift;
23079 + unsigned blocks, maxblocks;
23080 + int offs, numheaders;
23082 + buf = (u_char *) kmalloc(mtd->oobblock, GFP_KERNEL);
23084 + printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
23087 + if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out;
23088 + mh = (struct NFTLMediaHeader *) buf;
23090 +//#ifdef CONFIG_MTD_DEBUG_VERBOSE
23091 +// if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
23092 + printk(KERN_INFO " DataOrgID = %s\n"
23093 + " NumEraseUnits = %d\n"
23094 + " FirstPhysicalEUN = %d\n"
23095 + " FormattedSize = %d\n"
23096 + " UnitSizeFactor = %d\n",
23097 + mh->DataOrgID, mh->NumEraseUnits,
23098 + mh->FirstPhysicalEUN, mh->FormattedSize,
23099 + mh->UnitSizeFactor);
23102 + blocks = mtd->size >> this->phys_erase_shift;
23103 + maxblocks = min(32768U, mtd->erasesize - psize);
23105 + if (mh->UnitSizeFactor == 0x00) {
23106 + /* Auto-determine UnitSizeFactor. The constraints are:
23107 + - There can be at most 32768 virtual blocks.
23108 + - There can be at most (virtual block size - page size)
23109 + virtual blocks (because MediaHeader+BBT must fit in 1).
23111 + mh->UnitSizeFactor = 0xff;
23112 + while (blocks > maxblocks) {
23114 + maxblocks = min(32768U, (maxblocks << 1) + psize);
23115 + mh->UnitSizeFactor--;
23117 + printk(KERN_WARNING "UnitSizeFactor=0x00 detected. Correct value is assumed to be 0x%02x.\n", mh->UnitSizeFactor);
23120 + /* NOTE: The lines below modify internal variables of the NAND and MTD
23121 + layers; variables with have already been configured by nand_scan.
23122 + Unfortunately, we didn't know before this point what these values
23123 + should be. Thus, this code is somewhat dependant on the exact
23124 + implementation of the NAND layer. */
23125 + if (mh->UnitSizeFactor != 0xff) {
23126 + this->bbt_erase_shift += (0xff - mh->UnitSizeFactor);
23127 + mtd->erasesize <<= (0xff - mh->UnitSizeFactor);
23128 + printk(KERN_INFO "Setting virtual erase size to %d\n", mtd->erasesize);
23129 + blocks = mtd->size >> this->bbt_erase_shift;
23130 + maxblocks = min(32768U, mtd->erasesize - psize);
23133 + if (blocks > maxblocks) {
23134 + printk(KERN_ERR "UnitSizeFactor of 0x%02x is inconsistent with device size. Aborting.\n", mh->UnitSizeFactor);
23138 + /* Skip past the media headers. */
23139 + offs = max(doc->mh0_page, doc->mh1_page);
23140 + offs <<= this->page_shift;
23141 + offs += mtd->erasesize;
23143 + //parts[0].name = " DiskOnChip Boot / Media Header partition";
23144 + //parts[0].offset = 0;
23145 + //parts[0].size = offs;
23147 + parts[0].name = " DiskOnChip BDTL partition";
23148 + parts[0].offset = offs;
23149 + parts[0].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift;
23151 + offs += parts[0].size;
23152 + if (offs < mtd->size) {
23153 + parts[1].name = " DiskOnChip Remainder partition";
23154 + parts[1].offset = offs;
23155 + parts[1].size = mtd->size - offs;
23165 +/* This is a stripped-down copy of the code in inftlmount.c */
23166 +static inline int __init inftl_partscan(struct mtd_info *mtd,
23167 + struct mtd_partition *parts)
23169 + struct nand_chip *this = mtd->priv;
23170 + struct doc_priv *doc = (void *)this->priv;
23173 + struct INFTLMediaHeader *mh;
23174 + struct INFTLPartition *ip;
23175 + int numparts = 0;
23177 + int vshift, lastvunit = 0;
23179 + int end = mtd->size;
23181 + if (inftl_bbt_write)
23182 + end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift);
23184 + buf = (u_char *) kmalloc(mtd->oobblock, GFP_KERNEL);
23186 + printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
23190 + if (!find_media_headers(mtd, buf, "BNAND", 0)) goto out;
23191 + doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift);
23192 + mh = (struct INFTLMediaHeader *) buf;
23194 + mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
23195 + mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
23196 + mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions);
23197 + mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);
23198 + mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
23199 + mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
23201 +//#ifdef CONFIG_MTD_DEBUG_VERBOSE
23202 +// if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
23203 + printk(KERN_INFO " bootRecordID = %s\n"
23204 + " NoOfBootImageBlocks = %d\n"
23205 + " NoOfBinaryPartitions = %d\n"
23206 + " NoOfBDTLPartitions = %d\n"
23207 + " BlockMultiplerBits = %d\n"
23208 + " FormatFlgs = %d\n"
23209 + " OsakVersion = %d.%d.%d.%d\n"
23210 + " PercentUsed = %d\n",
23211 + mh->bootRecordID, mh->NoOfBootImageBlocks,
23212 + mh->NoOfBinaryPartitions,
23213 + mh->NoOfBDTLPartitions,
23214 + mh->BlockMultiplierBits, mh->FormatFlags,
23215 + ((unsigned char *) &mh->OsakVersion)[0] & 0xf,
23216 + ((unsigned char *) &mh->OsakVersion)[1] & 0xf,
23217 + ((unsigned char *) &mh->OsakVersion)[2] & 0xf,
23218 + ((unsigned char *) &mh->OsakVersion)[3] & 0xf,
23219 + mh->PercentUsed);
23222 + vshift = this->phys_erase_shift + mh->BlockMultiplierBits;
23224 + blocks = mtd->size >> vshift;
23225 + if (blocks > 32768) {
23226 + printk(KERN_ERR "BlockMultiplierBits=%d is inconsistent with device size. Aborting.\n", mh->BlockMultiplierBits);
23230 + blocks = doc->chips_per_floor << (this->chip_shift - this->phys_erase_shift);
23231 + if (inftl_bbt_write && (blocks > mtd->erasesize)) {
23232 + printk(KERN_ERR "Writeable BBTs spanning more than one erase block are not yet supported. FIX ME!\n");
23236 + /* Scan the partitions */
23237 + for (i = 0; (i < 4); i++) {
23238 + ip = &(mh->Partitions[i]);
23239 + ip->virtualUnits = le32_to_cpu(ip->virtualUnits);
23240 + ip->firstUnit = le32_to_cpu(ip->firstUnit);
23241 + ip->lastUnit = le32_to_cpu(ip->lastUnit);
23242 + ip->flags = le32_to_cpu(ip->flags);
23243 + ip->spareUnits = le32_to_cpu(ip->spareUnits);
23244 + ip->Reserved0 = le32_to_cpu(ip->Reserved0);
23246 +//#ifdef CONFIG_MTD_DEBUG_VERBOSE
23247 +// if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
23248 + printk(KERN_INFO " PARTITION[%d] ->\n"
23249 + " virtualUnits = %d\n"
23250 + " firstUnit = %d\n"
23251 + " lastUnit = %d\n"
23252 + " flags = 0x%x\n"
23253 + " spareUnits = %d\n",
23254 + i, ip->virtualUnits, ip->firstUnit,
23255 + ip->lastUnit, ip->flags,
23260 + if ((i == 0) && (ip->firstUnit > 0)) {
23261 + parts[0].name = " DiskOnChip IPL / Media Header partition";
23262 + parts[0].offset = 0;
23263 + parts[0].size = mtd->erasesize * ip->firstUnit;
23268 + if (ip->flags & INFTL_BINARY)
23269 + parts[numparts].name = " DiskOnChip BDK partition";
23271 + parts[numparts].name = " DiskOnChip BDTL partition";
23272 + parts[numparts].offset = ip->firstUnit << vshift;
23273 + parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift;
23275 + if (ip->lastUnit > lastvunit) lastvunit = ip->lastUnit;
23276 + if (ip->flags & INFTL_LAST) break;
23279 + if ((lastvunit << vshift) < end) {
23280 + parts[numparts].name = " DiskOnChip Remainder partition";
23281 + parts[numparts].offset = lastvunit << vshift;
23282 + parts[numparts].size = end - parts[numparts].offset;
23291 +static int __init nftl_scan_bbt(struct mtd_info *mtd)
23293 + int ret, numparts;
23294 + struct nand_chip *this = mtd->priv;
23295 + struct doc_priv *doc = (void *)this->priv;
23296 + struct mtd_partition parts[2];
23298 + memset((char *) parts, 0, sizeof(parts));
23299 + /* On NFTL, we have to find the media headers before we can read the
23300 + BBTs, since they're stored in the media header eraseblocks. */
23301 + numparts = nftl_partscan(mtd, parts);
23302 + if (!numparts) return -EIO;
23303 + this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT |
23304 + NAND_BBT_SAVECONTENT | NAND_BBT_WRITE |
23305 + NAND_BBT_VERSION;
23306 + this->bbt_td->veroffs = 7;
23307 + this->bbt_td->pages[0] = doc->mh0_page + 1;
23308 + if (doc->mh1_page != -1) {
23309 + this->bbt_md->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT |
23310 + NAND_BBT_SAVECONTENT | NAND_BBT_WRITE |
23311 + NAND_BBT_VERSION;
23312 + this->bbt_md->veroffs = 7;
23313 + this->bbt_md->pages[0] = doc->mh1_page + 1;
23315 + this->bbt_md = NULL;
23318 + /* It's safe to set bd=NULL below because NAND_BBT_CREATE is not set.
23319 + At least as nand_bbt.c is currently written. */
23320 + if ((ret = nand_scan_bbt(mtd, NULL)))
23322 + add_mtd_device(mtd);
23323 +#ifdef CONFIG_MTD_PARTITIONS
23324 + if (!no_autopart)
23325 + add_mtd_partitions(mtd, parts, numparts);
23330 +static int __init inftl_scan_bbt(struct mtd_info *mtd)
23332 + int ret, numparts;
23333 + struct nand_chip *this = mtd->priv;
23334 + struct doc_priv *doc = (void *)this->priv;
23335 + struct mtd_partition parts[5];
23337 + if (this->numchips > doc->chips_per_floor) {
23338 + printk(KERN_ERR "Multi-floor INFTL devices not yet supported.\n");
23342 + if (DoC_is_MillenniumPlus(doc)) {
23343 + this->bbt_td->options = NAND_BBT_2BIT | NAND_BBT_ABSPAGE;
23344 + if (inftl_bbt_write)
23345 + this->bbt_td->options |= NAND_BBT_WRITE;
23346 + this->bbt_td->pages[0] = 2;
23347 + this->bbt_md = NULL;
23349 + this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT |
23350 + NAND_BBT_VERSION;
23351 + if (inftl_bbt_write)
23352 + this->bbt_td->options |= NAND_BBT_WRITE;
23353 + this->bbt_td->offs = 8;
23354 + this->bbt_td->len = 8;
23355 + this->bbt_td->veroffs = 7;
23356 + this->bbt_td->maxblocks = INFTL_BBT_RESERVED_BLOCKS;
23357 + this->bbt_td->reserved_block_code = 0x01;
23358 + this->bbt_td->pattern = "MSYS_BBT";
23360 + this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT |
23361 + NAND_BBT_VERSION;
23362 + if (inftl_bbt_write)
23363 + this->bbt_md->options |= NAND_BBT_WRITE;
23364 + this->bbt_md->offs = 8;
23365 + this->bbt_md->len = 8;
23366 + this->bbt_md->veroffs = 7;
23367 + this->bbt_md->maxblocks = INFTL_BBT_RESERVED_BLOCKS;
23368 + this->bbt_md->reserved_block_code = 0x01;
23369 + this->bbt_md->pattern = "TBB_SYSM";
23372 + /* It's safe to set bd=NULL below because NAND_BBT_CREATE is not set.
23373 + At least as nand_bbt.c is currently written. */
23374 + if ((ret = nand_scan_bbt(mtd, NULL)))
23376 + memset((char *) parts, 0, sizeof(parts));
23377 + numparts = inftl_partscan(mtd, parts);
23378 + /* At least for now, require the INFTL Media Header. We could probably
23379 + do without it for non-INFTL use, since all it gives us is
23380 + autopartitioning, but I want to give it more thought. */
23381 + if (!numparts) return -EIO;
23382 + add_mtd_device(mtd);
23383 +#ifdef CONFIG_MTD_PARTITIONS
23384 + if (!no_autopart)
23385 + add_mtd_partitions(mtd, parts, numparts);
23390 +static inline int __init doc2000_init(struct mtd_info *mtd)
23392 + struct nand_chip *this = mtd->priv;
23393 + struct doc_priv *doc = (void *)this->priv;
23395 + this->write_byte = doc2000_write_byte;
23396 + this->read_byte = doc2000_read_byte;
23397 + this->write_buf = doc2000_writebuf;
23398 + this->read_buf = doc2000_readbuf;
23399 + this->verify_buf = doc2000_verifybuf;
23400 + this->scan_bbt = nftl_scan_bbt;
23402 + doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO;
23403 + doc2000_count_chips(mtd);
23404 + mtd->name = "DiskOnChip 2000 (NFTL Model)";
23405 + return (4 * doc->chips_per_floor);
23408 +static inline int __init doc2001_init(struct mtd_info *mtd)
23410 + struct nand_chip *this = mtd->priv;
23411 + struct doc_priv *doc = (void *)this->priv;
23413 + this->write_byte = doc2001_write_byte;
23414 + this->read_byte = doc2001_read_byte;
23415 + this->write_buf = doc2001_writebuf;
23416 + this->read_buf = doc2001_readbuf;
23417 + this->verify_buf = doc2001_verifybuf;
23419 + ReadDOC(doc->virtadr, ChipID);
23420 + ReadDOC(doc->virtadr, ChipID);
23421 + ReadDOC(doc->virtadr, ChipID);
23422 + if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) {
23423 + /* It's not a Millennium; it's one of the newer
23424 + DiskOnChip 2000 units with a similar ASIC.
23425 + Treat it like a Millennium, except that it
23426 + can have multiple chips. */
23427 + doc2000_count_chips(mtd);
23428 + mtd->name = "DiskOnChip 2000 (INFTL Model)";
23429 + this->scan_bbt = inftl_scan_bbt;
23430 + return (4 * doc->chips_per_floor);
23432 + /* Bog-standard Millennium */
23433 + doc->chips_per_floor = 1;
23434 + mtd->name = "DiskOnChip Millennium";
23435 + this->scan_bbt = nftl_scan_bbt;
23440 +static inline int __init doc2001plus_init(struct mtd_info *mtd)
23442 + struct nand_chip *this = mtd->priv;
23443 + struct doc_priv *doc = (void *)this->priv;
23445 + this->write_byte = NULL;
23446 + this->read_byte = doc2001plus_read_byte;
23447 + this->write_buf = doc2001plus_writebuf;
23448 + this->read_buf = doc2001plus_readbuf;
23449 + this->verify_buf = doc2001plus_verifybuf;
23450 + this->scan_bbt = inftl_scan_bbt;
23451 + this->hwcontrol = NULL;
23452 + this->select_chip = doc2001plus_select_chip;
23453 + this->cmdfunc = doc2001plus_command;
23454 + this->enable_hwecc = doc2001plus_enable_hwecc;
23456 + doc->chips_per_floor = 1;
23457 + mtd->name = "DiskOnChip Millennium Plus";
23462 +static inline int __init doc_probe(unsigned long physadr)
23464 + unsigned char ChipID;
23465 + struct mtd_info *mtd;
23466 + struct nand_chip *nand;
23467 + struct doc_priv *doc;
23468 + void __iomem *virtadr;
23469 + unsigned char save_control;
23470 + unsigned char tmp, tmpb, tmpc;
23471 + int reg, len, numchips;
23474 + virtadr = (void __iomem *)ioremap(physadr, DOC_IOREMAP_LEN);
23476 + printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr);
23480 + /* It's not possible to cleanly detect the DiskOnChip - the
23481 + * bootup procedure will put the device into reset mode, and
23482 + * it's not possible to talk to it without actually writing
23483 + * to the DOCControl register. So we store the current contents
23484 + * of the DOCControl register's location, in case we later decide
23485 + * that it's not a DiskOnChip, and want to put it back how we
23488 + save_control = ReadDOC(virtadr, DOCControl);
23490 + /* Reset the DiskOnChip ASIC */
23491 + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
23492 + virtadr, DOCControl);
23493 + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
23494 + virtadr, DOCControl);
23496 + /* Enable the DiskOnChip ASIC */
23497 + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
23498 + virtadr, DOCControl);
23499 + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
23500 + virtadr, DOCControl);
23502 + ChipID = ReadDOC(virtadr, ChipID);
23505 + case DOC_ChipID_Doc2k:
23506 + reg = DoC_2k_ECCStatus;
23508 + case DOC_ChipID_DocMil:
23509 + reg = DoC_ECCConf;
23511 + case DOC_ChipID_DocMilPlus16:
23512 + case DOC_ChipID_DocMilPlus32:
23514 + /* Possible Millennium Plus, need to do more checks */
23515 + /* Possibly release from power down mode */
23516 + for (tmp = 0; (tmp < 4); tmp++)
23517 + ReadDOC(virtadr, Mplus_Power);
23519 + /* Reset the Millennium Plus ASIC */
23520 + tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
23522 + WriteDOC(tmp, virtadr, Mplus_DOCControl);
23523 + WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
23526 + /* Enable the Millennium Plus ASIC */
23527 + tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
23529 + WriteDOC(tmp, virtadr, Mplus_DOCControl);
23530 + WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
23533 + ChipID = ReadDOC(virtadr, ChipID);
23535 + switch (ChipID) {
23536 + case DOC_ChipID_DocMilPlus16:
23537 + reg = DoC_Mplus_Toggle;
23539 + case DOC_ChipID_DocMilPlus32:
23540 + printk(KERN_ERR "DiskOnChip Millennium Plus 32MB is not supported, ignoring.\n");
23551 + /* Check the TOGGLE bit in the ECC register */
23552 + tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
23553 + tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
23554 + tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
23555 + if ((tmp == tmpb) || (tmp != tmpc)) {
23556 + printk(KERN_WARNING "Possible DiskOnChip at 0x%lx failed TOGGLE test, dropping.\n", physadr);
23561 + for (mtd = doclist; mtd; mtd = doc->nextdoc) {
23562 + unsigned char oldval;
23563 + unsigned char newval;
23564 + nand = mtd->priv;
23565 + doc = (void *)nand->priv;
23566 + /* Use the alias resolution register to determine if this is
23567 + in fact the same DOC aliased to a new address. If writes
23568 + to one chip's alias resolution register change the value on
23569 + the other chip, they're the same chip. */
23570 + if (ChipID == DOC_ChipID_DocMilPlus16) {
23571 + oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution);
23572 + newval = ReadDOC(virtadr, Mplus_AliasResolution);
23574 + oldval = ReadDOC(doc->virtadr, AliasResolution);
23575 + newval = ReadDOC(virtadr, AliasResolution);
23577 + if (oldval != newval)
23579 + if (ChipID == DOC_ChipID_DocMilPlus16) {
23580 + WriteDOC(~newval, virtadr, Mplus_AliasResolution);
23581 + oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution);
23582 + WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it
23584 + WriteDOC(~newval, virtadr, AliasResolution);
23585 + oldval = ReadDOC(doc->virtadr, AliasResolution);
23586 + WriteDOC(newval, virtadr, AliasResolution); // restore it
23588 + newval = ~newval;
23589 + if (oldval == newval) {
23590 + printk(KERN_DEBUG "Found alias of DOC at 0x%lx to 0x%lx\n", doc->physadr, physadr);
23595 + printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr);
23597 + len = sizeof(struct mtd_info) +
23598 + sizeof(struct nand_chip) +
23599 + sizeof(struct doc_priv) +
23600 + (2 * sizeof(struct nand_bbt_descr));
23601 + mtd = (struct mtd_info *) kmalloc(len, GFP_KERNEL);
23603 + printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
23607 + memset(mtd, 0, len);
23609 + nand = (struct nand_chip *) (mtd + 1);
23610 + doc = (struct doc_priv *) (nand + 1);
23611 + nand->bbt_td = (struct nand_bbt_descr *) (doc + 1);
23612 + nand->bbt_md = nand->bbt_td + 1;
23614 + mtd->priv = (void *) nand;
23615 + mtd->owner = THIS_MODULE;
23617 + nand->priv = (void *) doc;
23618 + nand->select_chip = doc200x_select_chip;
23619 + nand->hwcontrol = doc200x_hwcontrol;
23620 + nand->dev_ready = doc200x_dev_ready;
23621 + nand->waitfunc = doc200x_wait;
23622 + nand->block_bad = doc200x_block_bad;
23623 + nand->enable_hwecc = doc200x_enable_hwecc;
23624 + nand->calculate_ecc = doc200x_calculate_ecc;
23625 + nand->correct_data = doc200x_correct_data;
23627 + nand->autooob = &doc200x_oobinfo;
23628 + nand->eccmode = NAND_ECC_HW6_512;
23629 + nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME;
23631 + doc->physadr = physadr;
23632 + doc->virtadr = virtadr;
23633 + doc->ChipID = ChipID;
23634 + doc->curfloor = -1;
23635 + doc->curchip = -1;
23636 + doc->mh0_page = -1;
23637 + doc->mh1_page = -1;
23638 + doc->nextdoc = doclist;
23640 + if (ChipID == DOC_ChipID_Doc2k)
23641 + numchips = doc2000_init(mtd);
23642 + else if (ChipID == DOC_ChipID_DocMilPlus16)
23643 + numchips = doc2001plus_init(mtd);
23645 + numchips = doc2001_init(mtd);
23647 + if ((ret = nand_scan(mtd, numchips))) {
23648 + /* DBB note: i believe nand_release is necessary here, as
23649 + buffers may have been allocated in nand_base. Check with
23650 + Thomas. FIX ME! */
23651 + /* nand_release will call del_mtd_device, but we haven't yet
23652 + added it. This is handled without incident by
23653 + del_mtd_device, as far as I can tell. */
23654 + nand_release(mtd);
23664 + /* Put back the contents of the DOCControl register, in case it's not
23665 + actually a DiskOnChip. */
23666 + WriteDOC(save_control, virtadr, DOCControl);
23668 + iounmap((void *)virtadr);
23672 +int __init init_nanddoc(void)
23676 + if (doc_config_location) {
23677 + printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location);
23678 + return doc_probe(doc_config_location);
23680 + for (i=0; (doc_locations[i] != 0xffffffff); i++) {
23681 + doc_probe(doc_locations[i]);
23684 + /* No banner message any more. Print a message if no DiskOnChip
23685 + found, so the user knows we at least tried. */
23687 + printk(KERN_INFO "No valid DiskOnChip devices found\n");
23693 +void __exit cleanup_nanddoc(void)
23695 + struct mtd_info *mtd, *nextmtd;
23696 + struct nand_chip *nand;
23697 + struct doc_priv *doc;
23699 + for (mtd = doclist; mtd; mtd = nextmtd) {
23700 + nand = mtd->priv;
23701 + doc = (void *)nand->priv;
23703 + nextmtd = doc->nextdoc;
23704 + nand_release(mtd);
23705 + iounmap((void *)doc->virtadr);
23710 +module_init(init_nanddoc);
23711 +module_exit(cleanup_nanddoc);
23713 +MODULE_LICENSE("GPL");
23714 +MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
23715 +MODULE_DESCRIPTION("M-Systems DiskOnChip 2000, Millennium and Millennium Plus device driver\n");
23716 Index: linux-2.6.5/drivers/mtd/nand/edb7312.c
23717 ===================================================================
23718 --- linux-2.6.5.orig/drivers/mtd/nand/edb7312.c 2004-04-03 22:38:22.000000000 -0500
23719 +++ linux-2.6.5/drivers/mtd/nand/edb7312.c 2005-02-01 17:11:17.000000000 -0500
23721 * Derived from drivers/mtd/nand/autcpu12.c
23722 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
23724 - * $Id: edb7312.c,v 1.5 2003/04/20 07:24:40 gleixner Exp $
23725 + * $Id: edb7312.c,v 1.9 2004/09/16 23:27:14 gleixner Exp $
23727 * This program is free software; you can redistribute it and/or modify
23728 * it under the terms of the GNU General Public License version 2 as
23731 #include <linux/slab.h>
23732 #include <linux/module.h>
23733 +#include <linux/init.h>
23734 #include <linux/mtd/mtd.h>
23735 #include <linux/mtd/nand.h>
23736 #include <linux/mtd/partitions.h>
23741 -static int ep7312_fio_pbase = EP7312_FIO_PBASE;
23742 -static int ep7312_pxdr = EP7312_PXDR;
23743 -static int ep7312_pxddr = EP7312_PXDDR;
23744 +static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE;
23745 +static void __iomem * ep7312_pxdr = (void __iomem *) EP7312_PXDR;
23746 +static void __iomem * ep7312_pxddr = (void __iomem *) EP7312_PXDDR;
23749 MODULE_PARM(ep7312_fio_pbase, "i");
23752 * hardware specific access to control-lines
23754 -static void ep7312_hwcontrol(int cmd)
23755 +static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd)
23759 @@ -113,10 +114,13 @@
23761 * read device ready pin
23763 -static int ep7312_device_ready(void)
23764 +static int ep7312_device_ready(struct mtd_info *mtd)
23768 +#ifdef CONFIG_MTD_PARTITIONS
23769 +const char *part_probes[] = { "cmdlinepart", NULL };
23773 * Main initialization routine
23774 @@ -127,10 +131,10 @@
23775 const char *part_type = 0;
23776 int mtd_parts_nb = 0;
23777 struct mtd_partition *mtd_parts = 0;
23778 - int ep7312_fio_base;
23779 + void __iomem * ep7312_fio_base;
23781 /* Allocate memory for MTD device structure and private data */
23782 - ep7312_mtd = kmalloc(sizeof(struct mtd_info) +
23783 + ep7312_mtd = (struct mtd_info *) kmalloc(sizeof(struct mtd_info) +
23784 sizeof(struct nand_chip),
23787 @@ -139,7 +143,7 @@
23790 /* map physical adress */
23791 - ep7312_fio_base = (unsigned long)ioremap(ep7312_fio_pbase, SZ_1K);
23792 + ep7312_fio_base = (void __iomem *)ioremap(ep7312_fio_pbase, SZ_1K);
23793 if(!ep7312_fio_base) {
23794 printk("ioremap EDB7312 NAND flash failed\n");
23796 @@ -171,31 +175,22 @@
23797 this->chip_delay = 15;
23799 /* Scan to find existence of the device */
23800 - if (nand_scan (ep7312_mtd)) {
23801 + if (nand_scan (ep7312_mtd, 1)) {
23802 iounmap((void *)ep7312_fio_base);
23803 kfree (ep7312_mtd);
23807 - /* Allocate memory for internal data buffer */
23808 - this->data_buf = kmalloc (sizeof(u_char) * (ep7312_mtd->oobblock + ep7312_mtd->oobsize), GFP_KERNEL);
23809 - if (!this->data_buf) {
23810 - printk("Unable to allocate NAND data buffer for EDB7312.\n");
23811 - iounmap((void *)ep7312_fio_base);
23812 - kfree (ep7312_mtd);
23816 -#ifdef CONFIG_MTD_CMDLINE_PARTS
23817 - mtd_parts_nb = parse_cmdline_partitions(ep7312_mtd, &mtd_parts,
23819 +#ifdef CONFIG_MTD_PARTITIONS
23820 + ep7312_mtd->name = "edb7312-nand";
23821 + mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes,
23823 if (mtd_parts_nb > 0)
23824 - part_type = "command line";
23825 + part_type = "command line";
23827 - mtd_parts_nb = 0;
23828 + mtd_parts_nb = 0;
23830 - if (mtd_parts_nb == 0)
23832 + if (mtd_parts_nb == 0) {
23833 mtd_parts = partition_info;
23834 mtd_parts_nb = NUM_PARTITIONS;
23835 part_type = "static";
23836 @@ -217,8 +212,8 @@
23838 struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1];
23840 - /* Unregister the device */
23841 - del_mtd_device (ep7312_mtd);
23842 + /* Release resources, unregister device */
23843 + nand_release (ap7312_mtd);
23845 /* Free internal data buffer */
23846 kfree (this->data_buf);
23847 Index: linux-2.6.5/drivers/mtd/nand/h1910.c
23848 ===================================================================
23849 --- linux-2.6.5.orig/drivers/mtd/nand/h1910.c 1969-12-31 19:00:00.000000000 -0500
23850 +++ linux-2.6.5/drivers/mtd/nand/h1910.c 2005-02-01 17:11:17.000000000 -0500
23853 + * drivers/mtd/nand/h1910.c
23855 + * Copyright (C) 2003 Joshua Wise (joshua@joshuawise.com)
23857 + * Derived from drivers/mtd/nand/edb7312.c
23858 + * Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
23859 + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
23861 + * $Id: h1910.c,v 1.3 2004/09/16 23:27:14 gleixner Exp $
23863 + * This program is free software; you can redistribute it and/or modify
23864 + * it under the terms of the GNU General Public License version 2 as
23865 + * published by the Free Software Foundation.
23868 + * This is a device driver for the NAND flash device found on the
23869 + * iPAQ h1910 board which utilizes the Samsung K9F2808 part. This is
23870 + * a 128Mibit (16MiB x 8 bits) NAND flash device.
23873 +#include <linux/slab.h>
23874 +#include <linux/init.h>
23875 +#include <linux/module.h>
23876 +#include <linux/mtd/mtd.h>
23877 +#include <linux/mtd/nand.h>
23878 +#include <linux/mtd/partitions.h>
23879 +#include <asm/io.h>
23880 +#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
23881 +#include <asm/sizes.h>
23882 +#include <asm/arch/h1900-gpio.h>
23883 +#include <asm/arch/ipaq.h>
23886 + * MTD structure for EDB7312 board
23888 +static struct mtd_info *h1910_nand_mtd = NULL;
23894 +#ifdef CONFIG_MTD_PARTITIONS
23896 + * Define static partitions for flash device
23898 +static struct mtd_partition partition_info[] = {
23899 + { name: "h1910 NAND Flash",
23901 + size: 16*1024*1024 }
23903 +#define NUM_PARTITIONS 1
23909 + * hardware specific access to control-lines
23911 +static void h1910_hwcontrol(struct mtd_info *mtd, int cmd)
23913 + struct nand_chip* this = (struct nand_chip *) (mtd->priv);
23917 + case NAND_CTL_SETCLE:
23918 + this->IO_ADDR_R |= (1 << 2);
23919 + this->IO_ADDR_W |= (1 << 2);
23921 + case NAND_CTL_CLRCLE:
23922 + this->IO_ADDR_R &= ~(1 << 2);
23923 + this->IO_ADDR_W &= ~(1 << 2);
23926 + case NAND_CTL_SETALE:
23927 + this->IO_ADDR_R |= (1 << 3);
23928 + this->IO_ADDR_W |= (1 << 3);
23930 + case NAND_CTL_CLRALE:
23931 + this->IO_ADDR_R &= ~(1 << 3);
23932 + this->IO_ADDR_W &= ~(1 << 3);
23935 + case NAND_CTL_SETNCE:
23937 + case NAND_CTL_CLRNCE:
23943 + * read device ready pin
23946 +static int h1910_device_ready(struct mtd_info *mtd)
23948 + return (GPLR(55) & GPIO_bit(55));
23953 + * Main initialization routine
23955 +static int __init h1910_init (void)
23957 + struct nand_chip *this;
23958 + const char *part_type = 0;
23959 + int mtd_parts_nb = 0;
23960 + struct mtd_partition *mtd_parts = 0;
23961 + void __iomem *nandaddr;
23963 + if (!machine_is_h1900())
23966 + nandaddr = (void __iomem *)__ioremap(0x08000000, 0x1000, 0, 1);
23968 + printk("Failed to ioremap nand flash.\n");
23972 + /* Allocate memory for MTD device structure and private data */
23973 + h1910_nand_mtd = (struct mtd_info *) kmalloc(sizeof(struct mtd_info) +
23974 + sizeof(struct nand_chip),
23976 + if (!h1910_nand_mtd) {
23977 + printk("Unable to allocate h1910 NAND MTD device structure.\n");
23978 + iounmap ((void *) nandaddr);
23982 + /* Get pointer to private data */
23983 + this = (struct nand_chip *) (&h1910_nand_mtd[1]);
23985 + /* Initialize structures */
23986 + memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info));
23987 + memset((char *) this, 0, sizeof(struct nand_chip));
23989 + /* Link the private data with the MTD structure */
23990 + h1910_nand_mtd->priv = this;
23995 + GPSR(37) = GPIO_bit(37);
23997 + /* insert callbacks */
23998 + this->IO_ADDR_R = nandaddr;
23999 + this->IO_ADDR_W = nandaddr;
24000 + this->hwcontrol = h1910_hwcontrol;
24001 + this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */
24002 + /* 15 us command delay time */
24003 + this->chip_delay = 50;
24004 + this->eccmode = NAND_ECC_SOFT;
24005 + this->options = NAND_NO_AUTOINCR;
24007 + /* Scan to find existence of the device */
24008 + if (nand_scan (h1910_nand_mtd, 1)) {
24009 + printk(KERN_NOTICE "No NAND device - returning -ENXIO\n");
24010 + kfree (h1910_nand_mtd);
24011 + iounmap ((void *) nandaddr);
24015 +#ifdef CONFIG_MTD_CMDLINE_PARTS
24016 + mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts,
24018 + if (mtd_parts_nb > 0)
24019 + part_type = "command line";
24021 + mtd_parts_nb = 0;
24023 + if (mtd_parts_nb == 0)
24025 + mtd_parts = partition_info;
24026 + mtd_parts_nb = NUM_PARTITIONS;
24027 + part_type = "static";
24030 + /* Register the partitions */
24031 + printk(KERN_NOTICE "Using %s partition definition\n", part_type);
24032 + add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb);
24034 + /* Return happy */
24037 +module_init(h1910_init);
24040 + * Clean up routine
24042 +static void __exit h1910_cleanup (void)
24044 + struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1];
24046 + /* Release resources, unregister device */
24047 + nand_release (h1910_nand_mtd);
24049 + /* Release io resource */
24050 + iounmap ((void *) this->IO_ADDR_W);
24052 + /* Free the MTD device structure */
24053 + kfree (h1910_nand_mtd);
24055 +module_exit(h1910_cleanup);
24057 +MODULE_LICENSE("GPL");
24058 +MODULE_AUTHOR("Joshua Wise <joshua at joshuawise dot com>");
24059 +MODULE_DESCRIPTION("NAND flash driver for iPAQ h1910");
24060 Index: linux-2.6.5/drivers/mtd/nand/nand_base.c
24061 ===================================================================
24062 --- linux-2.6.5.orig/drivers/mtd/nand/nand_base.c 1969-12-31 19:00:00.000000000 -0500
24063 +++ linux-2.6.5/drivers/mtd/nand/nand_base.c 2005-02-01 17:11:17.000000000 -0500
24066 + * drivers/mtd/nand.c
24069 + * This is the generic MTD driver for NAND flash devices. It should be
24070 + * capable of working with almost all NAND chips currently available.
24071 + * Basic support for AG-AND chips is provided.
24073 + * Additional technical information is available on
24074 + * http://www.linux-mtd.infradead.org/tech/nand.html
24076 + * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
24077 + * 2002 Thomas Gleixner (tglx@linutronix.de)
24079 + * 02-08-2004 tglx: support for strange chips, which cannot auto increment
24080 + * pages on read / read_oob
24082 + * 03-17-2004 tglx: Check ready before auto increment check. Simon Bayes
24083 + * pointed this out, as he marked an auto increment capable chip
24084 + * as NOAUTOINCR in the board driver.
24085 + * Make reads over block boundaries work too
24087 + * 04-14-2004 tglx: first working version for 2k page size chips
24089 + * 05-19-2004 tglx: Basic support for Renesas AG-AND chips
24092 + * David Woodhouse for adding multichip support
24094 + * Aleph One Ltd. and Toby Churchill Ltd. for supporting the
24095 + * rework for 2K page size chips
24098 + * Enable cached programming for 2k page size chips
24099 + * Check, if mtd->ecctype should be set to MTD_ECC_HW
24100 + * if we have HW ecc support.
24101 + * The AG-AND chips have nice features for speed improvement,
24102 + * which are not supported yet. Read / program 4 pages in one go.
24104 + * $Id: nand_base.c,v 1.116 2004/08/30 18:00:45 gleixner Exp $
24106 + * This program is free software; you can redistribute it and/or modify
24107 + * it under the terms of the GNU General Public License version 2 as
24108 + * published by the Free Software Foundation.
24112 +#include <linux/delay.h>
24113 +#include <linux/errno.h>
24114 +#include <linux/sched.h>
24115 +#include <linux/slab.h>
24116 +#include <linux/types.h>
24117 +#include <linux/mtd/mtd.h>
24118 +#include <linux/mtd/nand.h>
24119 +#include <linux/mtd/nand_ecc.h>
24120 +#include <linux/mtd/compatmac.h>
24121 +#include <linux/interrupt.h>
24122 +#include <linux/bitops.h>
24123 +#include <asm/io.h>
24125 +#ifdef CONFIG_MTD_PARTITIONS
24126 +#include <linux/mtd/partitions.h>
24129 +/* Define default oob placement schemes for large and small page devices */
24130 +static struct nand_oobinfo nand_oob_8 = {
24131 + .useecc = MTD_NANDECC_AUTOPLACE,
24133 + .eccpos = {0, 1, 2},
24134 + .oobfree = { {3, 2}, {6, 2} }
24137 +static struct nand_oobinfo nand_oob_16 = {
24138 + .useecc = MTD_NANDECC_AUTOPLACE,
24140 + .eccpos = {0, 1, 2, 3, 6, 7},
24141 + .oobfree = { {8, 8} }
24144 +static struct nand_oobinfo nand_oob_64 = {
24145 + .useecc = MTD_NANDECC_AUTOPLACE,
24148 + 40, 41, 42, 43, 44, 45, 46, 47,
24149 + 48, 49, 50, 51, 52, 53, 54, 55,
24150 + 56, 57, 58, 59, 60, 61, 62, 63},
24151 + .oobfree = { {2, 38} }
24154 +/* This is used for padding purposes in nand_write_oob */
24155 +static u_char ffchars[] = {
24156 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
24157 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
24158 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
24159 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
24160 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
24161 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
24162 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
24163 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
24167 + * NAND low-level MTD interface functions
24169 +static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
24170 +static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
24171 +static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
24173 +static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
24174 +static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
24175 + size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
24176 +static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
24177 +static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf);
24178 +static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
24179 + size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
24180 +static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf);
24181 +static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
24182 + unsigned long count, loff_t to, size_t * retlen);
24183 +static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs,
24184 + unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
24185 +static int nand_erase (struct mtd_info *mtd, struct erase_info *instr);
24186 +static void nand_sync (struct mtd_info *mtd);
24188 +/* Some internal functions */
24189 +static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,
24190 + struct nand_oobinfo *oobsel, int mode);
24191 +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
24192 +static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
24193 + u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode);
24195 +#define nand_verify_pages(...) (0)
24198 +static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state);
24201 + * nand_release_chip - [GENERIC] release chip
24202 + * @mtd: MTD device structure
24204 + * Deselect, release chip lock and wake up anyone waiting on the device
24206 +static void nand_release_chip (struct mtd_info *mtd)
24208 + struct nand_chip *this = mtd->priv;
24210 + /* De-select the NAND device */
24211 + this->select_chip(mtd, -1);
24212 + /* Release the chip */
24213 + spin_lock_bh (&this->chip_lock);
24214 + this->state = FL_READY;
24215 + wake_up (&this->wq);
24216 + spin_unlock_bh (&this->chip_lock);
24220 + * nand_read_byte - [DEFAULT] read one byte from the chip
24221 + * @mtd: MTD device structure
24223 + * Default read function for 8bit buswith
24225 +static u_char nand_read_byte(struct mtd_info *mtd)
24227 + struct nand_chip *this = mtd->priv;
24228 + return readb(this->IO_ADDR_R);
24232 + * nand_write_byte - [DEFAULT] write one byte to the chip
24233 + * @mtd: MTD device structure
24234 + * @byte: pointer to data byte to write
24236 + * Default write function for 8it buswith
24238 +static void nand_write_byte(struct mtd_info *mtd, u_char byte)
24240 + struct nand_chip *this = mtd->priv;
24241 + writeb(byte, this->IO_ADDR_W);
24245 + * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
24246 + * @mtd: MTD device structure
24248 + * Default read function for 16bit buswith with
24249 + * endianess conversion
24251 +static u_char nand_read_byte16(struct mtd_info *mtd)
24253 + struct nand_chip *this = mtd->priv;
24254 + return (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
24258 + * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip
24259 + * @mtd: MTD device structure
24260 + * @byte: pointer to data byte to write
24262 + * Default write function for 16bit buswith with
24263 + * endianess conversion
24265 +static void nand_write_byte16(struct mtd_info *mtd, u_char byte)
24267 + struct nand_chip *this = mtd->priv;
24268 + writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
24272 + * nand_read_word - [DEFAULT] read one word from the chip
24273 + * @mtd: MTD device structure
24275 + * Default read function for 16bit buswith without
24276 + * endianess conversion
24278 +static u16 nand_read_word(struct mtd_info *mtd)
24280 + struct nand_chip *this = mtd->priv;
24281 + return readw(this->IO_ADDR_R);
24285 + * nand_write_word - [DEFAULT] write one word to the chip
24286 + * @mtd: MTD device structure
24287 + * @word: data word to write
24289 + * Default write function for 16bit buswith without
24290 + * endianess conversion
24292 +static void nand_write_word(struct mtd_info *mtd, u16 word)
24294 + struct nand_chip *this = mtd->priv;
24295 + writew(word, this->IO_ADDR_W);
24299 + * nand_select_chip - [DEFAULT] control CE line
24300 + * @mtd: MTD device structure
24301 + * @chip: chipnumber to select, -1 for deselect
24303 + * Default select function for 1 chip devices.
24305 +static void nand_select_chip(struct mtd_info *mtd, int chip)
24307 + struct nand_chip *this = mtd->priv;
24310 + this->hwcontrol(mtd, NAND_CTL_CLRNCE);
24313 + this->hwcontrol(mtd, NAND_CTL_SETNCE);
24322 + * nand_write_buf - [DEFAULT] write buffer to chip
24323 + * @mtd: MTD device structure
24324 + * @buf: data buffer
24325 + * @len: number of bytes to write
24327 + * Default write function for 8bit buswith
24329 +static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
24332 + struct nand_chip *this = mtd->priv;
24334 + for (i=0; i<len; i++)
24335 + writeb(buf[i], this->IO_ADDR_W);
24339 + * nand_read_buf - [DEFAULT] read chip data into buffer
24340 + * @mtd: MTD device structure
24341 + * @buf: buffer to store date
24342 + * @len: number of bytes to read
24344 + * Default read function for 8bit buswith
24346 +static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
24349 + struct nand_chip *this = mtd->priv;
24351 + for (i=0; i<len; i++)
24352 + buf[i] = readb(this->IO_ADDR_R);
24356 + * nand_verify_buf - [DEFAULT] Verify chip data against buffer
24357 + * @mtd: MTD device structure
24358 + * @buf: buffer containing the data to compare
24359 + * @len: number of bytes to compare
24361 + * Default verify function for 8bit buswith
24363 +static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
24366 + struct nand_chip *this = mtd->priv;
24368 + for (i=0; i<len; i++)
24369 + if (buf[i] != readb(this->IO_ADDR_R))
24376 + * nand_write_buf16 - [DEFAULT] write buffer to chip
24377 + * @mtd: MTD device structure
24378 + * @buf: data buffer
24379 + * @len: number of bytes to write
24381 + * Default write function for 16bit buswith
24383 +static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
24386 + struct nand_chip *this = mtd->priv;
24387 + u16 *p = (u16 *) buf;
24390 + for (i=0; i<len; i++)
24391 + writew(p[i], this->IO_ADDR_W);
24396 + * nand_read_buf16 - [DEFAULT] read chip data into buffer
24397 + * @mtd: MTD device structure
24398 + * @buf: buffer to store date
24399 + * @len: number of bytes to read
24401 + * Default read function for 16bit buswith
24403 +static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
24406 + struct nand_chip *this = mtd->priv;
24407 + u16 *p = (u16 *) buf;
24410 + for (i=0; i<len; i++)
24411 + p[i] = readw(this->IO_ADDR_R);
24415 + * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
24416 + * @mtd: MTD device structure
24417 + * @buf: buffer containing the data to compare
24418 + * @len: number of bytes to compare
24420 + * Default verify function for 16bit buswith
24422 +static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
24425 + struct nand_chip *this = mtd->priv;
24426 + u16 *p = (u16 *) buf;
24429 + for (i=0; i<len; i++)
24430 + if (p[i] != readw(this->IO_ADDR_R))
24437 + * nand_block_bad - [DEFAULT] Read bad block marker from the chip
24438 + * @mtd: MTD device structure
24439 + * @ofs: offset from device start
24440 + * @getchip: 0, if the chip is already selected
24442 + * Check, if the block is bad.
24444 +static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
24446 + int page, chipnr, res = 0;
24447 + struct nand_chip *this = mtd->priv;
24451 + page = (int)(ofs >> this->page_shift);
24452 + chipnr = (int)(ofs >> this->chip_shift);
24454 + /* Grab the lock and see if the device is available */
24455 + nand_get_chip (this, mtd, FL_READING);
24457 + /* Select the NAND device */
24458 + this->select_chip(mtd, chipnr);
24460 + page = (int) ofs;
24462 + if (this->options & NAND_BUSWIDTH_16) {
24463 + this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask);
24464 + bad = cpu_to_le16(this->read_word(mtd));
24465 + if (this->badblockpos & 0x1)
24467 + if ((bad & 0xFF) != 0xff)
24470 + this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask);
24471 + if (this->read_byte(mtd) != 0xff)
24476 + /* Deselect and wake up anyone waiting on the device */
24477 + nand_release_chip(mtd);
24484 + * nand_default_block_markbad - [DEFAULT] mark a block bad
24485 + * @mtd: MTD device structure
24486 + * @ofs: offset from device start
24488 + * This is the default implementation, which can be overridden by
24489 + * a hardware specific driver.
24491 +static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
24493 + struct nand_chip *this = mtd->priv;
24494 + u_char buf[2] = {0, 0};
24498 + /* Get block number */
24499 + block = ((int) ofs) >> this->bbt_erase_shift;
24500 + this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
24502 + /* Do we have a flash based bad block table ? */
24503 + if (this->options & NAND_USE_FLASH_BBT)
24504 + return nand_update_bbt (mtd, ofs);
24506 + /* We write two bytes, so we dont have to mess with 16 bit access */
24507 + ofs += mtd->oobsize + (this->badblockpos & ~0x01);
24508 + return nand_write_oob (mtd, ofs , 2, &retlen, buf);
24512 + * nand_check_wp - [GENERIC] check if the chip is write protected
24513 + * @mtd: MTD device structure
24514 + * Check, if the device is write protected
24516 + * The function expects, that the device is already selected
24518 +static int nand_check_wp (struct mtd_info *mtd)
24520 + struct nand_chip *this = mtd->priv;
24521 + /* Check the WP bit */
24522 + this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);
24523 + return (this->read_byte(mtd) & 0x80) ? 0 : 1;
24527 + * nand_block_checkbad - [GENERIC] Check if a block is marked bad
24528 + * @mtd: MTD device structure
24529 + * @ofs: offset from device start
24530 + * @getchip: 0, if the chip is already selected
24531 + * @allowbbt: 1, if its allowed to access the bbt area
24533 + * Check, if the block is bad. Either by reading the bad block table or
24534 + * calling of the scan function.
24536 +static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt)
24538 + struct nand_chip *this = mtd->priv;
24541 + return this->block_bad(mtd, ofs, getchip);
24543 + /* Return info from the table */
24544 + return nand_isbad_bbt (mtd, ofs, allowbbt);
24548 + * nand_command - [DEFAULT] Send command to NAND device
24549 + * @mtd: MTD device structure
24550 + * @command: the command to be sent
24551 + * @column: the column address for this command, -1 if none
24552 + * @page_addr: the page address for this command, -1 if none
24554 + * Send command to NAND device. This function is used for small page
24555 + * devices (256/512 Bytes per page)
24557 +static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
24559 + register struct nand_chip *this = mtd->priv;
24561 + /* Begin command latch cycle */
24562 + this->hwcontrol(mtd, NAND_CTL_SETCLE);
24564 + * Write out the command to the device.
24566 + if (command == NAND_CMD_SEQIN) {
24569 + if (column >= mtd->oobblock) {
24571 + column -= mtd->oobblock;
24572 + readcmd = NAND_CMD_READOOB;
24573 + } else if (column < 256) {
24574 + /* First 256 bytes --> READ0 */
24575 + readcmd = NAND_CMD_READ0;
24578 + readcmd = NAND_CMD_READ1;
24580 + this->write_byte(mtd, readcmd);
24582 + this->write_byte(mtd, command);
24584 + /* Set ALE and clear CLE to start address cycle */
24585 + this->hwcontrol(mtd, NAND_CTL_CLRCLE);
24587 + if (column != -1 || page_addr != -1) {
24588 + this->hwcontrol(mtd, NAND_CTL_SETALE);
24590 + /* Serially input address */
24591 + if (column != -1) {
24592 + /* Adjust columns for 16 bit buswidth */
24593 + if (this->options & NAND_BUSWIDTH_16)
24595 + this->write_byte(mtd, column);
24597 + if (page_addr != -1) {
24598 + this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
24599 + this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
24600 + /* One more address cycle for higher density devices */
24601 + if (this->chipsize & 0x0c000000)
24602 + this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));
24604 + /* Latch in address */
24605 + this->hwcontrol(mtd, NAND_CTL_CLRALE);
24609 + * program and erase have their own busy handlers
24610 + * status and sequential in needs no delay
24612 + switch (command) {
24614 + case NAND_CMD_PAGEPROG:
24615 + case NAND_CMD_ERASE1:
24616 + case NAND_CMD_ERASE2:
24617 + case NAND_CMD_SEQIN:
24618 + case NAND_CMD_STATUS:
24621 + case NAND_CMD_RESET:
24622 + if (this->dev_ready)
24624 + udelay(this->chip_delay);
24625 + this->hwcontrol(mtd, NAND_CTL_SETCLE);
24626 + this->write_byte(mtd, NAND_CMD_STATUS);
24627 + this->hwcontrol(mtd, NAND_CTL_CLRCLE);
24628 + while ( !(this->read_byte(mtd) & 0x40));
24631 + /* This applies to read commands */
24634 + * If we don't have access to the busy pin, we apply the given
24637 + if (!this->dev_ready) {
24638 + udelay (this->chip_delay);
24643 + /* Apply this short delay always to ensure that we do wait tWB in
24644 + * any case on any machine. */
24646 + /* wait until command is processed */
24647 + while (!this->dev_ready(mtd));
24651 + * nand_command_lp - [DEFAULT] Send command to NAND large page device
24652 + * @mtd: MTD device structure
24653 + * @command: the command to be sent
24654 + * @column: the column address for this command, -1 if none
24655 + * @page_addr: the page address for this command, -1 if none
24657 + * Send command to NAND device. This is the version for the new large page devices
24658 + * We dont have the seperate regions as we have in the small page devices.
24659 + * We must emulate NAND_CMD_READOOB to keep the code compatible.
24662 +static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, int page_addr)
24664 + register struct nand_chip *this = mtd->priv;
24666 + /* Emulate NAND_CMD_READOOB */
24667 + if (command == NAND_CMD_READOOB) {
24668 + column += mtd->oobblock;
24669 + command = NAND_CMD_READ0;
24673 + /* Begin command latch cycle */
24674 + this->hwcontrol(mtd, NAND_CTL_SETCLE);
24675 + /* Write out the command to the device. */
24676 + this->write_byte(mtd, command);
24677 + /* End command latch cycle */
24678 + this->hwcontrol(mtd, NAND_CTL_CLRCLE);
24680 + if (column != -1 || page_addr != -1) {
24681 + this->hwcontrol(mtd, NAND_CTL_SETALE);
24683 + /* Serially input address */
24684 + if (column != -1) {
24685 + /* Adjust columns for 16 bit buswidth */
24686 + if (this->options & NAND_BUSWIDTH_16)
24688 + this->write_byte(mtd, column & 0xff);
24689 + this->write_byte(mtd, column >> 8);
24691 + if (page_addr != -1) {
24692 + this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
24693 + this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
24694 + /* One more address cycle for devices > 128MiB */
24695 + if (this->chipsize > (128 << 20))
24696 + this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0xff));
24698 + /* Latch in address */
24699 + this->hwcontrol(mtd, NAND_CTL_CLRALE);
24703 + * program and erase have their own busy handlers
24704 + * status and sequential in needs no delay
24706 + switch (command) {
24708 + case NAND_CMD_CACHEDPROG:
24709 + case NAND_CMD_PAGEPROG:
24710 + case NAND_CMD_ERASE1:
24711 + case NAND_CMD_ERASE2:
24712 + case NAND_CMD_SEQIN:
24713 + case NAND_CMD_STATUS:
24717 + case NAND_CMD_RESET:
24718 + if (this->dev_ready)
24720 + udelay(this->chip_delay);
24721 + this->hwcontrol(mtd, NAND_CTL_SETCLE);
24722 + this->write_byte(mtd, NAND_CMD_STATUS);
24723 + this->hwcontrol(mtd, NAND_CTL_CLRCLE);
24724 + while ( !(this->read_byte(mtd) & 0x40));
24727 + case NAND_CMD_READ0:
24728 + /* Begin command latch cycle */
24729 + this->hwcontrol(mtd, NAND_CTL_SETCLE);
24730 + /* Write out the start read command */
24731 + this->write_byte(mtd, NAND_CMD_READSTART);
24732 + /* End command latch cycle */
24733 + this->hwcontrol(mtd, NAND_CTL_CLRCLE);
24734 + /* Fall through into ready check */
24736 + /* This applies to read commands */
24739 + * If we don't have access to the busy pin, we apply the given
24742 + if (!this->dev_ready) {
24743 + udelay (this->chip_delay);
24748 + /* Apply this short delay always to ensure that we do wait tWB in
24749 + * any case on any machine. */
24751 + /* wait until command is processed */
24752 + while (!this->dev_ready(mtd));
24756 + * nand_get_chip - [GENERIC] Get chip for selected access
24757 + * @this: the nand chip descriptor
24758 + * @mtd: MTD device structure
24759 + * @new_state: the state which is requested
24761 + * Get the device and lock it for exclusive access
24763 +static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state)
24766 + DECLARE_WAITQUEUE (wait, current);
24769 + * Grab the lock and see if the device is available
24772 + spin_lock_bh (&this->chip_lock);
24774 + if (this->state == FL_READY) {
24775 + this->state = new_state;
24776 + spin_unlock_bh (&this->chip_lock);
24780 + set_current_state (TASK_UNINTERRUPTIBLE);
24781 + add_wait_queue (&this->wq, &wait);
24782 + spin_unlock_bh (&this->chip_lock);
24784 + remove_wait_queue (&this->wq, &wait);
24789 + * nand_wait - [DEFAULT] wait until the command is done
24790 + * @mtd: MTD device structure
24791 + * @this: NAND chip structure
24792 + * @state: state to select the max. timeout value
24794 + * Wait for command done. This applies to erase and program only
24795 + * Erase can take up to 400ms and program up to 20ms according to
24796 + * general NAND and SmartMedia specs
24799 +static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
24802 + unsigned long timeo = jiffies;
24805 + if (state == FL_ERASING)
24806 + timeo += (HZ * 400) / 1000;
24808 + timeo += (HZ * 20) / 1000;
24810 + /* Apply this short delay always to ensure that we do wait tWB in
24811 + * any case on any machine. */
24814 + spin_lock_bh (&this->chip_lock);
24815 + if ((state == FL_ERASING) && (this->options & NAND_IS_AND))
24816 + this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1);
24818 + this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);
24820 + while (time_before(jiffies, timeo)) {
24821 + /* Check, if we were interrupted */
24822 + if (this->state != state) {
24823 + spin_unlock_bh (&this->chip_lock);
24826 + if (this->dev_ready) {
24827 + if (this->dev_ready(mtd))
24830 + if (this->read_byte(mtd) & NAND_STATUS_READY)
24833 + spin_unlock_bh (&this->chip_lock);
24835 + spin_lock_bh (&this->chip_lock);
24837 + status = (int) this->read_byte(mtd);
24838 + spin_unlock_bh (&this->chip_lock);
24844 + * nand_write_page - [GENERIC] write one page
24845 + * @mtd: MTD device structure
24846 + * @this: NAND chip structure
24847 + * @page: startpage inside the chip, must be called with (page & this->pagemask)
24848 + * @oob_buf: out of band data buffer
24849 + * @oobsel: out of band selecttion structre
24850 + * @cached: 1 = enable cached programming if supported by chip
24852 + * Nand_page_program function is used for write and writev !
24853 + * This function will always program a full page of data
24854 + * If you call it with a non page aligned buffer, you're lost :)
24856 + * Cached programming is not supported yet.
24858 +static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page,
24859 + u_char *oob_buf, struct nand_oobinfo *oobsel, int cached)
24862 + u_char ecc_code[8];
24863 + int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
24864 + int *oob_config = oobsel->eccpos;
24865 + int datidx = 0, eccidx = 0, eccsteps = this->eccsteps;
24866 + int eccbytes = 0;
24868 + /* FIXME: Enable cached programming */
24871 + /* Send command to begin auto page programming */
24872 + this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page);
24874 + /* Write out complete page of data, take care of eccmode */
24875 + switch (eccmode) {
24876 + /* No ecc, write all */
24877 + case NAND_ECC_NONE:
24878 + printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
24879 + this->write_buf(mtd, this->data_poi, mtd->oobblock);
24882 + /* Software ecc 3/256, write all */
24883 + case NAND_ECC_SOFT:
24884 + for (; eccsteps; eccsteps--) {
24885 + this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
24886 + for (i = 0; i < 3; i++, eccidx++)
24887 + oob_buf[oob_config[eccidx]] = ecc_code[i];
24888 + datidx += this->eccsize;
24890 + this->write_buf(mtd, this->data_poi, mtd->oobblock);
24893 + /* Hardware ecc 8 byte / 512 byte data */
24894 + case NAND_ECC_HW8_512:
24896 + /* Hardware ecc 6 byte / 512 byte data */
24897 + case NAND_ECC_HW6_512:
24899 + /* Hardware ecc 3 byte / 256 data */
24900 + /* Hardware ecc 3 byte / 512 byte data */
24901 + case NAND_ECC_HW3_256:
24902 + case NAND_ECC_HW3_512:
24904 + for (; eccsteps; eccsteps--) {
24905 + /* enable hardware ecc logic for write */
24906 + this->enable_hwecc(mtd, NAND_ECC_WRITE);
24907 + this->write_buf(mtd, &this->data_poi[datidx], this->eccsize);
24908 + this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
24909 + for (i = 0; i < eccbytes; i++, eccidx++)
24910 + oob_buf[oob_config[eccidx]] = ecc_code[i];
24911 + /* If the hardware ecc provides syndromes then
24912 + * the ecc code must be written immidiately after
24913 + * the data bytes (words) */
24914 + if (this->options & NAND_HWECC_SYNDROME)
24915 + this->write_buf(mtd, ecc_code, eccbytes);
24917 + datidx += this->eccsize;
24922 + printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
24926 + /* Write out OOB data */
24927 + if (this->options & NAND_HWECC_SYNDROME)
24928 + this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
24930 + this->write_buf(mtd, oob_buf, mtd->oobsize);
24932 + /* Send command to actually program the data */
24933 + this->cmdfunc (mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
24936 + /* call wait ready function */
24937 + status = this->waitfunc (mtd, this, FL_WRITING);
24938 + /* See if device thinks it succeeded */
24939 + if (status & 0x01) {
24940 + DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
24944 + /* FIXME: Implement cached programming ! */
24945 + /* wait until cache is ready*/
24946 + // status = this->waitfunc (mtd, this, FL_CACHEDRPG);
24951 +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
24953 + * nand_verify_pages - [GENERIC] verify the chip contents after a write
24954 + * @mtd: MTD device structure
24955 + * @this: NAND chip structure
24956 + * @page: startpage inside the chip, must be called with (page & this->pagemask)
24957 + * @numpages: number of pages to verify
24958 + * @oob_buf: out of band data buffer
24959 + * @oobsel: out of band selecttion structre
24960 + * @chipnr: number of the current chip
24961 + * @oobmode: 1 = full buffer verify, 0 = ecc only
24963 + * The NAND device assumes that it is always writing to a cleanly erased page.
24964 + * Hence, it performs its internal write verification only on bits that
24965 + * transitioned from 1 to 0. The device does NOT verify the whole page on a
24966 + * byte by byte basis. It is possible that the page was not completely erased
24967 + * or the page is becoming unusable due to wear. The read with ECC would catch
24968 + * the error later when the ECC page check fails, but we would rather catch
24969 + * it early in the page write stage. Better to write no data than invalid data.
24971 +static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
24972 + u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
24974 + int i, j, datidx = 0, oobofs = 0, res = -EIO;
24975 + int eccsteps = this->eccsteps;
24977 + u_char oobdata[64];
24979 + hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
24981 + /* Send command to read back the first page */
24982 + this->cmdfunc (mtd, NAND_CMD_READ0, 0, page);
24985 + for (j = 0; j < eccsteps; j++) {
24986 + /* Loop through and verify the data */
24987 + if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) {
24988 + DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
24991 + datidx += mtd->eccsize;
24992 + /* Have we a hw generator layout ? */
24995 + if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) {
24996 + DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
24999 + oobofs += hweccbytes;
25002 + /* check, if we must compare all data or if we just have to
25003 + * compare the ecc bytes
25006 + if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) {
25007 + DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
25011 + /* Read always, else autoincrement fails */
25012 + this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
25014 + if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
25015 + int ecccnt = oobsel->eccbytes;
25017 + for (i = 0; i < ecccnt; i++) {
25018 + int idx = oobsel->eccpos[i];
25019 + if (oobdata[idx] != oob_buf[oobofs + idx] ) {
25020 + DEBUG (MTD_DEBUG_LEVEL0,
25021 + "%s: Failed ECC write "
25022 + "verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i);
25028 + oobofs += mtd->oobsize - hweccbytes * eccsteps;
25032 + /* Apply delay or wait for ready/busy pin
25033 + * Do this before the AUTOINCR check, so no problems
25034 + * arise if a chip which does auto increment
25035 + * is marked as NOAUTOINCR by the board driver.
25036 + * Do this also before returning, so the chip is
25037 + * ready for the next command.
25039 + if (!this->dev_ready)
25040 + udelay (this->chip_delay);
25042 + while (!this->dev_ready(mtd));
25044 + /* All done, return happy */
25049 + /* Check, if the chip supports auto page increment */
25050 + if (!NAND_CANAUTOINCR(this))
25051 + this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
25054 + * Terminate the read command. We come here in case of an error
25055 + * So we must issue a reset command.
25058 + this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1);
25064 + * nand_read - [MTD Interface] MTD compability function for nand_read_ecc
25065 + * @mtd: MTD device structure
25066 + * @from: offset to read from
25067 + * @len: number of bytes to read
25068 + * @retlen: pointer to variable to store the number of read bytes
25069 + * @buf: the databuffer to put data
25071 + * This function simply calls nand_read_ecc with oob buffer and oobsel = NULL
25073 +static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
25075 + return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL);
25080 + * nand_read_ecc - [MTD Interface] Read data with ECC
25081 + * @mtd: MTD device structure
25082 + * @from: offset to read from
25083 + * @len: number of bytes to read
25084 + * @retlen: pointer to variable to store the number of read bytes
25085 + * @buf: the databuffer to put data
25086 + * @oob_buf: filesystem supplied oob data buffer
25087 + * @oobsel: oob selection structure
25089 + * NAND read with ECC
25091 +static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
25092 + size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel)
25094 + int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
25095 + int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
25096 + struct nand_chip *this = mtd->priv;
25097 + u_char *data_poi, *oob_data = oob_buf;
25098 + u_char ecc_calc[32];
25099 + u_char ecc_code[32];
25100 + int eccmode, eccsteps;
25101 + int *oob_config, datidx;
25102 + int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
25103 + int eccbytes = 3;
25104 + int compareecc = 1;
25108 + DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
25110 + /* Do not allow reads past end of device */
25111 + if ((from + len) > mtd->size) {
25112 + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
25117 + /* Grab the lock and see if the device is available */
25118 + nand_get_chip (this, mtd ,FL_READING);
25120 + /* use userspace supplied oobinfo, if zero */
25121 + if (oobsel == NULL)
25122 + oobsel = &mtd->oobinfo;
25124 + /* Autoplace of oob data ? Use the default placement scheme */
25125 + if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
25126 + oobsel = this->autooob;
25128 + eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
25129 + oob_config = oobsel->eccpos;
25131 + /* Select the NAND device */
25132 + chipnr = (int)(from >> this->chip_shift);
25133 + this->select_chip(mtd, chipnr);
25135 + /* First we calculate the starting page */
25136 + realpage = (int) (from >> this->page_shift);
25137 + page = realpage & this->pagemask;
25139 + /* Get raw starting column */
25140 + col = from & (mtd->oobblock - 1);
25142 + end = mtd->oobblock;
25143 + ecc = this->eccsize;
25144 + switch (eccmode) {
25145 + case NAND_ECC_HW6_512: /* Hardware ECC 6 byte / 512 byte data */
25148 + case NAND_ECC_HW8_512: /* Hardware ECC 8 byte / 512 byte data */
25151 + case NAND_ECC_NONE:
25156 + if (this->options & NAND_HWECC_SYNDROME)
25159 + oobreadlen = mtd->oobsize;
25160 + if (this->options & NAND_HWECC_SYNDROME)
25161 + oobreadlen -= oobsel->eccbytes;
25163 + /* Loop until all data read */
25164 + while (read < len) {
25166 + int aligned = (!col && (len - read) >= end);
25168 + * If the read is not page aligned, we have to read into data buffer
25169 + * due to ecc, else we read into return buffer direct
25172 + data_poi = &buf[read];
25174 + data_poi = this->data_buf;
25176 + /* Check, if we have this page in the buffer
25178 + * FIXME: Make it work when we must provide oob data too,
25179 + * check the usage of data_buf oob field
25181 + if (realpage == this->pagebuf && !oob_buf) {
25182 + /* aligned read ? */
25184 + memcpy (data_poi, this->data_buf, end);
25188 + /* Check, if we must send the read command */
25190 + this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
25194 + /* get oob area, if we have no oob buffer from fs-driver */
25195 + if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE)
25196 + oob_data = &this->data_buf[end];
25198 + eccsteps = this->eccsteps;
25200 + switch (eccmode) {
25201 + case NAND_ECC_NONE: { /* No ECC, Read in a page */
25202 + static unsigned long lastwhinge = 0;
25203 + if ((lastwhinge / HZ) != (jiffies / HZ)) {
25204 + printk (KERN_WARNING "Reading data from NAND FLASH without ECC is not recommended\n");
25205 + lastwhinge = jiffies;
25207 + this->read_buf(mtd, data_poi, end);
25211 + case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */
25212 + this->read_buf(mtd, data_poi, end);
25213 + for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc)
25214 + this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
25217 + case NAND_ECC_HW3_256: /* Hardware ECC 3 byte /256 byte data */
25218 + case NAND_ECC_HW3_512: /* Hardware ECC 3 byte /512 byte data */
25219 + case NAND_ECC_HW6_512: /* Hardware ECC 6 byte / 512 byte data */
25220 + case NAND_ECC_HW8_512: /* Hardware ECC 8 byte / 512 byte data */
25221 + for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) {
25222 + this->enable_hwecc(mtd, NAND_ECC_READ);
25223 + this->read_buf(mtd, &data_poi[datidx], ecc);
25225 + /* HW ecc with syndrome calculation must read the
25226 + * syndrome from flash immidiately after the data */
25227 + if (!compareecc) {
25228 + /* Some hw ecc generators need to know when the
25229 + * syndrome is read from flash */
25230 + this->enable_hwecc(mtd, NAND_ECC_READSYN);
25231 + this->read_buf(mtd, &oob_data[i], eccbytes);
25232 + /* We calc error correction directly, it checks the hw
25233 + * generator for an error, reads back the syndrome and
25234 + * does the error correction on the fly */
25235 + if (this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]) == -1) {
25236 + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: "
25237 + "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
25241 + this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
25247 + printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
25251 + /* read oobdata */
25252 + this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
25254 + /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
25258 + /* Pick the ECC bytes out of the oob data */
25259 + for (j = 0; j < oobsel->eccbytes; j++)
25260 + ecc_code[j] = oob_data[oob_config[j]];
25262 + /* correct data, if neccecary */
25263 + for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) {
25264 + ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
25266 + /* Get next chunk of ecc bytes */
25269 + /* Check, if we have a fs supplied oob-buffer,
25270 + * This is the legacy mode. Used by YAFFS1
25271 + * Should go away some day
25273 + if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {
25274 + int *p = (int *)(&oob_data[mtd->oobsize]);
25275 + p[i] = ecc_status;
25278 + if (ecc_status == -1) {
25279 + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);
25285 + /* check, if we have a fs supplied oob-buffer */
25287 + /* without autoplace. Legacy mode used by YAFFS1 */
25288 + switch(oobsel->useecc) {
25289 + case MTD_NANDECC_AUTOPLACE:
25290 + /* Walk through the autoplace chunks */
25291 + for (i = 0, j = 0; j < mtd->oobavail; i++) {
25292 + int from = oobsel->oobfree[i][0];
25293 + int num = oobsel->oobfree[i][1];
25294 + memcpy(&oob_buf[oob], &oob_data[from], num);
25297 + oob += mtd->oobavail;
25299 + case MTD_NANDECC_PLACE:
25300 + /* YAFFS1 legacy mode */
25301 + oob_data += this->eccsteps * sizeof (int);
25303 + oob_data += mtd->oobsize;
25307 + /* Partial page read, transfer data into fs buffer */
25309 + for (j = col; j < end && read < len; j++)
25310 + buf[read++] = data_poi[j];
25311 + this->pagebuf = realpage;
25313 + read += mtd->oobblock;
25315 + /* Apply delay or wait for ready/busy pin
25316 + * Do this before the AUTOINCR check, so no problems
25317 + * arise if a chip which does auto increment
25318 + * is marked as NOAUTOINCR by the board driver.
25320 + if (!this->dev_ready)
25321 + udelay (this->chip_delay);
25323 + while (!this->dev_ready(mtd));
25328 + /* For subsequent reads align to page boundary. */
25330 + /* Increment page address */
25333 + page = realpage & this->pagemask;
25334 + /* Check, if we cross a chip boundary */
25337 + this->select_chip(mtd, -1);
25338 + this->select_chip(mtd, chipnr);
25340 + /* Check, if the chip supports auto page increment
25341 + * or if we have hit a block boundary.
25343 + if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
25347 + /* Deselect and wake up anyone waiting on the device */
25348 + nand_release_chip(mtd);
25351 + * Return success, if no ECC failures, else -EBADMSG
25352 + * fs driver will take care of that, because
25353 + * retlen == desired len and result == -EBADMSG
25356 + return ecc_failed ? -EBADMSG : 0;
25360 + * nand_read_oob - [MTD Interface] NAND read out-of-band
25361 + * @mtd: MTD device structure
25362 + * @from: offset to read from
25363 + * @len: number of bytes to read
25364 + * @retlen: pointer to variable to store the number of read bytes
25365 + * @buf: the databuffer to put data
25367 + * NAND read out-of-band data from the spare area
25369 +static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
25371 + int i, col, page, chipnr;
25372 + struct nand_chip *this = mtd->priv;
25373 + int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
25375 + DEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
25377 + /* Shift to get page */
25378 + page = (int)(from >> this->page_shift);
25379 + chipnr = (int)(from >> this->chip_shift);
25381 + /* Mask to get column */
25382 + col = from & (mtd->oobsize - 1);
25384 + /* Initialize return length value */
25387 + /* Do not allow reads past end of device */
25388 + if ((from + len) > mtd->size) {
25389 + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n");
25394 + /* Grab the lock and see if the device is available */
25395 + nand_get_chip (this, mtd , FL_READING);
25397 + /* Select the NAND device */
25398 + this->select_chip(mtd, chipnr);
25400 + /* Send the read command */
25401 + this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask);
25403 + * Read the data, if we read more than one page
25404 + * oob data, let the device transfer the data !
25407 + while (i < len) {
25408 + int thislen = mtd->oobsize - col;
25409 + thislen = min_t(int, thislen, len);
25410 + this->read_buf(mtd, &buf[i], thislen);
25413 + /* Apply delay or wait for ready/busy pin
25414 + * Do this before the AUTOINCR check, so no problems
25415 + * arise if a chip which does auto increment
25416 + * is marked as NOAUTOINCR by the board driver.
25418 + if (!this->dev_ready)
25419 + udelay (this->chip_delay);
25421 + while (!this->dev_ready(mtd));
25423 + /* Read more ? */
25428 + /* Check, if we cross a chip boundary */
25429 + if (!(page & this->pagemask)) {
25431 + this->select_chip(mtd, -1);
25432 + this->select_chip(mtd, chipnr);
25435 + /* Check, if the chip supports auto page increment
25436 + * or if we have hit a block boundary.
25438 + if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) {
25439 + /* For subsequent page reads set offset to 0 */
25440 + this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);
25445 + /* Deselect and wake up anyone waiting on the device */
25446 + nand_release_chip(mtd);
25448 + /* Return happy */
25454 + * nand_read_raw - [GENERIC] Read raw data including oob into buffer
25455 + * @mtd: MTD device structure
25456 + * @buf: temporary buffer
25457 + * @from: offset to read from
25458 + * @len: number of bytes to read
25459 + * @ooblen: number of oob data bytes to read
25461 + * Read raw data including oob into buffer
25463 +int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen)
25465 + struct nand_chip *this = mtd->priv;
25466 + int page = (int) (from >> this->page_shift);
25467 + int chip = (int) (from >> this->chip_shift);
25470 + int pagesize = mtd->oobblock + mtd->oobsize;
25471 + int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
25473 + /* Do not allow reads past end of device */
25474 + if ((from + len) > mtd->size) {
25475 + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt read beyond end of device\n");
25479 + /* Grab the lock and see if the device is available */
25480 + nand_get_chip (this, mtd , FL_READING);
25482 + this->select_chip (mtd, chip);
25484 + /* Add requested oob length */
25489 + this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask);
25492 + this->read_buf (mtd, &buf[cnt], pagesize);
25498 + if (!this->dev_ready)
25499 + udelay (this->chip_delay);
25501 + while (!this->dev_ready(mtd));
25503 + /* Check, if the chip supports auto page increment */
25504 + if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
25508 + /* Deselect and wake up anyone waiting on the device */
25509 + nand_release_chip(mtd);
25515 + * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
25516 + * @mtd: MTD device structure
25517 + * @fsbuf: buffer given by fs driver
25518 + * @oobsel: out of band selection structre
25519 + * @autoplace: 1 = place given buffer into the oob bytes
25520 + * @numpages: number of pages to prepare
25523 + * 1. Filesystem buffer available and autoplacement is off,
25524 + * return filesystem buffer
25525 + * 2. No filesystem buffer or autoplace is off, return internal
25527 + * 3. Filesystem buffer is given and autoplace selected
25528 + * put data from fs buffer into internal buffer and
25529 + * retrun internal buffer
25531 + * Note: The internal buffer is filled with 0xff. This must
25532 + * be done only once, when no autoplacement happens
25533 + * Autoplacement sets the buffer dirty flag, which
25534 + * forces the 0xff fill before using the buffer again.
25537 +static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct nand_oobinfo *oobsel,
25538 + int autoplace, int numpages)
25540 + struct nand_chip *this = mtd->priv;
25543 + /* Zero copy fs supplied buffer */
25544 + if (fsbuf && !autoplace)
25547 + /* Check, if the buffer must be filled with ff again */
25548 + if (this->oobdirty) {
25549 + memset (this->oob_buf, 0xff,
25550 + mtd->oobsize << (this->phys_erase_shift - this->page_shift));
25551 + this->oobdirty = 0;
25554 + /* If we have no autoplacement or no fs buffer use the internal one */
25555 + if (!autoplace || !fsbuf)
25556 + return this->oob_buf;
25558 + /* Walk through the pages and place the data */
25559 + this->oobdirty = 1;
25561 + while (numpages--) {
25562 + for (i = 0, len = 0; len < mtd->oobavail; i++) {
25563 + int to = ofs + oobsel->oobfree[i][0];
25564 + int num = oobsel->oobfree[i][1];
25565 + memcpy (&this->oob_buf[to], fsbuf, num);
25569 + ofs += mtd->oobavail;
25571 + return this->oob_buf;
25574 +#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0
25577 + * nand_write - [MTD Interface] compability function for nand_write_ecc
25578 + * @mtd: MTD device structure
25579 + * @to: offset to write to
25580 + * @len: number of bytes to write
25581 + * @retlen: pointer to variable to store the number of written bytes
25582 + * @buf: the data to write
25584 + * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
25587 +static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
25589 + return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL));
25593 + * nand_write_ecc - [MTD Interface] NAND write with ECC
25594 + * @mtd: MTD device structure
25595 + * @to: offset to write to
25596 + * @len: number of bytes to write
25597 + * @retlen: pointer to variable to store the number of written bytes
25598 + * @buf: the data to write
25599 + * @eccbuf: filesystem supplied oob data buffer
25600 + * @oobsel: oob selection structure
25602 + * NAND write with ECC
25604 +static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
25605 + size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel)
25607 + int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
25608 + int autoplace = 0, numpages, totalpages;
25609 + struct nand_chip *this = mtd->priv;
25610 + u_char *oobbuf, *bufstart;
25611 + int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
25613 + DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
25615 + /* Initialize retlen, in case of early exit */
25618 + /* Do not allow write past end of device */
25619 + if ((to + len) > mtd->size) {
25620 + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n");
25624 + /* reject writes, which are not page aligned */
25625 + if (NOTALIGNED (to) || NOTALIGNED(len)) {
25626 + printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
25630 + /* Grab the lock and see if the device is available */
25631 + nand_get_chip (this, mtd, FL_WRITING);
25633 + /* Calculate chipnr */
25634 + chipnr = (int)(to >> this->chip_shift);
25635 + /* Select the NAND device */
25636 + this->select_chip(mtd, chipnr);
25638 + /* Check, if it is write protected */
25639 + if (nand_check_wp(mtd))
25642 + /* if oobsel is NULL, use chip defaults */
25643 + if (oobsel == NULL)
25644 + oobsel = &mtd->oobinfo;
25646 + /* Autoplace of oob data ? Use the default placement scheme */
25647 + if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
25648 + oobsel = this->autooob;
25652 + /* Setup variables and oob buffer */
25653 + totalpages = len >> this->page_shift;
25654 + page = (int) (to >> this->page_shift);
25655 + /* Invalidate the page cache, if we write to the cached page */
25656 + if (page <= this->pagebuf && this->pagebuf < (page + totalpages))
25657 + this->pagebuf = -1;
25659 + /* Set it relative to chip */
25660 + page &= this->pagemask;
25661 + startpage = page;
25662 + /* Calc number of pages we can write in one go */
25663 + numpages = min (ppblock - (startpage & (ppblock - 1)), totalpages);
25664 + oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, autoplace, numpages);
25665 + bufstart = (u_char *)buf;
25667 + /* Loop until all data is written */
25668 + while (written < len) {
25670 + this->data_poi = (u_char*) &buf[written];
25671 + /* Write one page. If this is the last page to write
25672 + * or the last page in this block, then use the
25673 + * real pageprogram command, else select cached programming
25674 + * if supported by the chip.
25676 + ret = nand_write_page (mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
25678 + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret);
25681 + /* Next oob page */
25682 + oob += mtd->oobsize;
25683 + /* Update written bytes count */
25684 + written += mtd->oobblock;
25685 + if (written == len)
25688 + /* Increment page address */
25691 + /* Have we hit a block boundary ? Then we have to verify and
25692 + * if verify is ok, we have to setup the oob buffer for
25693 + * the next pages.
25695 + if (!(page & (ppblock - 1))){
25697 + this->data_poi = bufstart;
25698 + ret = nand_verify_pages (mtd, this, startpage,
25699 + page - startpage,
25700 + oobbuf, oobsel, chipnr, (eccbuf != NULL));
25702 + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
25705 + *retlen = written;
25707 + ofs = autoplace ? mtd->oobavail : mtd->oobsize;
25709 + eccbuf += (page - startpage) * ofs;
25710 + totalpages -= page - startpage;
25711 + numpages = min (totalpages, ppblock);
25712 + page &= this->pagemask;
25713 + startpage = page;
25714 + oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel,
25715 + autoplace, numpages);
25716 + /* Check, if we cross a chip boundary */
25719 + this->select_chip(mtd, -1);
25720 + this->select_chip(mtd, chipnr);
25724 + /* Verify the remaining pages */
25726 + this->data_poi = bufstart;
25727 + ret = nand_verify_pages (mtd, this, startpage, totalpages,
25728 + oobbuf, oobsel, chipnr, (eccbuf != NULL));
25730 + *retlen = written;
25732 + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
25735 + /* Deselect and wake up anyone waiting on the device */
25736 + nand_release_chip(mtd);
25743 + * nand_write_oob - [MTD Interface] NAND write out-of-band
25744 + * @mtd: MTD device structure
25745 + * @to: offset to write to
25746 + * @len: number of bytes to write
25747 + * @retlen: pointer to variable to store the number of written bytes
25748 + * @buf: the data to write
25750 + * NAND write out-of-band
25752 +static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
25754 + int column, page, status, ret = -EIO, chipnr;
25755 + struct nand_chip *this = mtd->priv;
25757 + DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
25759 + /* Shift to get page */
25760 + page = (int) (to >> this->page_shift);
25761 + chipnr = (int) (to >> this->chip_shift);
25763 + /* Mask to get column */
25764 + column = to & (mtd->oobsize - 1);
25766 + /* Initialize return length value */
25769 + /* Do not allow write past end of page */
25770 + if ((column + len) > mtd->oobsize) {
25771 + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
25775 + /* Grab the lock and see if the device is available */
25776 + nand_get_chip (this, mtd, FL_WRITING);
25778 + /* Select the NAND device */
25779 + this->select_chip(mtd, chipnr);
25781 + /* Reset the chip. Some chips (like the Toshiba TC5832DC found
25782 + in one of my DiskOnChip 2000 test units) will clear the whole
25783 + data page too if we don't do this. I have no clue why, but
25784 + I seem to have 'fixed' it in the doc2000 driver in
25785 + August 1999. dwmw2. */
25786 + this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
25788 + /* Check, if it is write protected */
25789 + if (nand_check_wp(mtd))
25792 + /* Invalidate the page cache, if we write to the cached page */
25793 + if (page == this->pagebuf)
25794 + this->pagebuf = -1;
25796 + if (NAND_MUST_PAD(this)) {
25797 + /* Write out desired data */
25798 + this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page & this->pagemask);
25799 + /* prepad 0xff for partial programming */
25800 + this->write_buf(mtd, ffchars, column);
25802 + this->write_buf(mtd, buf, len);
25803 + /* postpad 0xff for partial programming */
25804 + this->write_buf(mtd, ffchars, mtd->oobsize - (len+column));
25806 + /* Write out desired data */
25807 + this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock + column, page & this->pagemask);
25809 + this->write_buf(mtd, buf, len);
25811 + /* Send command to program the OOB data */
25812 + this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1);
25814 + status = this->waitfunc (mtd, this, FL_WRITING);
25816 + /* See if device thinks it succeeded */
25817 + if (status & 0x01) {
25818 + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
25822 + /* Return happy */
25825 +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
25826 + /* Send command to read back the data */
25827 + this->cmdfunc (mtd, NAND_CMD_READOOB, column, page & this->pagemask);
25829 + if (this->verify_buf(mtd, buf, len)) {
25830 + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page);
25837 + /* Deselect and wake up anyone waiting on the device */
25838 + nand_release_chip(mtd);
25845 + * nand_writev - [MTD Interface] compabilty function for nand_writev_ecc
25846 + * @mtd: MTD device structure
25847 + * @vecs: the iovectors to write
25848 + * @count: number of vectors
25849 + * @to: offset to write to
25850 + * @retlen: pointer to variable to store the number of written bytes
25852 + * NAND write with kvec. This just calls the ecc function
25854 +static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
25855 + loff_t to, size_t * retlen)
25857 + return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL));
25861 + * nand_writev_ecc - [MTD Interface] write with iovec with ecc
25862 + * @mtd: MTD device structure
25863 + * @vecs: the iovectors to write
25864 + * @count: number of vectors
25865 + * @to: offset to write to
25866 + * @retlen: pointer to variable to store the number of written bytes
25867 + * @eccbuf: filesystem supplied oob data buffer
25868 + * @oobsel: oob selection structure
25870 + * NAND write with iovec with ecc
25872 +static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
25873 + loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel)
25875 + int i, page, len, total_len, ret = -EIO, written = 0, chipnr;
25876 + int oob, numpages, autoplace = 0, startpage;
25877 + struct nand_chip *this = mtd->priv;
25878 + int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
25879 + u_char *oobbuf, *bufstart;
25881 + /* Preset written len for early exit */
25884 + /* Calculate total length of data */
25886 + for (i = 0; i < count; i++)
25887 + total_len += (int) vecs[i].iov_len;
25889 + DEBUG (MTD_DEBUG_LEVEL3,
25890 + "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count);
25892 + /* Do not allow write past end of page */
25893 + if ((to + total_len) > mtd->size) {
25894 + DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n");
25898 + /* reject writes, which are not page aligned */
25899 + if (NOTALIGNED (to) || NOTALIGNED(total_len)) {
25900 + printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
25904 + /* Grab the lock and see if the device is available */
25905 + nand_get_chip (this, mtd, FL_WRITING);
25907 + /* Get the current chip-nr */
25908 + chipnr = (int) (to >> this->chip_shift);
25909 + /* Select the NAND device */
25910 + this->select_chip(mtd, chipnr);
25912 + /* Check, if it is write protected */
25913 + if (nand_check_wp(mtd))
25916 + /* if oobsel is NULL, use chip defaults */
25917 + if (oobsel == NULL)
25918 + oobsel = &mtd->oobinfo;
25920 + /* Autoplace of oob data ? Use the default placement scheme */
25921 + if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
25922 + oobsel = this->autooob;
25926 + /* Setup start page */
25927 + page = (int) (to >> this->page_shift);
25928 + /* Invalidate the page cache, if we write to the cached page */
25929 + if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift))
25930 + this->pagebuf = -1;
25932 + startpage = page & this->pagemask;
25934 + /* Loop until all kvec' data has been written */
25937 + /* If the given tuple is >= pagesize then
25938 + * write it out from the iov
25940 + if ((vecs->iov_len - len) >= mtd->oobblock) {
25941 + /* Calc number of pages we can write
25942 + * out of this iov in one go */
25943 + numpages = (vecs->iov_len - len) >> this->page_shift;
25944 + /* Do not cross block boundaries */
25945 + numpages = min (ppblock - (startpage & (ppblock - 1)), numpages);
25946 + oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);
25947 + bufstart = (u_char *)vecs->iov_base;
25949 + this->data_poi = bufstart;
25951 + for (i = 1; i <= numpages; i++) {
25952 + /* Write one page. If this is the last page to write
25953 + * then use the real pageprogram command, else select
25954 + * cached programming if supported by the chip.
25956 + ret = nand_write_page (mtd, this, page & this->pagemask,
25957 + &oobbuf[oob], oobsel, i != numpages);
25960 + this->data_poi += mtd->oobblock;
25961 + len += mtd->oobblock;
25962 + oob += mtd->oobsize;
25965 + /* Check, if we have to switch to the next tuple */
25966 + if (len >= (int) vecs->iov_len) {
25972 + /* We must use the internal buffer, read data out of each
25973 + * tuple until we have a full page to write
25976 + while (cnt < mtd->oobblock) {
25977 + if (vecs->iov_base != NULL && vecs->iov_len)
25978 + this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++];
25979 + /* Check, if we have to switch to the next tuple */
25980 + if (len >= (int) vecs->iov_len) {
25986 + this->pagebuf = page;
25987 + this->data_poi = this->data_buf;
25988 + bufstart = this->data_poi;
25990 + oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);
25991 + ret = nand_write_page (mtd, this, page & this->pagemask,
25992 + oobbuf, oobsel, 0);
25998 + this->data_poi = bufstart;
25999 + ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0);
26003 + written += mtd->oobblock * numpages;
26008 + startpage = page & this->pagemask;
26009 + /* Check, if we cross a chip boundary */
26010 + if (!startpage) {
26012 + this->select_chip(mtd, -1);
26013 + this->select_chip(mtd, chipnr);
26018 + /* Deselect and wake up anyone waiting on the device */
26019 + nand_release_chip(mtd);
26021 + *retlen = written;
26026 + * single_erease_cmd - [GENERIC] NAND standard block erase command function
26027 + * @mtd: MTD device structure
26028 + * @page: the page address of the block which will be erased
26030 + * Standard erase command for NAND chips
26032 +static void single_erase_cmd (struct mtd_info *mtd, int page)
26034 + struct nand_chip *this = mtd->priv;
26035 + /* Send commands to erase a block */
26036 + this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page);
26037 + this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1);
26041 + * multi_erease_cmd - [GENERIC] AND specific block erase command function
26042 + * @mtd: MTD device structure
26043 + * @page: the page address of the block which will be erased
26045 + * AND multi block erase command function
26046 + * Erase 4 consecutive blocks
26048 +static void multi_erase_cmd (struct mtd_info *mtd, int page)
26050 + struct nand_chip *this = mtd->priv;
26051 + /* Send commands to erase a block */
26052 + this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
26053 + this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
26054 + this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
26055 + this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page);
26056 + this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1);
26060 + * nand_erase - [MTD Interface] erase block(s)
26061 + * @mtd: MTD device structure
26062 + * @instr: erase instruction
26064 + * Erase one ore more blocks
26066 +static int nand_erase (struct mtd_info *mtd, struct erase_info *instr)
26068 + return nand_erase_nand (mtd, instr, 0);
26072 + * nand_erase_intern - [NAND Interface] erase block(s)
26073 + * @mtd: MTD device structure
26074 + * @instr: erase instruction
26075 + * @allowbbt: allow erasing the bbt area
26077 + * Erase one ore more blocks
26079 +int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
26081 + int page, len, status, pages_per_block, ret, chipnr;
26082 + struct nand_chip *this = mtd->priv;
26084 + DEBUG (MTD_DEBUG_LEVEL3,
26085 + "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len);
26087 + /* Start address must align on block boundary */
26088 + if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
26089 + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
26093 + /* Length must align on block boundary */
26094 + if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
26095 + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n");
26099 + /* Do not allow erase past end of device */
26100 + if ((instr->len + instr->addr) > mtd->size) {
26101 + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n");
26105 + instr->fail_addr = 0xffffffff;
26107 + /* Grab the lock and see if the device is available */
26108 + nand_get_chip (this, mtd, FL_ERASING);
26110 + /* Shift to get first page */
26111 + page = (int) (instr->addr >> this->page_shift);
26112 + chipnr = (int) (instr->addr >> this->chip_shift);
26114 + /* Calculate pages in each block */
26115 + pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
26117 + /* Select the NAND device */
26118 + this->select_chip(mtd, chipnr);
26120 + /* Check the WP bit */
26121 + /* Check, if it is write protected */
26122 + if (nand_check_wp(mtd)) {
26123 + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n");
26124 + instr->state = MTD_ERASE_FAILED;
26128 + /* Loop through the pages */
26129 + len = instr->len;
26131 + instr->state = MTD_ERASING;
26134 + /* Check if we have a bad block, we do not erase bad blocks ! */
26135 + if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) {
26136 + printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
26137 + instr->state = MTD_ERASE_FAILED;
26141 + /* Invalidate the page cache, if we erase the block which contains
26142 + the current cached page */
26143 + if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
26144 + this->pagebuf = -1;
26146 + this->erase_cmd (mtd, page & this->pagemask);
26148 + status = this->waitfunc (mtd, this, FL_ERASING);
26150 + /* See if block erase succeeded */
26151 + if (status & 0x01) {
26152 + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);
26153 + instr->state = MTD_ERASE_FAILED;
26154 + instr->fail_addr = (page << this->page_shift);
26158 + /* Increment page address and decrement length */
26159 + len -= (1 << this->phys_erase_shift);
26160 + page += pages_per_block;
26162 + /* Check, if we cross a chip boundary */
26163 + if (len && !(page & this->pagemask)) {
26165 + this->select_chip(mtd, -1);
26166 + this->select_chip(mtd, chipnr);
26169 + instr->state = MTD_ERASE_DONE;
26173 + ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
26174 + /* Do call back function */
26176 + mtd_erase_callback(instr);
26178 + /* Deselect and wake up anyone waiting on the device */
26179 + nand_release_chip(mtd);
26181 + /* Return more or less happy */
26186 + * nand_sync - [MTD Interface] sync
26187 + * @mtd: MTD device structure
26189 + * Sync is actually a wait for chip ready function
26191 +static void nand_sync (struct mtd_info *mtd)
26193 + struct nand_chip *this = mtd->priv;
26194 + DECLARE_WAITQUEUE (wait, current);
26196 + DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n");
26199 + /* Grab the spinlock */
26200 + spin_lock_bh (&this->chip_lock);
26202 + /* See what's going on */
26203 + switch (this->state) {
26206 + this->state = FL_SYNCING;
26207 + spin_unlock_bh (&this->chip_lock);
26211 + /* Not an idle state */
26212 + add_wait_queue (&this->wq, &wait);
26213 + spin_unlock_bh (&this->chip_lock);
26216 + remove_wait_queue (&this->wq, &wait);
26220 + /* Lock the device */
26221 + spin_lock_bh (&this->chip_lock);
26223 + /* Set the device to be ready again */
26224 + if (this->state == FL_SYNCING) {
26225 + this->state = FL_READY;
26226 + wake_up (&this->wq);
26229 + /* Unlock the device */
26230 + spin_unlock_bh (&this->chip_lock);
26235 + * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
26236 + * @mtd: MTD device structure
26237 + * @ofs: offset relative to mtd start
26239 +static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs)
26241 + /* Check for invalid offset */
26242 + if (ofs > mtd->size)
26245 + return nand_block_checkbad (mtd, ofs, 1, 0);
26249 + * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
26250 + * @mtd: MTD device structure
26251 + * @ofs: offset relative to mtd start
26253 +static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs)
26255 + struct nand_chip *this = mtd->priv;
26258 + if ((ret = nand_block_isbad(mtd, ofs))) {
26259 + /* If it was bad already, return success and do nothing. */
26265 + return this->block_markbad(mtd, ofs);
26269 + * nand_scan - [NAND Interface] Scan for the NAND device
26270 + * @mtd: MTD device structure
26271 + * @maxchips: Number of chips to scan for
26273 + * This fills out all the not initialized function pointers
26274 + * with the defaults.
26275 + * The flash ID is read and the mtd/chip structures are
26276 + * filled with the appropriate values. Buffers are allocated if
26277 + * they are not provided by the board driver
26280 +int nand_scan (struct mtd_info *mtd, int maxchips)
26282 + int i, j, nand_maf_id, nand_dev_id, busw;
26283 + struct nand_chip *this = mtd->priv;
26285 + /* Get buswidth to select the correct functions*/
26286 + busw = this->options & NAND_BUSWIDTH_16;
26288 + /* check for proper chip_delay setup, set 20us if not */
26289 + if (!this->chip_delay)
26290 + this->chip_delay = 20;
26292 + /* check, if a user supplied command function given */
26293 + if (this->cmdfunc == NULL)
26294 + this->cmdfunc = nand_command;
26296 + /* check, if a user supplied wait function given */
26297 + if (this->waitfunc == NULL)
26298 + this->waitfunc = nand_wait;
26300 + if (!this->select_chip)
26301 + this->select_chip = nand_select_chip;
26302 + if (!this->write_byte)
26303 + this->write_byte = busw ? nand_write_byte16 : nand_write_byte;
26304 + if (!this->read_byte)
26305 + this->read_byte = busw ? nand_read_byte16 : nand_read_byte;
26306 + if (!this->write_word)
26307 + this->write_word = nand_write_word;
26308 + if (!this->read_word)
26309 + this->read_word = nand_read_word;
26310 + if (!this->block_bad)
26311 + this->block_bad = nand_block_bad;
26312 + if (!this->block_markbad)
26313 + this->block_markbad = nand_default_block_markbad;
26314 + if (!this->write_buf)
26315 + this->write_buf = busw ? nand_write_buf16 : nand_write_buf;
26316 + if (!this->read_buf)
26317 + this->read_buf = busw ? nand_read_buf16 : nand_read_buf;
26318 + if (!this->verify_buf)
26319 + this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
26320 + if (!this->scan_bbt)
26321 + this->scan_bbt = nand_default_bbt;
26323 + /* Select the device */
26324 + this->select_chip(mtd, 0);
26326 + /* Send the command for reading device ID */
26327 + this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
26329 + /* Read manufacturer and device IDs */
26330 + nand_maf_id = this->read_byte(mtd);
26331 + nand_dev_id = this->read_byte(mtd);
26333 + /* Print and store flash device information */
26334 + for (i = 0; nand_flash_ids[i].name != NULL; i++) {
26336 + if (nand_dev_id != nand_flash_ids[i].id)
26339 + if (!mtd->name) mtd->name = nand_flash_ids[i].name;
26340 + this->chipsize = nand_flash_ids[i].chipsize << 20;
26342 + /* New devices have all the information in additional id bytes */
26343 + if (!nand_flash_ids[i].pagesize) {
26345 + /* The 3rd id byte contains non relevant data ATM */
26346 + extid = this->read_byte(mtd);
26347 + /* The 4th id byte is the important one */
26348 + extid = this->read_byte(mtd);
26349 + /* Calc pagesize */
26350 + mtd->oobblock = 1024 << (extid & 0x3);
26352 + /* Calc oobsize */
26353 + mtd->oobsize = (8 << (extid & 0x03)) * (mtd->oobblock / 512);
26355 + /* Calc blocksize. Blocksize is multiples of 64KiB */
26356 + mtd->erasesize = (64 * 1024) << (extid & 0x03);
26358 + /* Get buswidth information */
26359 + busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
26362 + /* Old devices have this data hardcoded in the
26363 + * device id table */
26364 + mtd->erasesize = nand_flash_ids[i].erasesize;
26365 + mtd->oobblock = nand_flash_ids[i].pagesize;
26366 + mtd->oobsize = mtd->oobblock / 32;
26367 + busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
26370 + /* Check, if buswidth is correct. Hardware drivers should set
26371 + * this correct ! */
26372 + if (busw != (this->options & NAND_BUSWIDTH_16)) {
26373 + printk (KERN_INFO "NAND device: Manufacturer ID:"
26374 + " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
26375 + nand_manuf_ids[i].name , mtd->name);
26376 + printk (KERN_WARNING
26377 + "NAND bus width %d instead %d bit\n",
26378 + (this->options & NAND_BUSWIDTH_16) ? 16 : 8,
26380 + this->select_chip(mtd, -1);
26384 + /* Calculate the address shift from the page size */
26385 + this->page_shift = ffs(mtd->oobblock) - 1;
26386 + this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;
26387 + this->chip_shift = ffs(this->chipsize) - 1;
26389 + /* Set the bad block position */
26390 + this->badblockpos = mtd->oobblock > 512 ?
26391 + NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
26393 + /* Get chip options, preserve non chip based options */
26394 + this->options &= ~NAND_CHIPOPTIONS_MSK;
26395 + this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
26396 + /* Set this as a default. Board drivers can override it, if neccecary */
26397 + this->options |= NAND_NO_AUTOINCR;
26398 + /* Check if this is a not a samsung device. Do not clear the options
26399 + * for chips which are not having an extended id.
26401 + if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
26402 + this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
26404 + /* Check for AND chips with 4 page planes */
26405 + if (this->options & NAND_4PAGE_ARRAY)
26406 + this->erase_cmd = multi_erase_cmd;
26408 + this->erase_cmd = single_erase_cmd;
26410 + /* Do not replace user supplied command function ! */
26411 + if (mtd->oobblock > 512 && this->cmdfunc == nand_command)
26412 + this->cmdfunc = nand_command_lp;
26414 + /* Try to identify manufacturer */
26415 + for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
26416 + if (nand_manuf_ids[j].id == nand_maf_id)
26419 + printk (KERN_INFO "NAND device: Manufacturer ID:"
26420 + " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
26421 + nand_manuf_ids[j].name , nand_flash_ids[i].name);
26425 + if (!nand_flash_ids[i].name) {
26426 + printk (KERN_WARNING "No NAND device found!!!\n");
26427 + this->select_chip(mtd, -1);
26431 + for (i=1; i < maxchips; i++) {
26432 + this->select_chip(mtd, i);
26434 + /* Send the command for reading device ID */
26435 + this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
26437 + /* Read manufacturer and device IDs */
26438 + if (nand_maf_id != this->read_byte(mtd) ||
26439 + nand_dev_id != this->read_byte(mtd))
26443 + printk(KERN_INFO "%d NAND chips detected\n", i);
26445 + /* Allocate buffers, if neccecary */
26446 + if (!this->oob_buf) {
26448 + len = mtd->oobsize << (this->phys_erase_shift - this->page_shift);
26449 + this->oob_buf = kmalloc (len, GFP_KERNEL);
26450 + if (!this->oob_buf) {
26451 + printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n");
26454 + this->options |= NAND_OOBBUF_ALLOC;
26457 + if (!this->data_buf) {
26459 + len = mtd->oobblock + mtd->oobsize;
26460 + this->data_buf = kmalloc (len, GFP_KERNEL);
26461 + if (!this->data_buf) {
26462 + if (this->options & NAND_OOBBUF_ALLOC)
26463 + kfree (this->oob_buf);
26464 + printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n");
26467 + this->options |= NAND_DATABUF_ALLOC;
26470 + /* Store the number of chips and calc total size for mtd */
26471 + this->numchips = i;
26472 + mtd->size = i * this->chipsize;
26473 + /* Convert chipsize to number of pages per chip -1. */
26474 + this->pagemask = (this->chipsize >> this->page_shift) - 1;
26475 + /* Preset the internal oob buffer */
26476 + memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
26478 + /* If no default placement scheme is given, select an
26479 + * appropriate one */
26480 + if (!this->autooob) {
26481 + /* Select the appropriate default oob placement scheme for
26482 + * placement agnostic filesystems */
26483 + switch (mtd->oobsize) {
26485 + this->autooob = &nand_oob_8;
26488 + this->autooob = &nand_oob_16;
26491 + this->autooob = &nand_oob_64;
26494 + printk (KERN_WARNING "No oob scheme defined for oobsize %d\n",
26500 + /* The number of bytes available for the filesystem to place fs dependend
26502 + if (this->options & NAND_BUSWIDTH_16) {
26503 + mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 2);
26504 + if (this->autooob->eccbytes & 0x01)
26507 + mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1);
26510 + * check ECC mode, default to software
26511 + * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize
26512 + * fallback to software ECC
26514 + this->eccsize = 256; /* set default eccsize */
26516 + switch (this->eccmode) {
26518 + case NAND_ECC_HW3_512:
26519 + case NAND_ECC_HW6_512:
26520 + case NAND_ECC_HW8_512:
26521 + if (mtd->oobblock == 256) {
26522 + printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");
26523 + this->eccmode = NAND_ECC_SOFT;
26524 + this->calculate_ecc = nand_calculate_ecc;
26525 + this->correct_data = nand_correct_data;
26528 + this->eccsize = 512; /* set eccsize to 512 and fall through for function check */
26530 + case NAND_ECC_HW3_256:
26531 + if (this->calculate_ecc && this->correct_data && this->enable_hwecc)
26533 + printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n");
26536 + case NAND_ECC_NONE:
26537 + printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n");
26538 + this->eccmode = NAND_ECC_NONE;
26541 + case NAND_ECC_SOFT:
26542 + this->calculate_ecc = nand_calculate_ecc;
26543 + this->correct_data = nand_correct_data;
26547 + printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
26551 + mtd->eccsize = this->eccsize;
26553 + /* Set the number of read / write steps for one page to ensure ECC generation */
26554 + switch (this->eccmode) {
26555 + case NAND_ECC_HW3_512:
26556 + case NAND_ECC_HW6_512:
26557 + case NAND_ECC_HW8_512:
26558 + this->eccsteps = mtd->oobblock / 512;
26560 + case NAND_ECC_HW3_256:
26561 + case NAND_ECC_SOFT:
26562 + this->eccsteps = mtd->oobblock / 256;
26565 + case NAND_ECC_NONE:
26566 + this->eccsteps = 1;
26570 + /* Initialize state, waitqueue and spinlock */
26571 + this->state = FL_READY;
26572 + init_waitqueue_head (&this->wq);
26573 + spin_lock_init (&this->chip_lock);
26575 + /* De-select the device */
26576 + this->select_chip(mtd, -1);
26578 + /* Invalidate the pagebuffer reference */
26579 + this->pagebuf = -1;
26581 + /* Fill in remaining MTD driver data */
26582 + mtd->type = MTD_NANDFLASH;
26583 + mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
26584 + mtd->ecctype = MTD_ECC_SW;
26585 + mtd->erase = nand_erase;
26586 + mtd->point = NULL;
26587 + mtd->unpoint = NULL;
26588 + mtd->read = nand_read;
26589 + mtd->write = nand_write;
26590 + mtd->read_ecc = nand_read_ecc;
26591 + mtd->write_ecc = nand_write_ecc;
26592 + mtd->read_oob = nand_read_oob;
26593 + mtd->write_oob = nand_write_oob;
26594 + mtd->readv = NULL;
26595 + mtd->writev = nand_writev;
26596 + mtd->writev_ecc = nand_writev_ecc;
26597 + mtd->sync = nand_sync;
26598 + mtd->lock = NULL;
26599 + mtd->unlock = NULL;
26600 + mtd->suspend = NULL;
26601 + mtd->resume = NULL;
26602 + mtd->block_isbad = nand_block_isbad;
26603 + mtd->block_markbad = nand_block_markbad;
26605 + /* and make the autooob the default one */
26606 + memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
26608 + mtd->owner = THIS_MODULE;
26610 + /* Build bad block table */
26611 + return this->scan_bbt (mtd);
26615 + * nand_release - [NAND Interface] Free resources held by the NAND device
26616 + * @mtd: MTD device structure
26618 +void nand_release (struct mtd_info *mtd)
26620 + struct nand_chip *this = mtd->priv;
26622 +#ifdef CONFIG_MTD_PARTITIONS
26623 + /* Deregister partitions */
26624 + del_mtd_partitions (mtd);
26626 + /* Deregister the device */
26627 + del_mtd_device (mtd);
26629 + /* Free bad block table memory, if allocated */
26631 + kfree (this->bbt);
26632 + /* Buffer allocated by nand_scan ? */
26633 + if (this->options & NAND_OOBBUF_ALLOC)
26634 + kfree (this->oob_buf);
26635 + /* Buffer allocated by nand_scan ? */
26636 + if (this->options & NAND_DATABUF_ALLOC)
26637 + kfree (this->data_buf);
26640 +EXPORT_SYMBOL (nand_scan);
26641 +EXPORT_SYMBOL (nand_release);
26643 +MODULE_LICENSE ("GPL");
26644 +MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
26645 +MODULE_DESCRIPTION ("Generic NAND flash driver code");
26646 Index: linux-2.6.5/drivers/mtd/nand/nand_bbt.c
26647 ===================================================================
26648 --- linux-2.6.5.orig/drivers/mtd/nand/nand_bbt.c 1969-12-31 19:00:00.000000000 -0500
26649 +++ linux-2.6.5/drivers/mtd/nand/nand_bbt.c 2005-02-01 17:11:17.000000000 -0500
26652 + * drivers/mtd/nand_bbt.c
26655 + * Bad block table support for the NAND driver
26657 + * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
26659 + * $Id: nand_bbt.c,v 1.24 2004/06/28 08:25:35 gleixner Exp $
26661 + * This program is free software; you can redistribute it and/or modify
26662 + * it under the terms of the GNU General Public License version 2 as
26663 + * published by the Free Software Foundation.
26667 + * When nand_scan_bbt is called, then it tries to find the bad block table
26668 + * depending on the options in the bbt descriptor(s). If a bbt is found
26669 + * then the contents are read and the memory based bbt is created. If a
26670 + * mirrored bbt is selected then the mirror is searched too and the
26671 + * versions are compared. If the mirror has a greater version number
26672 + * than the mirror bbt is used to build the memory based bbt.
26673 + * If the tables are not versioned, then we "or" the bad block information.
26674 + * If one of the bbt's is out of date or does not exist it is (re)created.
26675 + * If no bbt exists at all then the device is scanned for factory marked
26676 + * good / bad blocks and the bad block tables are created.
26678 + * For manufacturer created bbts like the one found on M-SYS DOC devices
26679 + * the bbt is searched and read but never created
26681 + * The autogenerated bad block table is located in the last good blocks
26682 + * of the device. The table is mirrored, so it can be updated eventually.
26683 + * The table is marked in the oob area with an ident pattern and a version
26684 + * number which indicates which of both tables is more up to date.
26686 + * The table uses 2 bits per block
26687 + * 11b: block is good
26688 + * 00b: block is factory marked bad
26689 + * 01b, 10b: block is marked bad due to wear
26691 + * The memory bad block table uses the following scheme:
26692 + * 00b: block is good
26693 + * 01b: block is marked bad due to wear
26694 + * 10b: block is reserved (to protect the bbt area)
26695 + * 11b: block is factory marked bad
26697 + * Multichip devices like DOC store the bad block info per floor.
26699 + * Following assumptions are made:
26700 + * - bbts start at a page boundary, if autolocated on a block boundary
26701 + * - the space neccecary for a bbt in FLASH does not exceed a block boundary
26705 +#include <linux/slab.h>
26706 +#include <linux/types.h>
26707 +#include <linux/mtd/mtd.h>
26708 +#include <linux/mtd/nand.h>
26709 +#include <linux/mtd/nand_ecc.h>
26710 +#include <linux/mtd/compatmac.h>
26711 +#include <linux/bitops.h>
26712 +#include <linux/delay.h>
26716 + * check_pattern - [GENERIC] check if a pattern is in the buffer
26717 + * @buf: the buffer to search
26718 + * @len: the length of buffer to search
26719 + * @paglen: the pagelength
26720 + * @td: search pattern descriptor
26722 + * Check for a pattern at the given place. Used to search bad block
26723 + * tables and good / bad block identifiers.
26724 + * If the SCAN_EMPTY option is set then check, if all bytes except the
26725 + * pattern area contain 0xff
26728 +static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
26731 + uint8_t *p = buf;
26733 + end = paglen + td->offs;
26734 + if (td->options & NAND_BBT_SCANEMPTY) {
26735 + for (i = 0; i < end; i++) {
26736 + if (p[i] != 0xff)
26742 + /* Compare the pattern */
26743 + for (i = 0; i < td->len; i++) {
26744 + if (p[i] != td->pattern[i])
26750 + if (td->options & NAND_BBT_SCANEMPTY) {
26751 + for (i = end; i < len; i++) {
26752 + if (*p++ != 0xff)
26760 + * read_bbt - [GENERIC] Read the bad block table starting from page
26761 + * @mtd: MTD device structure
26762 + * @buf: temporary buffer
26763 + * @page: the starting page
26764 + * @num: the number of bbt descriptors to read
26765 + * @bits: number of bits per block
26766 + * @offs: offset in the memory table
26768 + * Read the bad block table starting from page.
26771 +static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
26772 + int bits, int offs, int reserved_block_code)
26774 + int res, i, j, act = 0;
26775 + struct nand_chip *this = mtd->priv;
26776 + size_t retlen, len, totlen;
26778 + uint8_t msk = (uint8_t) ((1 << bits) - 1);
26780 + totlen = (num * bits) >> 3;
26781 + from = ((loff_t)page) << this->page_shift;
26784 + len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
26785 + res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
26787 + if (retlen != len) {
26788 + printk (KERN_INFO "nand_bbt: Error reading bad block table\n");
26791 + printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
26794 + /* Analyse data */
26795 + for (i = 0; i < len; i++) {
26796 + uint8_t dat = buf[i];
26797 + for (j = 0; j < 8; j += bits, act += 2) {
26798 + uint8_t tmp = (dat >> j) & msk;
26801 + if (reserved_block_code &&
26802 + (tmp == reserved_block_code)) {
26803 + printk (KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
26804 + ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
26805 + this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
26808 + /* Leave it for now, if its matured we can move this
26809 + * message to MTD_DEBUG_LEVEL0 */
26810 + printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
26811 + ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
26812 + /* Factory marked bad or worn out ? */
26814 + this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
26816 + this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
26826 + * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page
26827 + * @mtd: MTD device structure
26828 + * @buf: temporary buffer
26829 + * @td: descriptor for the bad block table
26830 + * @chip: read the table for a specific chip, -1 read all chips.
26831 + * Applies only if NAND_BBT_PERCHIP option is set
26833 + * Read the bad block table for all chips starting at a given page
26834 + * We assume that the bbt bits are in consecutive order.
26836 +static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
26838 + struct nand_chip *this = mtd->priv;
26842 + bits = td->options & NAND_BBT_NRBITS_MSK;
26843 + if (td->options & NAND_BBT_PERCHIP) {
26845 + for (i = 0; i < this->numchips; i++) {
26846 + if (chip == -1 || chip == i)
26847 + res = read_bbt (mtd, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code);
26850 + offs += this->chipsize >> (this->bbt_erase_shift + 2);
26853 + res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code);
26861 + * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
26862 + * @mtd: MTD device structure
26863 + * @buf: temporary buffer
26864 + * @td: descriptor for the bad block table
26865 + * @md: descriptor for the bad block table mirror
26867 + * Read the bad block table(s) for all chips starting at a given page
26868 + * We assume that the bbt bits are in consecutive order.
26871 +static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td,
26872 + struct nand_bbt_descr *md)
26874 + struct nand_chip *this = mtd->priv;
26876 + /* Read the primary version, if available */
26877 + if (td->options & NAND_BBT_VERSION) {
26878 + nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
26879 + td->version[0] = buf[mtd->oobblock + td->veroffs];
26880 + printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
26883 + /* Read the mirror version, if available */
26884 + if (md && (md->options & NAND_BBT_VERSION)) {
26885 + nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
26886 + md->version[0] = buf[mtd->oobblock + md->veroffs];
26887 + printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
26894 + * create_bbt - [GENERIC] Create a bad block table by scanning the device
26895 + * @mtd: MTD device structure
26896 + * @buf: temporary buffer
26897 + * @bd: descriptor for the good/bad block search pattern
26898 + * @chip: create the table for a specific chip, -1 read all chips.
26899 + * Applies only if NAND_BBT_PERCHIP option is set
26901 + * Create a bad block table by scanning the device
26902 + * for the given good/bad block identify pattern
26904 +static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
26906 + struct nand_chip *this = mtd->priv;
26907 + int i, j, numblocks, len, scanlen;
26910 + size_t readlen, ooblen;
26912 + printk (KERN_INFO "Scanning device for bad blocks\n");
26914 + if (bd->options & NAND_BBT_SCANALLPAGES)
26915 + len = 1 << (this->bbt_erase_shift - this->page_shift);
26917 + if (bd->options & NAND_BBT_SCAN2NDPAGE)
26922 + scanlen = mtd->oobblock + mtd->oobsize;
26923 + readlen = len * mtd->oobblock;
26924 + ooblen = len * mtd->oobsize;
26926 + if (chip == -1) {
26927 + /* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it
26928 + * makes shifting and masking less painful */
26929 + numblocks = mtd->size >> (this->bbt_erase_shift - 1);
26933 + if (chip >= this->numchips) {
26934 + printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
26935 + chip + 1, this->numchips);
26938 + numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
26939 + startblock = chip * numblocks;
26940 + numblocks += startblock;
26941 + from = startblock << (this->bbt_erase_shift - 1);
26944 + for (i = startblock; i < numblocks;) {
26945 + nand_read_raw (mtd, buf, from, readlen, ooblen);
26946 + for (j = 0; j < len; j++) {
26947 + if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
26948 + this->bbt[i >> 3] |= 0x03 << (i & 0x6);
26949 + printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
26950 + i >> 1, (unsigned int) from);
26955 + from += (1 << this->bbt_erase_shift);
26960 + * search_bbt - [GENERIC] scan the device for a specific bad block table
26961 + * @mtd: MTD device structure
26962 + * @buf: temporary buffer
26963 + * @td: descriptor for the bad block table
26965 + * Read the bad block table by searching for a given ident pattern.
26966 + * Search is preformed either from the beginning up or from the end of
26967 + * the device downwards. The search starts always at the start of a
26969 + * If the option NAND_BBT_PERCHIP is given, each chip is searched
26970 + * for a bbt, which contains the bad block information of this chip.
26971 + * This is neccecary to provide support for certain DOC devices.
26973 + * The bbt ident pattern resides in the oob area of the first page
26976 +static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
26978 + struct nand_chip *this = mtd->priv;
26980 + int bits, startblock, block, dir;
26981 + int scanlen = mtd->oobblock + mtd->oobsize;
26984 + /* Search direction top -> down ? */
26985 + if (td->options & NAND_BBT_LASTBLOCK) {
26986 + startblock = (mtd->size >> this->bbt_erase_shift) -1;
26993 + /* Do we have a bbt per chip ? */
26994 + if (td->options & NAND_BBT_PERCHIP) {
26995 + chips = this->numchips;
26996 + bbtblocks = this->chipsize >> this->bbt_erase_shift;
26997 + startblock &= bbtblocks - 1;
27000 + bbtblocks = mtd->size >> this->bbt_erase_shift;
27003 + /* Number of bits for each erase block in the bbt */
27004 + bits = td->options & NAND_BBT_NRBITS_MSK;
27006 + for (i = 0; i < chips; i++) {
27007 + /* Reset version information */
27008 + td->version[i] = 0;
27009 + td->pages[i] = -1;
27010 + /* Scan the maximum number of blocks */
27011 + for (block = 0; block < td->maxblocks; block++) {
27012 + int actblock = startblock + dir * block;
27013 + /* Read first page */
27014 + nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
27015 + if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
27016 + td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
27017 + if (td->options & NAND_BBT_VERSION) {
27018 + td->version[i] = buf[mtd->oobblock + td->veroffs];
27023 + startblock += this->chipsize >> this->bbt_erase_shift;
27025 + /* Check, if we found a bbt for each requested chip */
27026 + for (i = 0; i < chips; i++) {
27027 + if (td->pages[i] == -1)
27028 + printk (KERN_WARNING "Bad block table not found for chip %d\n", i);
27030 + printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]);
27036 + * search_read_bbts - [GENERIC] scan the device for bad block table(s)
27037 + * @mtd: MTD device structure
27038 + * @buf: temporary buffer
27039 + * @td: descriptor for the bad block table
27040 + * @md: descriptor for the bad block table mirror
27042 + * Search and read the bad block table(s)
27044 +static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
27045 + struct nand_bbt_descr *td, struct nand_bbt_descr *md)
27047 + /* Search the primary table */
27048 + search_bbt (mtd, buf, td);
27050 + /* Search the mirror table */
27052 + search_bbt (mtd, buf, md);
27054 + /* Force result check */
27060 + * write_bbt - [GENERIC] (Re)write the bad block table
27062 + * @mtd: MTD device structure
27063 + * @buf: temporary buffer
27064 + * @td: descriptor for the bad block table
27065 + * @md: descriptor for the bad block table mirror
27066 + * @chipsel: selector for a specific chip, -1 for all
27068 + * (Re)write the bad block table
27071 +static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
27072 + struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
27074 + struct nand_chip *this = mtd->priv;
27075 + struct nand_oobinfo oobinfo;
27076 + struct erase_info einfo;
27077 + int i, j, res, chip = 0;
27078 + int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
27079 + int nrchips, bbtoffs, pageoffs;
27081 + uint8_t rcode = td->reserved_block_code;
27082 + size_t retlen, len = 0;
27087 + /* Write bad block table per chip rather than per device ? */
27088 + if (td->options & NAND_BBT_PERCHIP) {
27089 + numblocks = (int) (this->chipsize >> this->bbt_erase_shift);
27090 + /* Full device write or specific chip ? */
27091 + if (chipsel == -1) {
27092 + nrchips = this->numchips;
27094 + nrchips = chipsel + 1;
27098 + numblocks = (int) (mtd->size >> this->bbt_erase_shift);
27102 + /* Loop through the chips */
27103 + for (; chip < nrchips; chip++) {
27105 + /* There was already a version of the table, reuse the page
27106 + * This applies for absolute placement too, as we have the
27107 + * page nr. in td->pages.
27109 + if (td->pages[chip] != -1) {
27110 + page = td->pages[chip];
27114 + /* Automatic placement of the bad block table */
27115 + /* Search direction top -> down ? */
27116 + if (td->options & NAND_BBT_LASTBLOCK) {
27117 + startblock = numblocks * (chip + 1) - 1;
27120 + startblock = chip * numblocks;
27124 + for (i = 0; i < td->maxblocks; i++) {
27125 + int block = startblock + dir * i;
27126 + /* Check, if the block is bad */
27127 + switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) {
27132 + page = block << (this->bbt_erase_shift - this->page_shift);
27133 + /* Check, if the block is used by the mirror table */
27134 + if (!md || md->pages[chip] != page)
27137 + printk (KERN_ERR "No space left to write bad block table\n");
27141 + /* Set up shift count and masks for the flash table */
27142 + bits = td->options & NAND_BBT_NRBITS_MSK;
27144 + case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break;
27145 + case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break;
27146 + case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break;
27147 + case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break;
27148 + default: return -EINVAL;
27151 + bbtoffs = chip * (numblocks >> 2);
27153 + to = ((loff_t) page) << this->page_shift;
27155 + memcpy (&oobinfo, this->autooob, sizeof(oobinfo));
27156 + oobinfo.useecc = MTD_NANDECC_PLACEONLY;
27158 + /* Must we save the block contents ? */
27159 + if (td->options & NAND_BBT_SAVECONTENT) {
27160 + /* Make it block aligned */
27161 + to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
27162 + len = 1 << this->bbt_erase_shift;
27163 + res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
27165 + if (retlen != len) {
27166 + printk (KERN_INFO "nand_bbt: Error reading block for writing the bad block table\n");
27169 + printk (KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n");
27171 + /* Calc the byte offset in the buffer */
27172 + pageoffs = page - (int)(to >> this->page_shift);
27173 + offs = pageoffs << this->page_shift;
27174 + /* Preset the bbt area with 0xff */
27175 + memset (&buf[offs], 0xff, (size_t)(numblocks >> sft));
27176 + /* Preset the bbt's oob area with 0xff */
27177 + memset (&buf[len + pageoffs * mtd->oobsize], 0xff,
27178 + ((len >> this->page_shift) - pageoffs) * mtd->oobsize);
27179 + if (td->options & NAND_BBT_VERSION) {
27180 + buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
27183 + /* Calc length */
27184 + len = (size_t) (numblocks >> sft);
27185 + /* Make it page aligned ! */
27186 + len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1);
27187 + /* Preset the buffer with 0xff */
27188 + memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
27190 + /* Pattern is located in oob area of first page */
27191 + memcpy (&buf[len + td->offs], td->pattern, td->len);
27192 + if (td->options & NAND_BBT_VERSION) {
27193 + buf[len + td->veroffs] = td->version[chip];
27197 + /* walk through the memory table */
27198 + for (i = 0; i < numblocks; ) {
27200 + dat = this->bbt[bbtoffs + (i >> 2)];
27201 + for (j = 0; j < 4; j++ , i++) {
27202 + int sftcnt = (i << (3 - sft)) & sftmsk;
27203 + /* Do not store the reserved bbt blocks ! */
27204 + buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt);
27209 + memset (&einfo, 0, sizeof (einfo));
27211 + einfo.addr = (unsigned long) to;
27212 + einfo.len = 1 << this->bbt_erase_shift;
27213 + res = nand_erase_nand (mtd, &einfo, 1);
27215 + printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
27219 + res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
27221 + printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
27224 + printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n",
27225 + (unsigned int) to, td->version[chip]);
27227 + /* Mark it as used */
27228 + td->pages[chip] = page;
27234 + * nand_memory_bbt - [GENERIC] create a memory based bad block table
27235 + * @mtd: MTD device structure
27236 + * @bd: descriptor for the good/bad block search pattern
27238 + * The function creates a memory based bbt by scanning the device
27239 + * for manufacturer / software marked good / bad blocks
27241 +static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
27243 + struct nand_chip *this = mtd->priv;
27245 + /* Ensure that we only scan for the pattern and nothing else */
27247 + create_bbt (mtd, this->data_buf, bd, -1);
27252 + * check_create - [GENERIC] create and write bbt(s) if neccecary
27253 + * @mtd: MTD device structure
27254 + * @buf: temporary buffer
27255 + * @bd: descriptor for the good/bad block search pattern
27257 + * The function checks the results of the previous call to read_bbt
27258 + * and creates / updates the bbt(s) if neccecary
27259 + * Creation is neccecary if no bbt was found for the chip/device
27260 + * Update is neccecary if one of the tables is missing or the
27261 + * version nr. of one table is less than the other
27263 +static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
27265 + int i, chips, writeops, chipsel, res;
27266 + struct nand_chip *this = mtd->priv;
27267 + struct nand_bbt_descr *td = this->bbt_td;
27268 + struct nand_bbt_descr *md = this->bbt_md;
27269 + struct nand_bbt_descr *rd, *rd2;
27271 + /* Do we have a bbt per chip ? */
27272 + if (td->options & NAND_BBT_PERCHIP)
27273 + chips = this->numchips;
27277 + for (i = 0; i < chips; i++) {
27281 + /* Per chip or per device ? */
27282 + chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
27283 + /* Mirrored table avilable ? */
27285 + if (td->pages[i] == -1 && md->pages[i] == -1) {
27290 + if (td->pages[i] == -1) {
27292 + td->version[i] = md->version[i];
27297 + if (md->pages[i] == -1) {
27299 + md->version[i] = td->version[i];
27304 + if (td->version[i] == md->version[i]) {
27306 + if (!(td->options & NAND_BBT_VERSION))
27311 + if (((int8_t) (td->version[i] - md->version[i])) > 0) {
27313 + md->version[i] = td->version[i];
27317 + td->version[i] = md->version[i];
27324 + if (td->pages[i] == -1) {
27332 + /* Create the bad block table by scanning the device ? */
27333 + if (!(td->options & NAND_BBT_CREATE))
27336 + /* Create the table in memory by scanning the chip(s) */
27337 + create_bbt (mtd, buf, bd, chipsel);
27339 + td->version[i] = 1;
27341 + md->version[i] = 1;
27343 + /* read back first ? */
27345 + read_abs_bbt (mtd, buf, rd, chipsel);
27346 + /* If they weren't versioned, read both. */
27348 + read_abs_bbt (mtd, buf, rd2, chipsel);
27350 + /* Write the bad block table to the device ? */
27351 + if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
27352 + res = write_bbt (mtd, buf, td, md, chipsel);
27357 + /* Write the mirror bad block table to the device ? */
27358 + if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
27359 + res = write_bbt (mtd, buf, md, td, chipsel);
27368 + * mark_bbt_regions - [GENERIC] mark the bad block table regions
27369 + * @mtd: MTD device structure
27370 + * @td: bad block table descriptor
27372 + * The bad block table regions are marked as "bad" to prevent
27373 + * accidental erasures / writes. The regions are identified by
27376 +static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
27378 + struct nand_chip *this = mtd->priv;
27379 + int i, j, chips, block, nrblocks, update;
27380 + uint8_t oldval, newval;
27382 + /* Do we have a bbt per chip ? */
27383 + if (td->options & NAND_BBT_PERCHIP) {
27384 + chips = this->numchips;
27385 + nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
27388 + nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
27391 + for (i = 0; i < chips; i++) {
27392 + if ((td->options & NAND_BBT_ABSPAGE) ||
27393 + !(td->options & NAND_BBT_WRITE)) {
27394 + if (td->pages[i] == -1) continue;
27395 + block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
27397 + oldval = this->bbt[(block >> 3)];
27398 + newval = oldval | (0x2 << (block & 0x06));
27399 + this->bbt[(block >> 3)] = newval;
27400 + if ((oldval != newval) && td->reserved_block_code)
27401 + nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1));
27405 + if (td->options & NAND_BBT_LASTBLOCK)
27406 + block = ((i + 1) * nrblocks) - td->maxblocks;
27408 + block = i * nrblocks;
27410 + for (j = 0; j < td->maxblocks; j++) {
27411 + oldval = this->bbt[(block >> 3)];
27412 + newval = oldval | (0x2 << (block & 0x06));
27413 + this->bbt[(block >> 3)] = newval;
27414 + if (oldval != newval) update = 1;
27417 + /* If we want reserved blocks to be recorded to flash, and some
27418 + new ones have been marked, then we need to update the stored
27419 + bbts. This should only happen once. */
27420 + if (update && td->reserved_block_code)
27421 + nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1));
27426 + * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s)
27427 + * @mtd: MTD device structure
27428 + * @bd: descriptor for the good/bad block search pattern
27430 + * The function checks, if a bad block table(s) is/are already
27431 + * available. If not it scans the device for manufacturer
27432 + * marked good / bad blocks and writes the bad block table(s) to
27433 + * the selected place.
27435 + * The bad block table memory is allocated here. It must be freed
27436 + * by calling the nand_free_bbt function.
27439 +int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
27441 + struct nand_chip *this = mtd->priv;
27442 + int len, res = 0;
27444 + struct nand_bbt_descr *td = this->bbt_td;
27445 + struct nand_bbt_descr *md = this->bbt_md;
27447 + len = mtd->size >> (this->bbt_erase_shift + 2);
27448 + /* Allocate memory (2bit per block) */
27449 + this->bbt = (uint8_t *) kmalloc (len, GFP_KERNEL);
27450 + if (!this->bbt) {
27451 + printk (KERN_ERR "nand_scan_bbt: Out of memory\n");
27454 + /* Clear the memory bad block table */
27455 + memset (this->bbt, 0x00, len);
27457 + /* If no primary table decriptor is given, scan the device
27458 + * to build a memory based bad block table
27461 + return nand_memory_bbt(mtd, bd);
27463 + /* Allocate a temporary buffer for one eraseblock incl. oob */
27464 + len = (1 << this->bbt_erase_shift);
27465 + len += (len >> this->page_shift) * mtd->oobsize;
27466 + buf = kmalloc (len, GFP_KERNEL);
27468 + printk (KERN_ERR "nand_bbt: Out of memory\n");
27469 + kfree (this->bbt);
27470 + this->bbt = NULL;
27474 + /* Is the bbt at a given page ? */
27475 + if (td->options & NAND_BBT_ABSPAGE) {
27476 + res = read_abs_bbts (mtd, buf, td, md);
27478 + /* Search the bad block table using a pattern in oob */
27479 + res = search_read_bbts (mtd, buf, td, md);
27483 + res = check_create (mtd, buf, bd);
27485 + /* Prevent the bbt regions from erasing / writing */
27486 + mark_bbt_region (mtd, td);
27488 + mark_bbt_region (mtd, md);
27496 + * nand_update_bbt - [NAND Interface] update bad block table(s)
27497 + * @mtd: MTD device structure
27498 + * @offs: the offset of the newly marked block
27500 + * The function updates the bad block table(s)
27502 +int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
27504 + struct nand_chip *this = mtd->priv;
27505 + int len, res = 0, writeops = 0;
27506 + int chip, chipsel;
27508 + struct nand_bbt_descr *td = this->bbt_td;
27509 + struct nand_bbt_descr *md = this->bbt_md;
27511 + if (!this->bbt || !td)
27514 + len = mtd->size >> (this->bbt_erase_shift + 2);
27515 + /* Allocate a temporary buffer for one eraseblock incl. oob */
27516 + len = (1 << this->bbt_erase_shift);
27517 + len += (len >> this->page_shift) * mtd->oobsize;
27518 + buf = kmalloc (len, GFP_KERNEL);
27520 + printk (KERN_ERR "nand_update_bbt: Out of memory\n");
27524 + writeops = md != NULL ? 0x03 : 0x01;
27526 + /* Do we have a bbt per chip ? */
27527 + if (td->options & NAND_BBT_PERCHIP) {
27528 + chip = (int) (offs >> this->chip_shift);
27535 + td->version[chip]++;
27537 + md->version[chip]++;
27539 + /* Write the bad block table to the device ? */
27540 + if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
27541 + res = write_bbt (mtd, buf, td, md, chipsel);
27545 + /* Write the mirror bad block table to the device ? */
27546 + if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
27547 + res = write_bbt (mtd, buf, md, td, chipsel);
27555 +/* Define some generic bad / good block scan pattern which are used
27556 + * while scanning a device for factory marked good / bad blocks
27558 + * The memory based patterns just
27560 +static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
27562 +static struct nand_bbt_descr smallpage_memorybased = {
27566 + .pattern = scan_ff_pattern
27569 +static struct nand_bbt_descr largepage_memorybased = {
27573 + .pattern = scan_ff_pattern
27576 +static struct nand_bbt_descr smallpage_flashbased = {
27577 + .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
27580 + .pattern = scan_ff_pattern
27583 +static struct nand_bbt_descr largepage_flashbased = {
27584 + .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
27587 + .pattern = scan_ff_pattern
27590 +static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
27592 +static struct nand_bbt_descr agand_flashbased = {
27593 + .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
27596 + .pattern = scan_agand_pattern
27599 +/* Generic flash bbt decriptors
27601 +static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
27602 +static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
27604 +static struct nand_bbt_descr bbt_main_descr = {
27605 + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
27606 + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
27611 + .pattern = bbt_pattern
27614 +static struct nand_bbt_descr bbt_mirror_descr = {
27615 + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
27616 + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
27621 + .pattern = mirror_pattern
27625 + * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
27626 + * @mtd: MTD device structure
27628 + * This function selects the default bad block table
27629 + * support for the device and calls the nand_scan_bbt function
27632 +int nand_default_bbt (struct mtd_info *mtd)
27634 + struct nand_chip *this = mtd->priv;
27636 + /* Default for AG-AND. We must use a flash based
27637 + * bad block table as the devices have factory marked
27638 + * _good_ blocks. Erasing those blocks leads to loss
27639 + * of the good / bad information, so we _must_ store
27640 + * this information in a good / bad table during
27643 + if (this->options & NAND_IS_AND) {
27644 + /* Use the default pattern descriptors */
27645 + if (!this->bbt_td) {
27646 + this->bbt_td = &bbt_main_descr;
27647 + this->bbt_md = &bbt_mirror_descr;
27649 + this->options |= NAND_USE_FLASH_BBT;
27650 + return nand_scan_bbt (mtd, &agand_flashbased);
27653 + /* Is a flash based bad block table requested ? */
27654 + if (this->options & NAND_USE_FLASH_BBT) {
27655 + /* Use the default pattern descriptors */
27656 + if (!this->bbt_td) {
27657 + this->bbt_td = &bbt_main_descr;
27658 + this->bbt_md = &bbt_mirror_descr;
27660 + if (mtd->oobblock > 512)
27661 + return nand_scan_bbt (mtd, &largepage_flashbased);
27663 + return nand_scan_bbt (mtd, &smallpage_flashbased);
27665 + this->bbt_td = NULL;
27666 + this->bbt_md = NULL;
27667 + if (mtd->oobblock > 512)
27668 + return nand_scan_bbt (mtd, &largepage_memorybased);
27670 + return nand_scan_bbt (mtd, &smallpage_memorybased);
27675 + * nand_isbad_bbt - [NAND Interface] Check if a block is bad
27676 + * @mtd: MTD device structure
27677 + * @offs: offset in the device
27678 + * @allowbbt: allow access to bad block table region
27681 +int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
27683 + struct nand_chip *this = mtd->priv;
27687 + /* Get block number * 2 */
27688 + block = (int) (offs >> (this->bbt_erase_shift - 1));
27689 + res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
27691 + DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
27692 + (unsigned int)offs, res, block >> 1);
27694 + switch ((int)res) {
27695 + case 0x00: return 0;
27696 + case 0x01: return 1;
27697 + case 0x02: return allowbbt ? 0 : 1;
27702 +EXPORT_SYMBOL (nand_scan_bbt);
27703 +EXPORT_SYMBOL (nand_default_bbt);
27704 Index: linux-2.6.5/drivers/mtd/nand/nand_ecc.c
27705 ===================================================================
27706 --- linux-2.6.5.orig/drivers/mtd/nand/nand_ecc.c 2004-04-03 22:36:54.000000000 -0500
27707 +++ linux-2.6.5/drivers/mtd/nand/nand_ecc.c 2005-02-01 17:11:17.000000000 -0500
27710 - * drivers/mtd/nand_ecc.c
27711 + * This file contains an ECC algorithm from Toshiba that detects and
27712 + * corrects 1 bit errors in a 256 byte block of data.
27714 - * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
27715 - * Toshiba America Electronics Components, Inc.
27716 + * drivers/mtd/nand/nand_ecc.c
27718 - * $Id: nand_ecc.c,v 1.9 2003/02/20 13:34:19 sjhill Exp $
27719 + * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
27720 + * Toshiba America Electronics Components, Inc.
27722 - * This program is free software; you can redistribute it and/or
27723 - * modify it under the terms of the GNU Lesser General Public License
27724 - * version 2.1 as published by the Free Software Foundation.
27725 + * $Id: nand_ecc.c,v 1.14 2004/06/16 15:34:37 gleixner Exp $
27727 - * This file contains an ECC algorithm from Toshiba that detects and
27728 - * corrects 1 bit errors in a 256 byte block of data.
27729 + * This file is free software; you can redistribute it and/or modify it
27730 + * under the terms of the GNU General Public License as published by the
27731 + * Free Software Foundation; either version 2 or (at your option) any
27734 + * This file is distributed in the hope that it will be useful, but WITHOUT
27735 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
27736 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27737 + * for more details.
27739 + * You should have received a copy of the GNU General Public License along
27740 + * with this file; if not, write to the Free Software Foundation, Inc.,
27741 + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27743 + * As a special exception, if other files instantiate templates or use
27744 + * macros or inline functions from these files, or you compile these
27745 + * files and link them with other works to produce a work based on these
27746 + * files, these files do not by themselves cause the resulting work to be
27747 + * covered by the GNU General Public License. However the source code for
27748 + * these files must still be made available in accordance with section (3)
27749 + * of the GNU General Public License.
27751 + * This exception does not invalidate any other reasons why a work based on
27752 + * this file might be covered by the GNU General Public License.
27755 #include <linux/types.h>
27756 #include <linux/kernel.h>
27757 #include <linux/module.h>
27758 +#include <linux/mtd/nand_ecc.h>
27761 * Pre-calculated 256-way 1 byte column parity
27768 + * nand_trans_result - [GENERIC] create non-inverted ECC
27769 + * @reg2: line parity reg 2
27770 + * @reg3: line parity reg 3
27773 * Creates non-inverted ECC code from line parity
27775 static void nand_trans_result(u_char reg2, u_char reg3,
27776 @@ -81,10 +108,13 @@
27777 ecc_code[1] = tmp2;
27781 - * Calculate 3 byte ECC code for 256 byte block
27783 + * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block
27784 + * @mtd: MTD block structure
27786 + * @ecc_code: buffer for ECC
27788 -void nand_calculate_ecc (const u_char *dat, u_char *ecc_code)
27789 +int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
27791 u_char idx, reg1, reg2, reg3;
27793 @@ -114,12 +144,19 @@
27794 ecc_code[0] = ~ecc_code[0];
27795 ecc_code[1] = ~ecc_code[1];
27796 ecc_code[2] = ((~reg1) << 2) | 0x03;
27802 + * nand_correct_data - [NAND Interface] Detect and correct bit error(s)
27803 + * @mtd: MTD block structure
27804 + * @dat: raw data read from the chip
27805 + * @read_ecc: ECC from the chip
27806 + * @calc_ecc: the ECC calculated from raw data
27808 * Detect and correct a 1 bit error for 256 byte block
27810 -int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc)
27811 +int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
27813 u_char a, b, c, d1, d2, d3, add, bit, i;
27815 Index: linux-2.6.5/drivers/mtd/nand/nand_ids.c
27816 ===================================================================
27817 --- linux-2.6.5.orig/drivers/mtd/nand/nand_ids.c 2004-04-03 22:36:56.000000000 -0500
27818 +++ linux-2.6.5/drivers/mtd/nand/nand_ids.c 2005-02-01 17:11:17.000000000 -0500
27820 * drivers/mtd/nandids.c
27822 * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
27825 - * $Id: nand_ids.c,v 1.4 2003/05/21 15:15:08 dwmw2 Exp $
27827 + * $Id: nand_ids.c,v 1.10 2004/05/26 13:40:12 gleixner Exp $
27829 * This program is free software; you can redistribute it and/or modify
27830 * it under the terms of the GNU General Public License version 2 as
27831 @@ -13,26 +12,99 @@
27833 #include <linux/module.h>
27834 #include <linux/mtd/nand.h>
27839 +* Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
27842 +* Pagesize; 0, 256, 512
27843 +* 0 get this information from the extended chip ID
27844 ++ 256 256 Byte page size
27845 +* 512 512 Byte page size
27847 struct nand_flash_dev nand_flash_ids[] = {
27848 - {"NAND 1MiB 5V", 0x6e, 20, 0x1000, 1},
27849 - {"NAND 2MiB 5V", 0x64, 21, 0x1000, 1},
27850 - {"NAND 4MiB 5V", 0x6b, 22, 0x2000, 0},
27851 - {"NAND 1MiB 3,3V", 0xe8, 20, 0x1000, 1},
27852 - {"NAND 1MiB 3,3V", 0xec, 20, 0x1000, 1},
27853 - {"NAND 2MiB 3,3V", 0xea, 21, 0x1000, 1},
27854 - {"NAND 4MiB 3,3V", 0xd5, 22, 0x2000, 0},
27855 - {"NAND 4MiB 3,3V", 0xe3, 22, 0x2000, 0},
27856 - {"NAND 4MiB 3,3V", 0xe5, 22, 0x2000, 0},
27857 - {"NAND 8MiB 3,3V", 0xd6, 23, 0x2000, 0},
27858 - {"NAND 8MiB 3,3V", 0xe6, 23, 0x2000, 0},
27859 - {"NAND 16MiB 3,3V", 0x73, 24, 0x4000, 0},
27860 - {"NAND 32MiB 3,3V", 0x75, 25, 0x4000, 0},
27861 - {"NAND 64MiB 3,3V", 0x76, 26, 0x4000, 0},
27862 - {"NAND 128MiB 3,3V", 0x79, 27, 0x4000, 0},
27863 + {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0},
27864 + {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0},
27865 + {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0},
27866 + {"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0},
27867 + {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0},
27868 + {"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0},
27869 + {"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0},
27870 + {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0},
27871 + {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0},
27872 + {"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0},
27874 + {"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0},
27875 + {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0},
27876 + {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
27877 + {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
27879 + {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0},
27880 + {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0},
27881 + {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
27882 + {"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
27884 + {"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0},
27885 + {"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0},
27886 + {"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
27887 + {"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
27889 + {"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0},
27890 + {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0},
27891 + {"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
27892 + {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
27894 + {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0},
27895 + {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0},
27896 + {"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
27897 + {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
27899 + {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0},
27901 + {"NAND 512MiB 3,3V 8-bit", 0xDC, 512, 512, 0x4000, 0},
27903 + /* These are the new chips with large page size. The pagesize
27904 + * and the erasesize is determined from the extended id bytes
27907 + {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
27908 + {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
27909 + {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
27910 + {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
27913 + {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
27914 + {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
27915 + {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
27916 + {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
27919 + {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
27920 + {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
27921 + {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
27922 + {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
27925 + {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
27926 + {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
27927 + {"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
27928 + {"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
27931 + {"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
27932 + {"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
27933 + {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
27934 + {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
27936 + /* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout !
27937 + * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes
27938 + * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7
27939 + * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
27940 + * There are more speed improvements for reads and writes possible, but not implemented now
27942 + {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},
27947 @@ -44,10 +116,11 @@
27948 {NAND_MFR_SAMSUNG, "Samsung"},
27949 {NAND_MFR_FUJITSU, "Fujitsu"},
27950 {NAND_MFR_NATIONAL, "National"},
27951 + {NAND_MFR_RENESAS, "Renesas"},
27952 + {NAND_MFR_STMICRO, "ST Micro"},
27957 EXPORT_SYMBOL (nand_manuf_ids);
27958 EXPORT_SYMBOL (nand_flash_ids);
27960 Index: linux-2.6.5/drivers/mtd/nand/ppchameleonevb.c
27961 ===================================================================
27962 --- linux-2.6.5.orig/drivers/mtd/nand/ppchameleonevb.c 1969-12-31 19:00:00.000000000 -0500
27963 +++ linux-2.6.5/drivers/mtd/nand/ppchameleonevb.c 2005-02-01 17:11:17.000000000 -0500
27966 + * drivers/mtd/nand/ppchameleonevb.c
27968 + * Copyright (C) 2003 DAVE Srl (info@wawnet.biz)
27970 + * Derived from drivers/mtd/nand/edb7312.c
27973 + * $Id: ppchameleonevb.c,v 1.3 2004/09/16 23:27:14 gleixner Exp $
27975 + * This program is free software; you can redistribute it and/or modify
27976 + * it under the terms of the GNU General Public License version 2 as
27977 + * published by the Free Software Foundation.
27980 + * This is a device driver for the NAND flash devices found on the
27981 + * PPChameleon/PPChameleonEVB system.
27982 + * PPChameleon options (autodetected):
27983 + * - BA model: no NAND
27984 + * - ME model: 32MB (Samsung K9F5608U0B)
27985 + * - HI model: 128MB (Samsung K9F1G08UOM)
27986 + * PPChameleonEVB options:
27987 + * - 32MB (Samsung K9F5608U0B)
27990 +#include <linux/init.h>
27991 +#include <linux/slab.h>
27992 +#include <linux/module.h>
27993 +#include <linux/mtd/mtd.h>
27994 +#include <linux/mtd/nand.h>
27995 +#include <linux/mtd/partitions.h>
27996 +#include <asm/io.h>
27997 +#include <platforms/PPChameleonEVB.h>
27999 +#undef USE_READY_BUSY_PIN
28000 +#define USE_READY_BUSY_PIN
28001 +/* see datasheets (tR) */
28002 +#define NAND_BIG_DELAY_US 25
28003 +#define NAND_SMALL_DELAY_US 10
28006 +#define SZ_4M 0x00400000
28007 +#define NAND_SMALL_SIZE 0x02000000
28008 +#define NAND_MTD_NAME "ppchameleon-nand"
28009 +#define NAND_EVB_MTD_NAME "ppchameleonevb-nand"
28011 +/* GPIO pins used to drive NAND chip mounted on processor module */
28012 +#define NAND_nCE_GPIO_PIN (0x80000000 >> 1)
28013 +#define NAND_CLE_GPIO_PIN (0x80000000 >> 2)
28014 +#define NAND_ALE_GPIO_PIN (0x80000000 >> 3)
28015 +#define NAND_RB_GPIO_PIN (0x80000000 >> 4)
28016 +/* GPIO pins used to drive NAND chip mounted on EVB */
28017 +#define NAND_EVB_nCE_GPIO_PIN (0x80000000 >> 14)
28018 +#define NAND_EVB_CLE_GPIO_PIN (0x80000000 >> 15)
28019 +#define NAND_EVB_ALE_GPIO_PIN (0x80000000 >> 16)
28020 +#define NAND_EVB_RB_GPIO_PIN (0x80000000 >> 31)
28023 + * MTD structure for PPChameleonEVB board
28025 +static struct mtd_info *ppchameleon_mtd = NULL;
28026 +static struct mtd_info *ppchameleonevb_mtd = NULL;
28031 +static int ppchameleon_fio_pbase = CFG_NAND0_PADDR;
28032 +static int ppchameleonevb_fio_pbase = CFG_NAND1_PADDR;
28035 +MODULE_PARM(ppchameleon_fio_pbase, "i");
28036 +__setup("ppchameleon_fio_pbase=",ppchameleon_fio_pbase);
28037 +MODULE_PARM(ppchameleonevb_fio_pbase, "i");
28038 +__setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase);
28041 +#ifdef CONFIG_MTD_PARTITIONS
28043 + * Define static partitions for flash devices
28045 +static struct mtd_partition partition_info_hi[] = {
28046 + { name: "PPChameleon HI Nand Flash",
28048 + size: 128*1024*1024 }
28051 +static struct mtd_partition partition_info_me[] = {
28052 + { name: "PPChameleon ME Nand Flash",
28054 + size: 32*1024*1024 }
28057 +static struct mtd_partition partition_info_evb[] = {
28058 + { name: "PPChameleonEVB Nand Flash",
28060 + size: 32*1024*1024 }
28063 +#define NUM_PARTITIONS 1
28065 +extern int parse_cmdline_partitions(struct mtd_info *master,
28066 + struct mtd_partition **pparts,
28067 + const char *mtd_id);
28072 + * hardware specific access to control-lines
28074 +static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd)
28078 + case NAND_CTL_SETCLE:
28079 + MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
28081 + case NAND_CTL_CLRCLE:
28082 + MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
28084 + case NAND_CTL_SETALE:
28085 + MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
28087 + case NAND_CTL_CLRALE:
28088 + MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
28090 + case NAND_CTL_SETNCE:
28091 + MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
28093 + case NAND_CTL_CLRNCE:
28094 + MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
28099 +static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
28103 + case NAND_CTL_SETCLE:
28104 + MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
28106 + case NAND_CTL_CLRCLE:
28107 + MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
28109 + case NAND_CTL_SETALE:
28110 + MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
28112 + case NAND_CTL_CLRALE:
28113 + MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
28115 + case NAND_CTL_SETNCE:
28116 + MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
28118 + case NAND_CTL_CLRNCE:
28119 + MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
28124 +#ifdef USE_READY_BUSY_PIN
28126 + * read device ready pin
28128 +static int ppchameleon_device_ready(struct mtd_info *minfo)
28130 + if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_RB_GPIO_PIN)
28135 +static int ppchameleonevb_device_ready(struct mtd_info *minfo)
28137 + if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
28143 +#ifdef CONFIG_MTD_PARTITIONS
28144 +const char *part_probes[] = { "cmdlinepart", NULL };
28145 +const char *part_probes_evb[] = { "cmdlinepart", NULL };
28149 + * Main initialization routine
28151 +static int __init ppchameleonevb_init (void)
28153 + struct nand_chip *this;
28154 + const char *part_type = 0;
28155 + int mtd_parts_nb = 0;
28156 + struct mtd_partition *mtd_parts = 0;
28157 + void __iomem *ppchameleon_fio_base;
28158 + void __iomem *ppchameleonevb_fio_base;
28161 + /*********************************
28162 + * Processor module NAND (if any) *
28163 + *********************************/
28164 + /* Allocate memory for MTD device structure and private data */
28165 + ppchameleon_mtd = (struct mtd_info *) kmalloc(sizeof(struct mtd_info) +
28166 + sizeof(struct nand_chip), GFP_KERNEL);
28167 + if (!ppchameleon_mtd) {
28168 + printk("Unable to allocate PPChameleon NAND MTD device structure.\n");
28172 + /* map physical address */
28173 + ppchameleon_fio_base = (void __iomem *) ioremap(ppchameleon_fio_pbase, SZ_4M);
28174 + if(!ppchameleon_fio_base) {
28175 + printk("ioremap PPChameleon NAND flash failed\n");
28176 + kfree(ppchameleon_mtd);
28180 + /* Get pointer to private data */
28181 + this = (struct nand_chip *) (&ppchameleon_mtd[1]);
28183 + /* Initialize structures */
28184 + memset((char *) ppchameleon_mtd, 0, sizeof(struct mtd_info));
28185 + memset((char *) this, 0, sizeof(struct nand_chip));
28187 + /* Link the private data with the MTD structure */
28188 + ppchameleon_mtd->priv = this;
28190 + /* Initialize GPIOs */
28191 + /* Pin mapping for NAND chip */
28198 + /* output select */
28199 + out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xC0FFFFFF);
28200 + /* three-state select */
28201 + out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xC0FFFFFF);
28202 + /* enable output driver */
28203 + out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
28204 +#ifdef USE_READY_BUSY_PIN
28205 + /* three-state select */
28206 + out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFF3FFFFF);
28207 + /* high-impedecence */
28208 + out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
28209 + /* input select */
28210 + out_be32((volatile unsigned*)GPIO0_ISR1H, (in_be32((volatile unsigned*)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
28213 + /* insert callbacks */
28214 + this->IO_ADDR_R = ppchameleon_fio_base;
28215 + this->IO_ADDR_W = ppchameleon_fio_base;
28216 + this->hwcontrol = ppchameleon_hwcontrol;
28217 +#ifdef USE_READY_BUSY_PIN
28218 + this->dev_ready = ppchameleon_device_ready;
28220 + this->chip_delay = NAND_BIG_DELAY_US;
28222 + this->eccmode = NAND_ECC_SOFT;
28224 + /* Scan to find existence of the device (it could not be mounted) */
28225 + if (nand_scan (ppchameleon_mtd, 1)) {
28226 + iounmap((void *)ppchameleon_fio_base);
28227 + kfree (ppchameleon_mtd);
28228 + goto nand_evb_init;
28231 +#ifndef USE_READY_BUSY_PIN
28232 + /* Adjust delay if necessary */
28233 + if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
28234 + this->chip_delay = NAND_SMALL_DELAY_US;
28237 +#ifdef CONFIG_MTD_PARTITIONS
28238 + ppchameleon_mtd->name = "ppchameleon-nand";
28239 + mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0);
28240 + if (mtd_parts_nb > 0)
28241 + part_type = "command line";
28243 + mtd_parts_nb = 0;
28245 + if (mtd_parts_nb == 0)
28247 + if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
28248 + mtd_parts = partition_info_me;
28250 + mtd_parts = partition_info_hi;
28251 + mtd_parts_nb = NUM_PARTITIONS;
28252 + part_type = "static";
28255 + /* Register the partitions */
28256 + printk(KERN_NOTICE "Using %s partition definition\n", part_type);
28257 + add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
28260 + /****************************
28261 + * EVB NAND (always present) *
28262 + ****************************/
28263 + /* Allocate memory for MTD device structure and private data */
28264 + ppchameleonevb_mtd = (struct mtd_info *) kmalloc(sizeof(struct mtd_info) +
28265 + sizeof(struct nand_chip), GFP_KERNEL);
28266 + if (!ppchameleonevb_mtd) {
28267 + printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n");
28271 + /* map physical address */
28272 + ppchameleonevb_fio_base = (void __iomem *)ioremap(ppchameleonevb_fio_pbase, SZ_4M);
28273 + if(!ppchameleonevb_fio_base) {
28274 + printk("ioremap PPChameleonEVB NAND flash failed\n");
28275 + kfree(ppchameleonevb_mtd);
28279 + /* Get pointer to private data */
28280 + this = (struct nand_chip *) (&ppchameleonevb_mtd[1]);
28282 + /* Initialize structures */
28283 + memset((char *) ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
28284 + memset((char *) this, 0, sizeof(struct nand_chip));
28286 + /* Link the private data with the MTD structure */
28287 + ppchameleonevb_mtd->priv = this;
28289 + /* Initialize GPIOs */
28290 + /* Pin mapping for NAND chip */
28297 + /* output select */
28298 + out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xFFFFFFF0);
28299 + out_be32((volatile unsigned*)GPIO0_OSRL, in_be32((volatile unsigned*)GPIO0_OSRL) & 0x3FFFFFFF);
28300 + /* three-state select */
28301 + out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0);
28302 + out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF);
28303 + /* enable output driver */
28304 + out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
28305 + NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN);
28306 +#ifdef USE_READY_BUSY_PIN
28307 + /* three-state select */
28308 + out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC);
28309 + /* high-impedecence */
28310 + out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
28311 + /* input select */
28312 + out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
28315 + /* insert callbacks */
28316 + this->IO_ADDR_R = ppchameleonevb_fio_base;
28317 + this->IO_ADDR_W = ppchameleonevb_fio_base;
28318 + this->hwcontrol = ppchameleonevb_hwcontrol;
28319 +#ifdef USE_READY_BUSY_PIN
28320 + this->dev_ready = ppchameleonevb_device_ready;
28322 + this->chip_delay = NAND_SMALL_DELAY_US;
28325 + this->eccmode = NAND_ECC_SOFT;
28327 + /* Scan to find existence of the device */
28328 + if (nand_scan (ppchameleonevb_mtd, 1)) {
28329 + iounmap((void *)ppchameleonevb_fio_base);
28330 + kfree (ppchameleonevb_mtd);
28334 +#ifdef CONFIG_MTD_PARTITIONS
28335 + ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
28336 + mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0);
28337 + if (mtd_parts_nb > 0)
28338 + part_type = "command line";
28340 + mtd_parts_nb = 0;
28342 + if (mtd_parts_nb == 0)
28344 + mtd_parts = partition_info_evb;
28345 + mtd_parts_nb = NUM_PARTITIONS;
28346 + part_type = "static";
28349 + /* Register the partitions */
28350 + printk(KERN_NOTICE "Using %s partition definition\n", part_type);
28351 + add_mtd_partitions(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb);
28353 + /* Return happy */
28356 +module_init(ppchameleonevb_init);
28359 + * Clean up routine
28361 +static void __exit ppchameleonevb_cleanup (void)
28363 + struct nand_chip *this;
28365 + /* Release resources, unregister device(s) */
28366 + nand_release (ppchameleon_mtd);
28367 + nand_release (ppchameleonevb_mtd);
28369 + /* Release iomaps */
28370 + this = (struct nand_chip *) &ppchameleon_mtd[1];
28371 + iounmap((void *) this->IO_ADDR_R;
28372 + this = (struct nand_chip *) &ppchameleonevb_mtd[1];
28373 + iounmap((void *) this->IO_ADDR_R;
28375 + /* Free the MTD device structure */
28376 + kfree (ppchameleon_mtd);
28377 + kfree (ppchameleonevb_mtd);
28379 +module_exit(ppchameleonevb_cleanup);
28381 +MODULE_LICENSE("GPL");
28382 +MODULE_AUTHOR("DAVE Srl <support-ppchameleon@dave-tech.it>");
28383 +MODULE_DESCRIPTION("MTD map driver for DAVE Srl PPChameleonEVB board");
28384 Index: linux-2.6.5/drivers/mtd/nand/rtc_from4.c
28385 ===================================================================
28386 --- linux-2.6.5.orig/drivers/mtd/nand/rtc_from4.c 1969-12-31 19:00:00.000000000 -0500
28387 +++ linux-2.6.5/drivers/mtd/nand/rtc_from4.c 2005-02-01 17:11:17.000000000 -0500
28390 + * drivers/mtd/nand/rtc_from4.c
28392 + * Copyright (C) 2004 Red Hat, Inc.
28394 + * Derived from drivers/mtd/nand/spia.c
28395 + * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
28397 + * $Id: rtc_from4.c,v 1.1 2004/09/16 23:23:42 gleixner Exp $
28399 + * This program is free software; you can redistribute it and/or modify
28400 + * it under the terms of the GNU General Public License version 2 as
28401 + * published by the Free Software Foundation.
28404 + * This is a device driver for the AG-AND flash device found on the
28405 + * Renesas Technology Corp. Flash ROM 4-slot interface board (FROM_BOARD4),
28406 + * which utilizes the Renesas HN29V1G91T-30 part.
28407 + * This chip is a 1 GBibit (128MiB x 8 bits) AG-AND flash device.
28410 +#include <linux/delay.h>
28411 +#include <linux/kernel.h>
28412 +#include <linux/init.h>
28413 +#include <linux/slab.h>
28414 +#include <linux/rslib.h>
28415 +#include <linux/module.h>
28416 +#include <linux/mtd/compatmac.h>
28417 +#include <linux/mtd/mtd.h>
28418 +#include <linux/mtd/nand.h>
28419 +#include <linux/mtd/partitions.h>
28420 +#include <asm/io.h>
28423 + * MTD structure for Renesas board
28425 +static struct mtd_info *rtc_from4_mtd = NULL;
28427 +#define RTC_FROM4_MAX_CHIPS 2
28429 +/* HS77x9 processor register defines */
28430 +#define SH77X9_BCR1 ((volatile unsigned short *)(0xFFFFFF60))
28431 +#define SH77X9_BCR2 ((volatile unsigned short *)(0xFFFFFF62))
28432 +#define SH77X9_WCR1 ((volatile unsigned short *)(0xFFFFFF64))
28433 +#define SH77X9_WCR2 ((volatile unsigned short *)(0xFFFFFF66))
28434 +#define SH77X9_MCR ((volatile unsigned short *)(0xFFFFFF68))
28435 +#define SH77X9_PCR ((volatile unsigned short *)(0xFFFFFF6C))
28436 +#define SH77X9_FRQCR ((volatile unsigned short *)(0xFFFFFF80))
28439 + * Values specific to the Renesas Technology Corp. FROM_BOARD4 (used with HS77x9 processor)
28441 +/* Address where flash is mapped */
28442 +#define RTC_FROM4_FIO_BASE 0x14000000
28444 +/* CLE and ALE are tied to address lines 5 & 4, respectively */
28445 +#define RTC_FROM4_CLE (1 << 5)
28446 +#define RTC_FROM4_ALE (1 << 4)
28448 +/* address lines A24-A22 used for chip selection */
28449 +#define RTC_FROM4_NAND_ADDR_SLOT3 (0x00800000)
28450 +#define RTC_FROM4_NAND_ADDR_SLOT4 (0x00C00000)
28451 +#define RTC_FROM4_NAND_ADDR_FPGA (0x01000000)
28452 +/* mask address lines A24-A22 used for chip selection */
28453 +#define RTC_FROM4_NAND_ADDR_MASK (RTC_FROM4_NAND_ADDR_SLOT3 | RTC_FROM4_NAND_ADDR_SLOT4 | RTC_FROM4_NAND_ADDR_FPGA)
28455 +/* FPGA status register for checking device ready (bit zero) */
28456 +#define RTC_FROM4_FPGA_SR (RTC_FROM4_NAND_ADDR_FPGA | 0x00000002)
28457 +#define RTC_FROM4_DEVICE_READY 0x0001
28459 +/* FPGA Reed-Solomon ECC Control register */
28461 +#define RTC_FROM4_RS_ECC_CTL (RTC_FROM4_NAND_ADDR_FPGA | 0x00000050)
28462 +#define RTC_FROM4_RS_ECC_CTL_CLR (1 << 7)
28463 +#define RTC_FROM4_RS_ECC_CTL_GEN (1 << 6)
28464 +#define RTC_FROM4_RS_ECC_CTL_FD_E (1 << 5)
28466 +/* FPGA Reed-Solomon ECC code base */
28467 +#define RTC_FROM4_RS_ECC (RTC_FROM4_NAND_ADDR_FPGA | 0x00000060)
28468 +#define RTC_FROM4_RS_ECCN (RTC_FROM4_NAND_ADDR_FPGA | 0x00000080)
28470 +/* FPGA Reed-Solomon ECC check register */
28471 +#define RTC_FROM4_RS_ECC_CHK (RTC_FROM4_NAND_ADDR_FPGA | 0x00000070)
28472 +#define RTC_FROM4_RS_ECC_CHK_ERROR (1 << 7)
28474 +/* Undefine for software ECC */
28475 +#define RTC_FROM4_HWECC 1
28480 +static void __iomem *rtc_from4_fio_base = P2SEGADDR(RTC_FROM4_FIO_BASE);
28482 +MODULE_PARM(rtc_from4_fio_base, "i");
28484 +const static struct mtd_partition partition_info[] = {
28486 + .name = "Renesas flash partition 1",
28488 + .size = MTDPART_SIZ_FULL
28491 +#define NUM_PARTITIONS 1
28494 + * hardware specific flash bbt decriptors
28495 + * Note: this is to allow debugging by disabling
28496 + * NAND_BBT_CREATE and/or NAND_BBT_WRITE
28499 +static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
28500 +static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
28502 +static struct nand_bbt_descr rtc_from4_bbt_main_descr = {
28503 + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
28504 + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
28509 + .pattern = bbt_pattern
28512 +static struct nand_bbt_descr rtc_from4_bbt_mirror_descr = {
28513 + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
28514 + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
28519 + .pattern = mirror_pattern
28524 +#ifdef RTC_FROM4_HWECC
28526 +/* the Reed Solomon control structure */
28527 +static struct rs_control *rs_decoder;
28530 + * hardware specific Out Of Band information
28532 +static struct nand_oobinfo rtc_from4_nand_oobinfo = {
28533 + .useecc = MTD_NANDECC_AUTOPLACE,
28536 + 0, 1, 2, 3, 4, 5, 6, 7,
28537 + 8, 9, 10, 11, 12, 13, 14, 15,
28538 + 16, 17, 18, 19, 20, 21, 22, 23,
28539 + 24, 25, 26, 27, 28, 29, 30, 31},
28540 + .oobfree = { {32, 32} }
28547 + * rtc_from4_hwcontrol - hardware specific access to control-lines
28548 + * @mtd: MTD device structure
28549 + * @cmd: hardware control command
28551 + * Address lines (A5 and A4) are used to control Command and Address Latch
28552 + * Enable on this board, so set the read/write address appropriately.
28554 + * Chip Enable is also controlled by the Chip Select (CS5) and
28555 + * Address lines (A24-A22), so no action is required here.
28558 +static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
28560 + struct nand_chip* this = (struct nand_chip *) (mtd->priv);
28564 + case NAND_CTL_SETCLE:
28565 + this->IO_ADDR_W |= RTC_FROM4_CLE;
28567 + case NAND_CTL_CLRCLE:
28568 + this->IO_ADDR_W &= ~RTC_FROM4_CLE;
28571 + case NAND_CTL_SETALE:
28572 + this->IO_ADDR_W |= RTC_FROM4_ALE;
28574 + case NAND_CTL_CLRALE:
28575 + this->IO_ADDR_W &= ~RTC_FROM4_ALE;
28578 + case NAND_CTL_SETNCE:
28580 + case NAND_CTL_CLRNCE:
28588 + * rtc_from4_nand_select_chip - hardware specific chip select
28589 + * @mtd: MTD device structure
28590 + * @chip: Chip to select (0 == slot 3, 1 == slot 4)
28592 + * The chip select is based on address lines A24-A22.
28593 + * This driver uses flash slots 3 and 4 (A23-A22).
28596 +static void rtc_from4_nand_select_chip(struct mtd_info *mtd, int chip)
28598 + struct nand_chip *this = mtd->priv;
28600 + this->IO_ADDR_R &= ~RTC_FROM4_NAND_ADDR_MASK;
28601 + this->IO_ADDR_W &= ~RTC_FROM4_NAND_ADDR_MASK;
28605 + case 0: /* select slot 3 chip */
28606 + this->IO_ADDR_R |= RTC_FROM4_NAND_ADDR_SLOT3;
28607 + this->IO_ADDR_W |= RTC_FROM4_NAND_ADDR_SLOT3;
28609 + case 1: /* select slot 4 chip */
28610 + this->IO_ADDR_R |= RTC_FROM4_NAND_ADDR_SLOT4;
28611 + this->IO_ADDR_W |= RTC_FROM4_NAND_ADDR_SLOT4;
28620 + * rtc_from4_nand_device_ready - hardware specific ready/busy check
28621 + * @mtd: MTD device structure
28623 + * This board provides the Ready/Busy state in the status register
28624 + * of the FPGA. Bit zero indicates the RDY(1)/BSY(0) signal.
28627 +static int rtc_from4_nand_device_ready(struct mtd_info *mtd)
28629 + unsigned short status;
28631 + status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_FPGA_SR));
28633 + return (status & RTC_FROM4_DEVICE_READY);
28637 +#ifdef RTC_FROM4_HWECC
28639 + * rtc_from4_enable_hwecc - hardware specific hardware ECC enable function
28640 + * @mtd: MTD device structure
28641 + * @mode: I/O mode; read or write
28643 + * enable hardware ECC for data read or write
28646 +static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode)
28648 + volatile unsigned short * rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL);
28649 + unsigned short status;
28652 + case NAND_ECC_READ :
28653 + status = RTC_FROM4_RS_ECC_CTL_CLR
28654 + | RTC_FROM4_RS_ECC_CTL_FD_E;
28656 + *rs_ecc_ctl = status;
28659 + case NAND_ECC_READSYN :
28662 + *rs_ecc_ctl = status;
28665 + case NAND_ECC_WRITE :
28666 + status = RTC_FROM4_RS_ECC_CTL_CLR
28667 + | RTC_FROM4_RS_ECC_CTL_GEN
28668 + | RTC_FROM4_RS_ECC_CTL_FD_E;
28670 + *rs_ecc_ctl = status;
28681 + * rtc_from4_calculate_ecc - hardware specific code to read ECC code
28682 + * @mtd: MTD device structure
28683 + * @dat: buffer containing the data to generate ECC codes
28684 + * @ecc_code ECC codes calculated
28686 + * The ECC code is calculated by the FPGA. All we have to do is read the values
28687 + * from the FPGA registers.
28689 + * Note: We read from the inverted registers, since data is inverted before
28690 + * the code is calculated. So all 0xff data (blank page) results in all 0xff rs code
28693 +static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
28695 + volatile unsigned short * rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN);
28696 + unsigned short value;
28699 + for (i = 0; i < 8; i++) {
28700 + value = *rs_eccn;
28701 + ecc_code[i] = (unsigned char)value;
28704 + ecc_code[7] |= 0x0f; /* set the last four bits (not used) */
28709 + * rtc_from4_correct_data - hardware specific code to correct data using ECC code
28710 + * @mtd: MTD device structure
28711 + * @buf: buffer containing the data to generate ECC codes
28712 + * @ecc1 ECC codes read
28713 + * @ecc2 ECC codes calculated
28715 + * The FPGA tells us fast, if there's an error or not. If no, we go back happy
28716 + * else we read the ecc results from the fpga and call the rs library to decode
28717 + * and hopefully correct the error
28719 + * For now I use the code, which we read from the FLASH to use the RS lib,
28720 + * as the syndrom conversion has a unresolved issue.
28722 +static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2)
28725 + unsigned short status;
28726 + uint16_t rpar[6];
28728 + status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CHK));
28730 + if (!(status & RTC_FROM4_RS_ECC_CHK_ERROR))
28733 + /* convert into 6 10bit parity fields */
28734 + rpar[0] = ((uint16_t)ecc1[7] >> 4) | (((uint16_t)ecc1[6] << 4) & 0x3f0);
28735 + rpar[1] = ((uint16_t)ecc1[6] >> 6) | (((uint16_t)ecc1[5] << 2) & 0x3f3);
28736 + rpar[2] = ((uint16_t)ecc1[4] >> 0) | (((uint16_t)ecc1[3] << 8) & 0x300);
28737 + rpar[3] = ((uint16_t)ecc1[3] >> 2) | (((uint16_t)ecc1[2] << 6) & 0x3c0);
28738 + rpar[4] = ((uint16_t)ecc1[2] >> 4) | (((uint16_t)ecc1[1] << 4) & 0x3f0);
28739 + rpar[5] = ((uint16_t)ecc1[1] >> 6) | (((uint16_t)ecc1[0] << 2) & 0x3f3);
28741 + /* Invert the codes */
28742 + for (i = 0; i < 6; i++)
28743 + rpar[i] ^= 0x3ff;
28745 + /* Let the library code do its magic.
28746 + * Set the data inversion mask to 0xff, as the FPGA inverts data on read
28747 + * except for the virtual bits 9 /10 which are tied low
28749 + res = decode_rs8 (rs_decoder, buf, rpar, 512, NULL, 0, NULL, 0xff);
28751 + DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: "
28752 + "ECC corrected %d errors on read\n", res);
28759 + * Main initialization routine
28761 +int __init rtc_from4_init (void)
28763 + struct nand_chip *this;
28764 + unsigned short bcr1, bcr2, wcr2;
28766 + /* Allocate memory for MTD device structure and private data */
28767 + rtc_from4_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
28769 + if (!rtc_from4_mtd) {
28770 + printk ("Unable to allocate Renesas NAND MTD device structure.\n");
28774 + /* Get pointer to private data */
28775 + this = (struct nand_chip *) (&rtc_from4_mtd[1]);
28777 + /* Initialize structures */
28778 + memset((char *) rtc_from4_mtd, 0, sizeof(struct mtd_info));
28779 + memset((char *) this, 0, sizeof(struct nand_chip));
28781 + /* Link the private data with the MTD structure */
28782 + rtc_from4_mtd->priv = this;
28784 + /* set area 5 as PCMCIA mode to clear the spec of tDH(Data hold time;9ns min) */
28785 + bcr1 = *SH77X9_BCR1 & ~0x0002;
28787 + *SH77X9_BCR1 = bcr1;
28790 + bcr2 = *SH77X9_BCR2 & ~0x0c00;
28792 + *SH77X9_BCR2 = bcr2;
28794 + /* set area 5 wait states */
28795 + wcr2 = *SH77X9_WCR2 & ~0x1c00;
28797 + *SH77X9_WCR2 = wcr2;
28799 + /* Set address of NAND IO lines */
28800 + this->IO_ADDR_R = rtc_from4_fio_base;
28801 + this->IO_ADDR_W = rtc_from4_fio_base;
28802 + /* Set address of hardware control function */
28803 + this->hwcontrol = rtc_from4_hwcontrol;
28804 + /* Set address of chip select function */
28805 + this->select_chip = rtc_from4_nand_select_chip;
28806 + /* command delay time (in us) */
28807 + this->chip_delay = 100;
28808 + /* return the status of the Ready/Busy line */
28809 + this->dev_ready = rtc_from4_nand_device_ready;
28811 +#ifdef RTC_FROM4_HWECC
28812 + printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n");
28814 + this->eccmode = NAND_ECC_HW8_512;
28815 + this->options |= NAND_HWECC_SYNDROME;
28816 + /* set the nand_oobinfo to support FPGA H/W error detection */
28817 + this->autooob = &rtc_from4_nand_oobinfo;
28818 + this->enable_hwecc = rtc_from4_enable_hwecc;
28819 + this->calculate_ecc = rtc_from4_calculate_ecc;
28820 + this->correct_data = rtc_from4_correct_data;
28822 + printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
28824 + this->eccmode = NAND_ECC_SOFT;
28827 + /* set the bad block tables to support debugging */
28828 + this->bbt_td = &rtc_from4_bbt_main_descr;
28829 + this->bbt_md = &rtc_from4_bbt_mirror_descr;
28831 + /* Scan to find existence of the device */
28832 + if (nand_scan (rtc_from4_mtd, RTC_FROM4_MAX_CHIPS)) {
28833 + kfree (rtc_from4_mtd);
28837 + /* Register the partitions */
28838 + add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
28840 +#ifdef RTC_FROM4_HWECC
28841 + /* We could create the decoder on demand, if memory is a concern.
28842 + * This way we have it handy, if an error happens
28844 + * Symbolsize is 10 (bits)
28845 + * Primitve polynomial is x^10+x^3+1
28846 + * first consecutive root is 0
28847 + * primitve element to generate roots = 1
28848 + * generator polinomial degree = 6
28850 + rs_decoder = init_rs (10, 0x409, 0, 1, 6);
28851 + if (!rs_decoder) {
28852 + printk (KERN_ERROR "Could not create a RS decoder\n");
28853 + nand_release(rtc_from4_mtd);
28854 + kfree (rtc_from4_mtd);
28858 + /* Return happy */
28861 +module_init(rtc_from4_init);
28865 + * Clean up routine
28868 +static void __exit rtc_from4_cleanup (void)
28870 + /* Release resource, unregister partitions */
28871 + nand_release(rtc_from4_mtd);
28873 + /* Free the MTD device structure */
28874 + kfree (rtc_from4_mtd);
28876 +#ifdef RTC_FROM4_HWECC
28877 + /* Free the reed solomon resources */
28879 + free_rs(rs_decoder);
28882 +module_exit(rtc_from4_cleanup);
28885 +MODULE_LICENSE("GPL");
28886 +MODULE_AUTHOR("d.marlin <dmarlin@redhat.com");
28887 +MODULE_DESCRIPTION("Board-specific glue layer for AG-AND flash on Renesas FROM_BOARD4");
28889 Index: linux-2.6.5/drivers/mtd/nand/spia.c
28890 ===================================================================
28891 --- linux-2.6.5.orig/drivers/mtd/nand/spia.c 2004-04-03 22:37:23.000000000 -0500
28892 +++ linux-2.6.5/drivers/mtd/nand/spia.c 2005-02-01 17:11:17.000000000 -0500
28894 * to controllines (due to change in nand.c)
28897 - * $Id: spia.c,v 1.19 2003/04/20 07:24:40 gleixner Exp $
28898 + * $Id: spia.c,v 1.22 2004/09/16 23:27:14 gleixner Exp $
28900 * This program is free software; you can redistribute it and/or modify
28901 * it under the terms of the GNU General Public License version 2 as
28903 * a 64Mibit (8MiB x 8 bits) NAND flash device.
28906 +#include <linux/kernel.h>
28907 +#include <linux/init.h>
28908 #include <linux/slab.h>
28909 #include <linux/module.h>
28910 #include <linux/mtd/mtd.h>
28911 @@ -35,14 +37,14 @@
28913 * Values specific to the SPIA board (used with EP7212 processor)
28915 -#define SPIA_IO_ADDR = 0xd0000000 /* Start of EP7212 IO address space */
28916 -#define SPIA_FIO_ADDR = 0xf0000000 /* Address where flash is mapped */
28917 -#define SPIA_PEDR = 0x0080 /*
28918 +#define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */
28919 +#define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */
28920 +#define SPIA_PEDR 0x0080 /*
28921 * IO offset to Port E data register
28922 * where the CLE, ALE and NCE pins
28925 -#define SPIA_PEDDR = 0x00c0 /*
28926 +#define SPIA_PEDDR 0x00c0 /*
28927 * IO offset to Port E data direction
28928 * register so we can control the IO
28931 MODULE_PARM(spia_pedr, "i");
28932 MODULE_PARM(spia_peddr, "i");
28934 -__setup("spia_io_base=",spia_io_base);
28935 -__setup("spia_fio_base=",spia_fio_base);
28936 -__setup("spia_pedr=",spia_pedr);
28937 -__setup("spia_peddr=",spia_peddr);
28940 * Define partitions for flash device
28944 * hardware specific access to control-lines
28946 -void spia_hwcontrol(int cmd){
28947 +static void spia_hwcontrol(struct mtd_info *mtd, int cmd){
28951 @@ -111,7 +108,7 @@
28952 struct nand_chip *this;
28954 /* Allocate memory for MTD device structure and private data */
28955 - spia_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
28956 + spia_mtd = (struct mtd_info *) kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
28959 printk ("Unable to allocate SPIA NAND MTD device structure.\n");
28960 @@ -135,27 +132,19 @@
28961 (*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07;
28963 /* Set address of NAND IO lines */
28964 - this->IO_ADDR_R = spia_fio_base;
28965 - this->IO_ADDR_W = spia_fio_base;
28966 + this->IO_ADDR_R = (void __iomem *) spia_fio_base;
28967 + this->IO_ADDR_W = (void __iomem *) spia_fio_base;
28968 /* Set address of hardware control function */
28969 this->hwcontrol = spia_hwcontrol;
28970 /* 15 us command delay time */
28971 this->chip_delay = 15;
28973 /* Scan to find existence of the device */
28974 - if (nand_scan (spia_mtd)) {
28975 + if (nand_scan (spia_mtd, 1)) {
28980 - /* Allocate memory for internal data buffer */
28981 - this->data_buf = kmalloc (sizeof(u_char) * (spia_mtd->oobblock + spia_mtd->oobsize), GFP_KERNEL);
28982 - if (!this->data_buf) {
28983 - printk ("Unable to allocate NAND data buffer for SPIA.\n");
28984 - kfree (spia_mtd);
28988 /* Register the partitions */
28989 add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS);
28991 @@ -170,13 +159,8 @@
28993 static void __exit spia_cleanup (void)
28995 - struct nand_chip *this = (struct nand_chip *) &spia_mtd[1];
28997 - /* Unregister the device */
28998 - del_mtd_device (spia_mtd);
29000 - /* Free internal data buffer */
29001 - kfree (this->data_buf);
29002 + /* Release resources, unregister device */
29003 + nand_release (spia_mtd);
29005 /* Free the MTD device structure */
29007 Index: linux-2.6.5/drivers/mtd/nand/toto.c
29008 ===================================================================
29009 --- linux-2.6.5.orig/drivers/mtd/nand/toto.c 1969-12-31 19:00:00.000000000 -0500
29010 +++ linux-2.6.5/drivers/mtd/nand/toto.c 2005-02-01 17:11:17.000000000 -0500
29013 + * drivers/mtd/nand/toto.c
29015 + * Copyright (c) 2003 Texas Instruments
29017 + * Derived from drivers/mtd/autcpu12.c
29019 + * Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
29021 + * This program is free software; you can redistribute it and/or modify
29022 + * it under the terms of the GNU General Public License version 2 as
29023 + * published by the Free Software Foundation.
29026 + * This is a device driver for the NAND flash device found on the
29027 + * TI fido board. It supports 32MiB and 64MiB cards
29029 + * $Id: toto.c,v 1.3 2004/09/16 23:27:15 gleixner Exp $
29032 +#include <linux/slab.h>
29033 +#include <linux/init.h>
29034 +#include <linux/module.h>
29035 +#include <linux/delay.h>
29036 +#include <linux/mtd/mtd.h>
29037 +#include <linux/mtd/nand.h>
29038 +#include <linux/mtd/partitions.h>
29039 +#include <asm/io.h>
29040 +#include <asm/arch/hardware.h>
29041 +#include <asm/sizes.h>
29042 +#include <asm/arch/toto.h>
29043 +#include <asm/arch-omap1510/hardware.h>
29044 +#include <asm/arch/gpio.h>
29047 + * MTD structure for TOTO board
29049 +static struct mtd_info *toto_mtd = NULL;
29051 +static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
29053 +#define CONFIG_NAND_WORKAROUND 1
29055 +#define NAND_NCE 0x4000
29056 +#define NAND_CLE 0x1000
29057 +#define NAND_ALE 0x0002
29058 +#define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE)
29060 +#define T_NAND_CTL_CLRALE(iob) gpiosetout(NAND_ALE, 0)
29061 +#define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE)
29062 +#ifdef CONFIG_NAND_WORKAROUND /* "some" dev boards busted, blue wired to rts2 :( */
29063 +#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2)
29064 +#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0)
29066 +#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0)
29067 +#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE)
29069 +#define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0)
29070 +#define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE)
29073 + * Define partitions for flash devices
29076 +static struct mtd_partition partition_info64M[] = {
29077 + { .name = "toto kernel partition 1",
29079 + .size = 2 * SZ_1M },
29080 + { .name = "toto file sys partition 2",
29081 + .offset = 2 * SZ_1M,
29082 + .size = 14 * SZ_1M },
29083 + { .name = "toto user partition 3",
29084 + .offset = 16 * SZ_1M,
29085 + .size = 16 * SZ_1M },
29086 + { .name = "toto devboard extra partition 4",
29087 + .offset = 32 * SZ_1M,
29088 + .size = 32 * SZ_1M },
29091 +static struct mtd_partition partition_info32M[] = {
29092 + { .name = "toto kernel partition 1",
29094 + .size = 2 * SZ_1M },
29095 + { .name = "toto file sys partition 2",
29096 + .offset = 2 * SZ_1M,
29097 + .size = 14 * SZ_1M },
29098 + { .name = "toto user partition 3",
29099 + .offset = 16 * SZ_1M,
29100 + .size = 16 * SZ_1M },
29103 +#define NUM_PARTITIONS32M 3
29104 +#define NUM_PARTITIONS64M 4
29106 + * hardware specific access to control-lines
29109 +static void toto_hwcontrol(struct mtd_info *mtd, int cmd)
29112 + udelay(1); /* hopefully enough time for tc make proceding write to clear */
29115 + case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
29116 + case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
29118 + case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break;
29119 + case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break;
29121 + case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
29122 + case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
29124 + udelay(1); /* allow time to ensure gpio state to over take memory write */
29128 + * Main initialization routine
29130 +int __init toto_init (void)
29132 + struct nand_chip *this;
29135 + /* Allocate memory for MTD device structure and private data */
29136 + toto_mtd = (struct mtd_info *) kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
29139 + printk (KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
29144 + /* Get pointer to private data */
29145 + this = (struct nand_chip *) (&toto_mtd[1]);
29147 + /* Initialize structures */
29148 + memset((char *) toto_mtd, 0, sizeof(struct mtd_info));
29149 + memset((char *) this, 0, sizeof(struct nand_chip));
29151 + /* Link the private data with the MTD structure */
29152 + toto_mtd->priv = this;
29154 + /* Set address of NAND IO lines */
29155 + this->IO_ADDR_R = toto_io_base;
29156 + this->IO_ADDR_W = toto_io_base;
29157 + this->hwcontrol = toto_hwcontrol;
29158 + this->dev_ready = NULL;
29159 + /* 25 us command delay time */
29160 + this->chip_delay = 30;
29161 + this->eccmode = NAND_ECC_SOFT;
29163 + /* Scan to find existance of the device */
29164 + if (nand_scan (toto_mtd, 1)) {
29169 + /* Register the partitions */
29170 + switch(toto_mtd->size){
29171 + case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break;
29172 + case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break;
29174 + printk (KERN_WARNING "Unsupported Nand device\n");
29180 + gpioreserve(NAND_MASK); /* claim our gpios */
29181 + archflashwp(0,0); /* open up flash for writing */
29186 + kfree (this->data_buf);
29188 + kfree (toto_mtd);
29193 +module_init(toto_init);
29196 + * Clean up routine
29198 +static void __exit toto_cleanup (void)
29200 + /* Release resources, unregister device */
29201 + nand_release (toto_mtd);
29203 + /* Free the MTD device structure */
29204 + kfree (toto_mtd);
29206 + /* stop flash writes */
29207 + archflashwp(0,1);
29209 + /* release gpios to system */
29210 + gpiorelease(NAND_MASK);
29212 +module_exit(toto_cleanup);
29214 +MODULE_LICENSE("GPL");
29215 +MODULE_AUTHOR("Richard Woodruff <r-woodruff2@ti.com>");
29216 +MODULE_DESCRIPTION("Glue layer for NAND flash on toto board");
29217 Index: linux-2.6.5/drivers/mtd/nand/tx4925ndfmc.c
29218 ===================================================================
29219 --- linux-2.6.5.orig/drivers/mtd/nand/tx4925ndfmc.c 1969-12-31 19:00:00.000000000 -0500
29220 +++ linux-2.6.5/drivers/mtd/nand/tx4925ndfmc.c 2005-02-01 17:11:17.000000000 -0500
29223 + * drivers/mtd/tx4925ndfmc.c
29226 + * This is a device driver for the NAND flash device found on the
29227 + * Toshiba RBTX4925 reference board, which is a SmartMediaCard. It supports
29228 + * 16MiB, 32MiB and 64MiB cards.
29230 + * Author: MontaVista Software, Inc. source@mvista.com
29232 + * Derived from drivers/mtd/autcpu12.c
29233 + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
29235 + * $Id: tx4925ndfmc.c,v 1.4 2004/09/16 23:27:15 gleixner Exp $
29237 + * Copyright (C) 2001 Toshiba Corporation
29239 + * 2003 (c) MontaVista Software, Inc. This file is licensed under
29240 + * the terms of the GNU General Public License version 2. This program
29241 + * is licensed "as is" without any warranty of any kind, whether express
29246 +#include <linux/slab.h>
29247 +#include <linux/init.h>
29248 +#include <linux/module.h>
29249 +#include <linux/mtd/mtd.h>
29250 +#include <linux/mtd/nand.h>
29251 +#include <linux/mtd/partitions.h>
29252 +#include <linux/delay.h>
29253 +#include <asm/io.h>
29254 +#include <asm/tx4925/tx4925_nand.h>
29256 +extern struct nand_oobinfo jffs2_oobinfo;
29259 + * MTD structure for RBTX4925 board
29261 +static struct mtd_info *tx4925ndfmc_mtd = NULL;
29264 + * Define partitions for flash devices
29267 +static struct mtd_partition partition_info16k[] = {
29268 + { .name = "RBTX4925 flash partition 1",
29270 + .size = 8 * 0x00100000 },
29271 + { .name = "RBTX4925 flash partition 2",
29272 + .offset = 8 * 0x00100000,
29273 + .size = 8 * 0x00100000 },
29276 +static struct mtd_partition partition_info32k[] = {
29277 + { .name = "RBTX4925 flash partition 1",
29279 + .size = 8 * 0x00100000 },
29280 + { .name = "RBTX4925 flash partition 2",
29281 + .offset = 8 * 0x00100000,
29282 + .size = 24 * 0x00100000 },
29285 +static struct mtd_partition partition_info64k[] = {
29286 + { .name = "User FS",
29288 + .size = 16 * 0x00100000 },
29289 + { .name = "RBTX4925 flash partition 2",
29290 + .offset = 16 * 0x00100000,
29291 + .size = 48 * 0x00100000},
29294 +static struct mtd_partition partition_info128k[] = {
29295 + { .name = "Skip bad section",
29297 + .size = 16 * 0x00100000 },
29298 + { .name = "User FS",
29299 + .offset = 16 * 0x00100000,
29300 + .size = 112 * 0x00100000 },
29302 +#define NUM_PARTITIONS16K 2
29303 +#define NUM_PARTITIONS32K 2
29304 +#define NUM_PARTITIONS64K 2
29305 +#define NUM_PARTITIONS128K 2
29308 + * hardware specific access to control-lines
29310 +static void tx4925ndfmc_hwcontrol(struct mtd_info *mtd, int cmd)
29315 + case NAND_CTL_SETCLE:
29316 + tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CLE;
29318 + case NAND_CTL_CLRCLE:
29319 + tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CLE;
29321 + case NAND_CTL_SETALE:
29322 + tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ALE;
29324 + case NAND_CTL_CLRALE:
29325 + tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ALE;
29327 + case NAND_CTL_SETNCE:
29328 + tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CE;
29330 + case NAND_CTL_CLRNCE:
29331 + tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CE;
29333 + case NAND_CTL_SETWP:
29334 + tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_WE;
29336 + case NAND_CTL_CLRWP:
29337 + tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_WE;
29343 +* read device ready pin
29345 +static int tx4925ndfmc_device_ready(struct mtd_info *mtd)
29348 + ready = (tx4925_ndfmcptr->sr & TX4925_NDSFR_BUSY) ? 0 : 1;
29351 +void tx4925ndfmc_enable_hwecc(struct mtd_info *mtd, int mode)
29353 + /* reset first */
29354 + tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_MASK;
29355 + tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK;
29356 + tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_ENAB;
29358 +static void tx4925ndfmc_disable_ecc(void)
29360 + tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK;
29362 +static void tx4925ndfmc_enable_read_ecc(void)
29364 + tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK;
29365 + tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_READ;
29367 +void tx4925ndfmc_readecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code){
29369 + u_char *ecc = ecc_code;
29370 + tx4925ndfmc_enable_read_ecc();
29371 + for (i = 0;i < 6;i++,ecc++)
29372 + *ecc = tx4925_read_nfmc(&(tx4925_ndfmcptr->dtr));
29373 + tx4925ndfmc_disable_ecc();
29375 +void tx4925ndfmc_device_setup(void)
29378 + *(unsigned char *)0xbb005000 &= ~0x08;
29380 + /* reset NDFMC */
29381 + tx4925_ndfmcptr->rstr |= TX4925_NDFRSTR_RST;
29382 + while (tx4925_ndfmcptr->rstr & TX4925_NDFRSTR_RST);
29384 + /* setup BusSeparete, Hold Time, Strobe Pulse Width */
29385 + tx4925_ndfmcptr->mcr = TX4925_BSPRT ? TX4925_NDFMCR_BSPRT : 0;
29386 + tx4925_ndfmcptr->spr = TX4925_HOLD << 4 | TX4925_SPW;
29388 +static u_char tx4925ndfmc_nand_read_byte(struct mtd_info *mtd)
29390 + struct nand_chip *this = mtd->priv;
29391 + return tx4925_read_nfmc(this->IO_ADDR_R);
29394 +static void tx4925ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte)
29396 + struct nand_chip *this = mtd->priv;
29397 + tx4925_write_nfmc(byte, this->IO_ADDR_W);
29400 +static void tx4925ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
29403 + struct nand_chip *this = mtd->priv;
29405 + for (i=0; i<len; i++)
29406 + tx4925_write_nfmc(buf[i], this->IO_ADDR_W);
29409 +static void tx4925ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
29412 + struct nand_chip *this = mtd->priv;
29414 + for (i=0; i<len; i++)
29415 + buf[i] = tx4925_read_nfmc(this->IO_ADDR_R);
29418 +static int tx4925ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
29421 + struct nand_chip *this = mtd->priv;
29423 + for (i=0; i<len; i++)
29424 + if (buf[i] != tx4925_read_nfmc(this->IO_ADDR_R))
29431 + * Send command to NAND device
29433 +static void tx4925ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
29435 + register struct nand_chip *this = mtd->priv;
29437 + /* Begin command latch cycle */
29438 + this->hwcontrol(mtd, NAND_CTL_SETCLE);
29440 + * Write out the command to the device.
29442 + if (command == NAND_CMD_SEQIN) {
29445 + if (column >= mtd->oobblock) {
29447 + column -= mtd->oobblock;
29448 + readcmd = NAND_CMD_READOOB;
29449 + } else if (column < 256) {
29450 + /* First 256 bytes --> READ0 */
29451 + readcmd = NAND_CMD_READ0;
29454 + readcmd = NAND_CMD_READ1;
29456 + this->write_byte(mtd, readcmd);
29458 + this->write_byte(mtd, command);
29460 + /* Set ALE and clear CLE to start address cycle */
29461 + this->hwcontrol(mtd, NAND_CTL_CLRCLE);
29463 + if (column != -1 || page_addr != -1) {
29464 + this->hwcontrol(mtd, NAND_CTL_SETALE);
29466 + /* Serially input address */
29467 + if (column != -1)
29468 + this->write_byte(mtd, column);
29469 + if (page_addr != -1) {
29470 + this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
29471 + this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
29472 + /* One more address cycle for higher density devices */
29473 + if (mtd->size & 0x0c000000)
29474 + this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));
29476 + /* Latch in address */
29477 + this->hwcontrol(mtd, NAND_CTL_CLRALE);
29481 + * program and erase have their own busy handlers
29482 + * status and sequential in needs no delay
29484 + switch (command) {
29486 + case NAND_CMD_PAGEPROG:
29487 + /* Turn off WE */
29488 + this->hwcontrol (mtd, NAND_CTL_CLRWP);
29491 + case NAND_CMD_SEQIN:
29493 + this->hwcontrol (mtd, NAND_CTL_SETWP);
29496 + case NAND_CMD_ERASE1:
29497 + case NAND_CMD_ERASE2:
29498 + case NAND_CMD_STATUS:
29501 + case NAND_CMD_RESET:
29502 + if (this->dev_ready)
29504 + this->hwcontrol(mtd, NAND_CTL_SETCLE);
29505 + this->write_byte(mtd, NAND_CMD_STATUS);
29506 + this->hwcontrol(mtd, NAND_CTL_CLRCLE);
29507 + while ( !(this->read_byte(mtd) & 0x40));
29510 + /* This applies to read commands */
29513 + * If we don't have access to the busy pin, we apply the given
29516 + if (!this->dev_ready) {
29517 + udelay (this->chip_delay);
29522 + /* wait until command is processed */
29523 + while (!this->dev_ready(mtd));
29526 +#ifdef CONFIG_MTD_CMDLINE_PARTS
29527 +extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partitio
29528 +n **pparts, char *);
29532 + * Main initialization routine
29534 +extern int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
29535 +int __init tx4925ndfmc_init (void)
29537 + struct nand_chip *this;
29540 + /* Allocate memory for MTD device structure and private data */
29541 + tx4925ndfmc_mtd = (struct mtd_info *) kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
29543 + if (!tx4925ndfmc_mtd) {
29544 + printk ("Unable to allocate RBTX4925 NAND MTD device structure.\n");
29549 + tx4925ndfmc_device_setup();
29551 + /* io is indirect via a register so don't need to ioremap address */
29553 + /* Get pointer to private data */
29554 + this = (struct nand_chip *) (&tx4925ndfmc_mtd[1]);
29556 + /* Initialize structures */
29557 + memset((char *) tx4925ndfmc_mtd, 0, sizeof(struct mtd_info));
29558 + memset((char *) this, 0, sizeof(struct nand_chip));
29560 + /* Link the private data with the MTD structure */
29561 + tx4925ndfmc_mtd->priv = this;
29563 + /* Set address of NAND IO lines */
29564 + this->IO_ADDR_R = (void __iomem *)&(tx4925_ndfmcptr->dtr);
29565 + this->IO_ADDR_W = (void __iomem *)&(tx4925_ndfmcptr->dtr);
29566 + this->hwcontrol = tx4925ndfmc_hwcontrol;
29567 + this->enable_hwecc = tx4925ndfmc_enable_hwecc;
29568 + this->calculate_ecc = tx4925ndfmc_readecc;
29569 + this->correct_data = nand_correct_data;
29570 + this->eccmode = NAND_ECC_HW6_512;
29571 + this->dev_ready = tx4925ndfmc_device_ready;
29572 + /* 20 us command delay time */
29573 + this->chip_delay = 20;
29574 + this->read_byte = tx4925ndfmc_nand_read_byte;
29575 + this->write_byte = tx4925ndfmc_nand_write_byte;
29576 + this->cmdfunc = tx4925ndfmc_nand_command;
29577 + this->write_buf = tx4925ndfmc_nand_write_buf;
29578 + this->read_buf = tx4925ndfmc_nand_read_buf;
29579 + this->verify_buf = tx4925ndfmc_nand_verify_buf;
29581 + /* Scan to find existance of the device */
29582 + if (nand_scan (tx4925ndfmc_mtd, 1)) {
29587 + /* Register the partitions */
29588 +#ifdef CONFIG_MTD_CMDLINE_PARTS
29590 + int mtd_parts_nb = 0;
29591 + struct mtd_partition *mtd_parts = 0;
29592 + mtd_parts_nb = parse_cmdline_partitions(tx4925ndfmc_mtd, &mtd_parts, "tx4925ndfmc");
29593 + if (mtd_parts_nb > 0)
29594 + add_mtd_partitions(tx4925ndfmc_mtd, mtd_parts, mtd_parts_nb);
29596 + add_mtd_device(tx4925ndfmc_mtd);
29598 +#else /* ifdef CONFIG_MTD_CMDLINE_PARTS */
29599 + switch(tx4925ndfmc_mtd->size){
29600 + case 0x01000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info16k, NUM_PARTITIONS16K); break;
29601 + case 0x02000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info32k, NUM_PARTITIONS32K); break;
29602 + case 0x04000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info64k, NUM_PARTITIONS64K); break;
29603 + case 0x08000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info128k, NUM_PARTITIONS128K); break;
29605 + printk ("Unsupported SmartMedia device\n");
29610 +#endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */
29618 +module_init(tx4925ndfmc_init);
29621 + * Clean up routine
29624 +static void __exit tx4925ndfmc_cleanup (void)
29626 + /* Release resources, unregister device */
29627 + nand_release (tx4925ndfmc_mtd);
29629 + /* Free the MTD device structure */
29630 + kfree (tx4925ndfmc_mtd);
29632 +module_exit(tx4925ndfmc_cleanup);
29635 +MODULE_LICENSE("GPL");
29636 +MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
29637 +MODULE_DESCRIPTION("Glue layer for SmartMediaCard on Toshiba RBTX4925");
29638 Index: linux-2.6.5/drivers/mtd/nand/tx4938ndfmc.c
29639 ===================================================================
29640 --- linux-2.6.5.orig/drivers/mtd/nand/tx4938ndfmc.c 1969-12-31 19:00:00.000000000 -0500
29641 +++ linux-2.6.5/drivers/mtd/nand/tx4938ndfmc.c 2005-02-01 17:11:17.000000000 -0500
29644 + * drivers/mtd/nand/tx4938ndfmc.c
29647 + * This is a device driver for the NAND flash device connected to
29648 + * TX4938 internal NAND Memory Controller.
29649 + * TX4938 NDFMC is almost same as TX4925 NDFMC, but register size are 64 bit.
29651 + * Author: source@mvista.com
29653 + * Based on spia.c by Steven J. Hill
29655 + * $Id: tx4938ndfmc.c,v 1.3 2004/09/16 23:27:15 gleixner Exp $
29657 + * Copyright (C) 2000-2001 Toshiba Corporation
29659 + * 2003 (c) MontaVista Software, Inc. This file is licensed under the
29660 + * terms of the GNU General Public License version 2. This program is
29661 + * licensed "as is" without any warranty of any kind, whether express
29664 +#include <linux/config.h>
29665 +#include <linux/slab.h>
29666 +#include <linux/init.h>
29667 +#include <linux/module.h>
29668 +#include <linux/mtd/mtd.h>
29669 +#include <linux/mtd/nand.h>
29670 +#include <linux/mtd/nand_ecc.h>
29671 +#include <linux/mtd/partitions.h>
29672 +#include <asm/io.h>
29673 +#include <asm/bootinfo.h>
29674 +#include <linux/delay.h>
29675 +#include <asm/tx4938/rbtx4938.h>
29677 +extern struct nand_oobinfo jffs2_oobinfo;
29680 + * MTD structure for TX4938 NDFMC
29682 +static struct mtd_info *tx4938ndfmc_mtd;
29685 + * Define partitions for flash device
29687 +#define flush_wb() (void)tx4938_ndfmcptr->mcr;
29689 +#define NUM_PARTITIONS 3
29690 +#define NUMBER_OF_CIS_BLOCKS 24
29691 +#define SIZE_OF_BLOCK 0x00004000
29692 +#define NUMBER_OF_BLOCK_PER_ZONE 1024
29693 +#define SIZE_OF_ZONE (NUMBER_OF_BLOCK_PER_ZONE * SIZE_OF_BLOCK)
29694 +#ifndef CONFIG_MTD_CMDLINE_PARTS
29696 + * You can use the following sample of MTD partitions
29697 + * on the NAND Flash Memory 32MB or more.
29699 + * The following figure shows the image of the sample partition on
29700 + * the 32MB NAND Flash Memory.
29703 + * 0 +-----------------------------+ ------
29705 + * 24 +-----------------------------+ |
29706 + * | kernel image | | Zone 0
29708 + * +-----------------------------+ |
29709 + * 1023 | unused area | v
29710 + * +-----------------------------+ ------
29711 + * 1024 | JFFS2 | ^
29717 + * 2047 +-----------------------------+ ------
29720 +static struct mtd_partition partition_info[NUM_PARTITIONS] = {
29722 + .name = "RBTX4938 CIS Area",
29724 + .size = (NUMBER_OF_CIS_BLOCKS * SIZE_OF_BLOCK),
29725 + .mask_flags = MTD_WRITEABLE /* This partition is NOT writable */
29728 + .name = "RBTX4938 kernel image",
29729 + .offset = MTDPART_OFS_APPEND,
29730 + .size = 8 * 0x00100000, /* 8MB (Depends on size of kernel image) */
29731 + .mask_flags = MTD_WRITEABLE /* This partition is NOT writable */
29734 + .name = "Root FS (JFFS2)",
29735 + .offset = (0 + SIZE_OF_ZONE), /* start address of next zone */
29736 + .size = MTDPART_SIZ_FULL
29741 +static void tx4938ndfmc_hwcontrol(struct mtd_info *mtd, int cmd)
29744 + case NAND_CTL_SETCLE:
29745 + tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CLE;
29747 + case NAND_CTL_CLRCLE:
29748 + tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CLE;
29750 + case NAND_CTL_SETALE:
29751 + tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_ALE;
29753 + case NAND_CTL_CLRALE:
29754 + tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_ALE;
29756 + /* TX4938_NDFMCR_CE bit is 0:high 1:low */
29757 + case NAND_CTL_SETNCE:
29758 + tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CE;
29760 + case NAND_CTL_CLRNCE:
29761 + tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CE;
29763 + case NAND_CTL_SETWP:
29764 + tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_WE;
29766 + case NAND_CTL_CLRWP:
29767 + tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_WE;
29771 +static int tx4938ndfmc_dev_ready(struct mtd_info *mtd)
29774 + return !(tx4938_ndfmcptr->sr & TX4938_NDFSR_BUSY);
29776 +static void tx4938ndfmc_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
29778 + u32 mcr = tx4938_ndfmcptr->mcr;
29779 + mcr &= ~TX4938_NDFMCR_ECC_ALL;
29780 + tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF;
29781 + tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_READ;
29782 + ecc_code[1] = tx4938_ndfmcptr->dtr;
29783 + ecc_code[0] = tx4938_ndfmcptr->dtr;
29784 + ecc_code[2] = tx4938_ndfmcptr->dtr;
29785 + tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF;
29787 +static void tx4938ndfmc_enable_hwecc(struct mtd_info *mtd, int mode)
29789 + u32 mcr = tx4938_ndfmcptr->mcr;
29790 + mcr &= ~TX4938_NDFMCR_ECC_ALL;
29791 + tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_RESET;
29792 + tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF;
29793 + tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_ON;
29796 +static u_char tx4938ndfmc_nand_read_byte(struct mtd_info *mtd)
29798 + struct nand_chip *this = mtd->priv;
29799 + return tx4938_read_nfmc(this->IO_ADDR_R);
29802 +static void tx4938ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte)
29804 + struct nand_chip *this = mtd->priv;
29805 + tx4938_write_nfmc(byte, this->IO_ADDR_W);
29808 +static void tx4938ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
29811 + struct nand_chip *this = mtd->priv;
29813 + for (i=0; i<len; i++)
29814 + tx4938_write_nfmc(buf[i], this->IO_ADDR_W);
29817 +static void tx4938ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
29820 + struct nand_chip *this = mtd->priv;
29822 + for (i=0; i<len; i++)
29823 + buf[i] = tx4938_read_nfmc(this->IO_ADDR_R);
29826 +static int tx4938ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
29829 + struct nand_chip *this = mtd->priv;
29831 + for (i=0; i<len; i++)
29832 + if (buf[i] != tx4938_read_nfmc(this->IO_ADDR_R))
29839 + * Send command to NAND device
29841 +static void tx4938ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
29843 + register struct nand_chip *this = mtd->priv;
29845 + /* Begin command latch cycle */
29846 + this->hwcontrol(mtd, NAND_CTL_SETCLE);
29848 + * Write out the command to the device.
29850 + if (command == NAND_CMD_SEQIN) {
29853 + if (column >= mtd->oobblock) {
29855 + column -= mtd->oobblock;
29856 + readcmd = NAND_CMD_READOOB;
29857 + } else if (column < 256) {
29858 + /* First 256 bytes --> READ0 */
29859 + readcmd = NAND_CMD_READ0;
29862 + readcmd = NAND_CMD_READ1;
29864 + this->write_byte(mtd, readcmd);
29866 + this->write_byte(mtd, command);
29868 + /* Set ALE and clear CLE to start address cycle */
29869 + this->hwcontrol(mtd, NAND_CTL_CLRCLE);
29871 + if (column != -1 || page_addr != -1) {
29872 + this->hwcontrol(mtd, NAND_CTL_SETALE);
29874 + /* Serially input address */
29875 + if (column != -1)
29876 + this->write_byte(mtd, column);
29877 + if (page_addr != -1) {
29878 + this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
29879 + this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
29880 + /* One more address cycle for higher density devices */
29881 + if (mtd->size & 0x0c000000)
29882 + this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));
29884 + /* Latch in address */
29885 + this->hwcontrol(mtd, NAND_CTL_CLRALE);
29889 + * program and erase have their own busy handlers
29890 + * status and sequential in needs no delay
29892 + switch (command) {
29894 + case NAND_CMD_PAGEPROG:
29895 + /* Turn off WE */
29896 + this->hwcontrol (mtd, NAND_CTL_CLRWP);
29899 + case NAND_CMD_SEQIN:
29901 + this->hwcontrol (mtd, NAND_CTL_SETWP);
29904 + case NAND_CMD_ERASE1:
29905 + case NAND_CMD_ERASE2:
29906 + case NAND_CMD_STATUS:
29909 + case NAND_CMD_RESET:
29910 + if (this->dev_ready)
29912 + this->hwcontrol(mtd, NAND_CTL_SETCLE);
29913 + this->write_byte(mtd, NAND_CMD_STATUS);
29914 + this->hwcontrol(mtd, NAND_CTL_CLRCLE);
29915 + while ( !(this->read_byte(mtd) & 0x40));
29918 + /* This applies to read commands */
29921 + * If we don't have access to the busy pin, we apply the given
29924 + if (!this->dev_ready) {
29925 + udelay (this->chip_delay);
29930 + /* wait until command is processed */
29931 + while (!this->dev_ready(mtd));
29934 +#ifdef CONFIG_MTD_CMDLINE_PARTS
29935 +extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *);
29938 + * Main initialization routine
29940 +int __init tx4938ndfmc_init (void)
29942 + struct nand_chip *this;
29943 + int bsprt = 0, hold = 0xf, spw = 0xf;
29944 + int protected = 0;
29946 + if ((*rbtx4938_piosel_ptr & 0x0c) != 0x08) {
29947 + printk("TX4938 NDFMC: disabled by IOC PIOSEL\n");
29952 + spw = 9 - 1; /* 8 GBUSCLK = 80ns (@ GBUSCLK 100MHz) */
29954 + if ((tx4938_ccfgptr->pcfg &
29955 + (TX4938_PCFG_ATA_SEL|TX4938_PCFG_ISA_SEL|TX4938_PCFG_NDF_SEL))
29956 + != TX4938_PCFG_NDF_SEL) {
29957 + printk("TX4938 NDFMC: disabled by PCFG.\n");
29961 + /* reset NDFMC */
29962 + tx4938_ndfmcptr->rstr |= TX4938_NDFRSTR_RST;
29963 + while (tx4938_ndfmcptr->rstr & TX4938_NDFRSTR_RST)
29965 + /* setup BusSeparete, Hold Time, Strobe Pulse Width */
29966 + tx4938_ndfmcptr->mcr = bsprt ? TX4938_NDFMCR_BSPRT : 0;
29967 + tx4938_ndfmcptr->spr = hold << 4 | spw;
29969 + /* Allocate memory for MTD device structure and private data */
29970 + tx4938ndfmc_mtd = (struct mtd_info *) kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
29972 + if (!tx4938ndfmc_mtd) {
29973 + printk ("Unable to allocate TX4938 NDFMC MTD device structure.\n");
29977 + /* Get pointer to private data */
29978 + this = (struct nand_chip *) (&tx4938ndfmc_mtd[1]);
29980 + /* Initialize structures */
29981 + memset((char *) tx4938ndfmc_mtd, 0, sizeof(struct mtd_info));
29982 + memset((char *) this, 0, sizeof(struct nand_chip));
29984 + /* Link the private data with the MTD structure */
29985 + tx4938ndfmc_mtd->priv = this;
29987 + /* Set address of NAND IO lines */
29988 + this->IO_ADDR_R = (unsigned long)&tx4938_ndfmcptr->dtr;
29989 + this->IO_ADDR_W = (unsigned long)&tx4938_ndfmcptr->dtr;
29990 + this->hwcontrol = tx4938ndfmc_hwcontrol;
29991 + this->dev_ready = tx4938ndfmc_dev_ready;
29992 + this->calculate_ecc = tx4938ndfmc_calculate_ecc;
29993 + this->correct_data = nand_correct_data;
29994 + this->enable_hwecc = tx4938ndfmc_enable_hwecc;
29995 + this->eccmode = NAND_ECC_HW3_256;
29996 + this->chip_delay = 100;
29997 + this->read_byte = tx4938ndfmc_nand_read_byte;
29998 + this->write_byte = tx4938ndfmc_nand_write_byte;
29999 + this->cmdfunc = tx4938ndfmc_nand_command;
30000 + this->write_buf = tx4938ndfmc_nand_write_buf;
30001 + this->read_buf = tx4938ndfmc_nand_read_buf;
30002 + this->verify_buf = tx4938ndfmc_nand_verify_buf;
30004 + /* Scan to find existance of the device */
30005 + if (nand_scan (tx4938ndfmc_mtd, 1)) {
30006 + kfree (tx4938ndfmc_mtd);
30011 + printk(KERN_INFO "TX4938 NDFMC: write protected.\n");
30012 + tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE);
30015 +#ifdef CONFIG_MTD_CMDLINE_PARTS
30017 + int mtd_parts_nb = 0;
30018 + struct mtd_partition *mtd_parts = 0;
30019 + mtd_parts_nb = parse_cmdline_partitions(tx4938ndfmc_mtd, &mtd_parts, "tx4938ndfmc");
30020 + if (mtd_parts_nb > 0)
30021 + add_mtd_partitions(tx4938ndfmc_mtd, mtd_parts, mtd_parts_nb);
30023 + add_mtd_device(tx4938ndfmc_mtd);
30026 + add_mtd_partitions(tx4938ndfmc_mtd, partition_info, NUM_PARTITIONS );
30031 +module_init(tx4938ndfmc_init);
30034 + * Clean up routine
30036 +static void __exit tx4938ndfmc_cleanup (void)
30038 + /* Release resources, unregister device */
30039 + nand_release (tx4938ndfmc_mtd);
30041 + /* Free the MTD device structure */
30042 + kfree (tx4938ndfmc_mtd);
30044 +module_exit(tx4938ndfmc_cleanup);
30046 +MODULE_LICENSE("GPL");
30047 +MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
30048 +MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on TX4938 NDFMC");
30049 Index: linux-2.6.5/drivers/mtd/nftlcore.c
30050 ===================================================================
30051 --- linux-2.6.5.orig/drivers/mtd/nftlcore.c 2004-04-03 22:36:15.000000000 -0500
30052 +++ linux-2.6.5/drivers/mtd/nftlcore.c 2005-02-01 17:11:29.000000000 -0500
30054 /* Linux driver for NAND Flash Translation Layer */
30055 /* (c) 1999 Machine Vision Holdings, Inc. */
30056 /* Author: David Woodhouse <dwmw2@infradead.org> */
30057 -/* $Id: nftlcore.c,v 1.94 2003/06/23 12:00:08 dwmw2 Exp $ */
30058 +/* $Id: nftlcore.c,v 1.96 2004/06/28 13:52:55 dbrown Exp $ */
30061 The contents of this file are distributed under the GNU General
30063 struct NFTLrecord *nftl;
30064 unsigned long temp;
30066 - if (mtd->ecctype != MTD_ECC_RS_DiskOnChip)
30067 + if (mtd->type != MTD_NANDFLASH)
30069 + /* OK, this is moderately ugly. But probably safe. Alternatives? */
30070 + if (memcmp(mtd->name, "DiskOnChip", 10))
30073 + if (!mtd->block_isbad) {
30075 +"NFTL no longer supports the old DiskOnChip drivers loaded via docprobe.\n"
30076 +"Please use the new diskonchip driver under the NAND subsystem.\n");
30080 DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name);
30082 nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
30084 nftl->mbd.devnum = -1;
30085 nftl->mbd.blksize = 512;
30087 + memcpy(&nftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
30088 + nftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
30090 if (NFTL_mount(nftl) < 0) {
30091 printk(KERN_WARNING "NFTL: could not mount device\n");
30092 @@ -350,17 +362,19 @@
30093 if (BlockMap[block] == BLOCK_NIL)
30096 - ret = MTD_READECC(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
30097 - 512, &retlen, movebuf, (char *)&oob, NAND_ECC_DISKONCHIP);
30098 + ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
30099 + 512, &retlen, movebuf);
30101 - ret = MTD_READECC(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block])
30102 + ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block])
30103 + (block * 512), 512, &retlen,
30104 - movebuf, (char *)&oob, NAND_ECC_DISKONCHIP);
30107 printk("Error went away on retry.\n");
30109 + memset(&oob, 0xff, sizeof(struct nftl_oob));
30110 + oob.b.Status = oob.b.Status1 = SECTOR_USED;
30111 MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512),
30112 - 512, &retlen, movebuf, (char *)&oob, NAND_ECC_DISKONCHIP);
30113 + 512, &retlen, movebuf, (char *)&oob, &nftl->oobinfo);
30116 /* add the header so that it is now a valid chain */
30117 @@ -390,7 +404,6 @@
30119 if (NFTL_formatblock(nftl, thisEUN) < 0) {
30120 /* could not erase : mark block as reserved
30121 - * FixMe: Update Bad Unit Table on disk
30123 nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED;
30125 @@ -617,7 +630,7 @@
30127 unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
30130 + struct nftl_oob oob;
30132 writeEUN = NFTL_findwriteunit(nftl, block);
30134 @@ -628,9 +641,11 @@
30138 + memset(&oob, 0xff, sizeof(struct nftl_oob));
30139 + oob.b.Status = oob.b.Status1 = SECTOR_USED;
30140 MTD_WRITEECC(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
30141 - 512, &retlen, (char *)buffer, (char *)eccbuf, NAND_ECC_DISKONCHIP);
30142 - /* no need to write SECTOR_USED flags since they are written in mtd_writeecc */
30143 + 512, &retlen, (char *)buffer, (char *)&oob, &nftl->oobinfo);
30144 + /* need to write SECTOR_USED flags since they are not written in mtd_writeecc */
30148 @@ -692,8 +707,7 @@
30150 loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
30152 - u_char eccbuf[6];
30153 - if (MTD_READECC(nftl->mbd.mtd, ptr, 512, &retlen, buffer, eccbuf, NAND_ECC_DISKONCHIP))
30154 + if (MTD_READ(nftl->mbd.mtd, ptr, 512, &retlen, buffer))
30158 @@ -735,7 +749,7 @@
30160 int __init init_nftl(void)
30162 - printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.94 $, nftlmount.c %s\n", nftlmountrev);
30163 + printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.96 $, nftlmount.c %s\n", nftlmountrev);
30165 return register_mtd_blktrans(&nftl_tr);
30167 Index: linux-2.6.5/drivers/mtd/nftlmount.c
30168 ===================================================================
30169 --- linux-2.6.5.orig/drivers/mtd/nftlmount.c 2004-04-03 22:37:36.000000000 -0500
30170 +++ linux-2.6.5/drivers/mtd/nftlmount.c 2005-02-01 17:11:29.000000000 -0500
30172 * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
30173 * Copyright (C) 2000 Netgem S.A.
30175 - * $Id: nftlmount.c,v 1.34 2003/05/21 10:54:10 dwmw2 Exp $
30176 + * $Id: nftlmount.c,v 1.37 2004/09/16 23:32:37 gleixner Exp $
30178 * This program is free software; you can redistribute it and/or modify
30179 * it under the terms of the GNU General Public License as published by
30182 #define SECTORSIZE 512
30184 -char nftlmountrev[]="$Revision: 1.34 $";
30185 +char nftlmountrev[]="$Revision: 1.37 $";
30187 /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
30188 * various device information of the NFTL partition and Bad Unit Table. Update
30190 static int find_boot_record(struct NFTLrecord *nftl)
30192 struct nftl_uci1 h1;
30193 - struct nftl_oob oob;
30194 unsigned int block, boot_record_count = 0;
30196 u8 buf[SECTORSIZE];
30199 /* Assume logical EraseSize == physical erasesize for starting the scan.
30200 We'll sort it out later if we find a MediaHeader which says otherwise */
30201 + /* Actually, we won't. The new DiskOnChip driver has already scanned
30202 + the MediaHeader and adjusted the virtual erasesize it presents in
30203 + the mtd device accordingly. We could even get rid of
30204 + nftl->EraseSize if there were any point in doing so. */
30205 nftl->EraseSize = nftl->mbd.mtd->erasesize;
30206 nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
30210 /* Check for ANAND header first. Then can whinge if it's found but later
30212 - if ((ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf))) {
30213 + ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf);
30214 + /* We ignore ret in case the ECC of the MediaHeader is invalid
30215 + (which is apparently acceptable) */
30216 + if (retlen != SECTORSIZE) {
30217 static int warncount = 5;
30220 @@ -104,7 +110,7 @@
30222 /* Finally reread to check ECC */
30223 if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE,
30224 - &retlen, buf, (char *)&oob, NAND_ECC_DISKONCHIP) < 0)) {
30225 + &retlen, buf, (char *)&oob, NULL) < 0)) {
30226 printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n",
30227 block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
30229 @@ -149,6 +155,10 @@
30230 memcpy(mh, buf, sizeof(struct NFTLMediaHeader));
30232 /* Do some sanity checks on it */
30234 +The new DiskOnChip driver scans the MediaHeader itself, and presents a virtual
30235 +erasesize based on UnitSizeFactor. So the erasesize we read from the mtd
30236 +device is already correct.
30237 if (mh->UnitSizeFactor == 0) {
30238 printk(KERN_NOTICE "NFTL: UnitSizeFactor 0x00 detected. This violates the spec but we think we know what it means...\n");
30239 } else if (mh->UnitSizeFactor < 0xfc) {
30240 @@ -161,6 +171,7 @@
30241 nftl->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor);
30242 nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
30245 nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
30246 if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {
30247 printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");
30248 @@ -213,11 +224,13 @@
30250 /* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */
30251 for (i = 0; i < nftl->nb_blocks; i++) {
30253 +The new DiskOnChip driver already scanned the bad block table. Just query it.
30254 if ((i & (SECTORSIZE - 1)) == 0) {
30255 /* read one sector for every SECTORSIZE of blocks */
30256 if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize +
30257 i + SECTORSIZE, SECTORSIZE, &retlen, buf,
30258 - (char *)&oob, NAND_ECC_DISKONCHIP)) < 0) {
30259 + (char *)&oob, NULL)) < 0) {
30260 printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n",
30262 kfree(nftl->ReplUnitTable);
30263 @@ -228,6 +241,9 @@
30264 /* mark the Bad Erase Unit as RESERVED in ReplUnitTable */
30265 if (buf[i & (SECTORSIZE - 1)] != 0xff)
30266 nftl->ReplUnitTable[i] = BLOCK_RESERVED;
30268 + if (nftl->mbd.mtd->block_isbad(nftl->mbd.mtd, i * nftl->EraseSize))
30269 + nftl->ReplUnitTable[i] = BLOCK_RESERVED;
30272 nftl->MediaUnit = block;
30273 @@ -253,21 +269,16 @@
30277 - u8 buf[SECTORSIZE];
30278 + u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
30280 for (i = 0; i < len; i += SECTORSIZE) {
30281 - /* we want to read the sector without ECC check here since a free
30282 - sector does not have ECC syndrome on it yet */
30283 - if (MTD_READ(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf) < 0)
30284 + if (MTD_READECC(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &nftl->oobinfo) < 0)
30286 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
30290 - if (MTD_READOOB(nftl->mbd.mtd, address, nftl->mbd.mtd->oobsize,
30291 - &retlen, buf) < 0)
30293 - if (memcmpb(buf, 0xff, nftl->mbd.mtd->oobsize) != 0)
30294 + if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0)
30297 address += SECTORSIZE;
30298 @@ -282,7 +293,6 @@
30299 * Return: 0 when succeed, -1 on error.
30301 * ToDo: 1. Is it neceressary to check_free_sector after erasing ??
30302 - * 2. UnitSizeFactor != 0xFF
30304 int NFTL_formatblock(struct NFTLrecord *nftl, int block)
30306 @@ -312,11 +322,10 @@
30307 MTD_ERASE(nftl->mbd.mtd, instr);
30309 if (instr->state == MTD_ERASE_FAILED) {
30310 - /* could not format, FixMe: We should update the BadUnitTable
30311 - both in memory and on disk */
30312 printk("Error while formatting block %d\n", block);
30318 /* increase and write Wear-Leveling info */
30319 nb_erases = le32_to_cpu(uci.WearInfo);
30321 @@ -329,14 +338,18 @@
30322 * FixMe: is this check really necessary ? since we have check the
30323 * return code after the erase operation. */
30324 if (check_free_sectors(nftl, instr->addr, nftl->EraseSize, 1) != 0)
30328 uci.WearInfo = le32_to_cpu(nb_erases);
30329 if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
30330 &retlen, (char *)&uci) < 0)
30336 + /* could not format, update the bad block table (caller is responsible
30337 + for setting the ReplUnitTable to BLOCK_RESERVED on failure) */
30338 + nftl->mbd.mtd->block_markbad(nftl->mbd.mtd, instr->addr);
30342 /* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct.
30343 @@ -441,8 +454,7 @@
30345 printk("Formatting block %d\n", block);
30346 if (NFTL_formatblock(nftl, block) < 0) {
30347 - /* cannot format !!!! Mark it as Bad Unit,
30348 - FixMe: update the BadUnitTable on disk */
30349 + /* cannot format !!!! Mark it as Bad Unit */
30350 nftl->ReplUnitTable[block] = BLOCK_RESERVED;
30352 nftl->ReplUnitTable[block] = BLOCK_FREE;
30353 Index: linux-2.6.5/drivers/mtd/redboot.c
30354 ===================================================================
30355 --- linux-2.6.5.orig/drivers/mtd/redboot.c 2004-04-03 22:37:23.000000000 -0500
30356 +++ linux-2.6.5/drivers/mtd/redboot.c 2005-02-01 17:11:17.000000000 -0500
30359 - * $Id: redboot.c,v 1.11 2003/05/21 10:39:26 dwmw2 Exp $
30360 + * $Id: redboot.c,v 1.15 2004/08/10 07:55:16 dwmw2 Exp $
30362 * Parse RedBoot-style Flash Image System (FIS) tables and
30363 * produce a Linux partition array to match.
30365 #include <linux/kernel.h>
30366 #include <linux/slab.h>
30367 #include <linux/init.h>
30368 +#include <linux/vmalloc.h>
30370 #include <linux/mtd/mtd.h>
30371 #include <linux/mtd/partitions.h>
30372 @@ -48,21 +49,24 @@
30377 +#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
30378 static char nullstring[] = "unallocated";
30381 - buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
30382 + buf = vmalloc(master->erasesize);
30387 /* Read the start of the last erase block */
30388 ret = master->read(master, master->size - master->erasesize,
30389 - PAGE_SIZE, &retlen, (void *)buf);
30390 + master->erasesize, &retlen, (void *)buf);
30395 - if (retlen != PAGE_SIZE) {
30396 + if (retlen != master->erasesize) {
30404 - for (i = 0; i < PAGE_SIZE / sizeof(struct fis_image_desc); i++) {
30405 + for (i = 0; i < master->erasesize / sizeof(struct fis_image_desc); i++) {
30406 struct fis_list *new_fl, **prev;
30408 if (buf[i].name[0] == 0xff)
30409 @@ -112,48 +116,69 @@
30413 - if (fl->img->flash_base)
30414 +#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
30415 + if (fl->img->flash_base) {
30417 + nulllen = sizeof(nullstring);
30420 for (tmp_fl = fl; tmp_fl->next; tmp_fl = tmp_fl->next) {
30421 - if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize < tmp_fl->next->img->flash_base)
30422 + if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize <= tmp_fl->next->img->flash_base) {
30424 + nulllen = sizeof(nullstring);
30427 - parts = kmalloc(sizeof(*parts)*nrparts + sizeof(nullstring) + namelen, GFP_KERNEL);
30429 + parts = kmalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
30436 - memset(parts, 0, sizeof(*parts)*nrparts + namelen);
30437 + memset(parts, 0, sizeof(*parts)*nrparts + nulllen + namelen);
30439 - /* FIXME: Include nullname only if it's used */
30440 nullname = (char *)&parts[nrparts];
30441 - sprintf(nullname, nullstring);
30442 - names = nullname + sizeof(nullstring);
30443 +#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
30444 + if (nulllen > 0) {
30445 + strcpy(nullname, nullstring);
30448 + names = nullname + nulllen;
30452 +#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
30453 if (fl->img->flash_base) {
30454 parts[0].name = nullname;
30455 parts[0].size = fl->img->flash_base;
30456 parts[0].offset = 0;
30460 for ( ; i<nrparts; i++) {
30461 parts[i].size = fl->img->size;
30462 parts[i].offset = fl->img->flash_base;
30463 parts[i].name = names;
30465 strcpy(names, fl->img->name);
30466 +#ifdef CONFIG_MTD_REDBOOT_PARTS_READONLY
30467 + if (!memcmp(names, "RedBoot", 8) ||
30468 + !memcmp(names, "RedBoot config", 15) ||
30469 + !memcmp(names, "FIS directory", 14)) {
30470 + parts[i].mask_flags = MTD_WRITEABLE;
30473 names += strlen(names)+1;
30475 - if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize < fl->next->img->flash_base) {
30476 +#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
30477 + if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
30479 parts[i].offset = parts[i-1].size + parts[i-1].offset;
30480 parts[i].size = fl->next->img->flash_base - parts[i].offset;
30481 parts[i].name = nullname;
30487 @@ -166,7 +191,7 @@
30496 Index: linux-2.6.5/drivers/mtd/ssfdc.c
30497 ===================================================================
30498 --- linux-2.6.5.orig/drivers/mtd/ssfdc.c 1969-12-31 19:00:00.000000000 -0500
30499 +++ linux-2.6.5/drivers/mtd/ssfdc.c 2005-02-01 17:11:17.000000000 -0500
30502 + * drivers/mtd/ssfdc.c
30504 + * Copyright (C) 2003 Simon Haynes (simon@baydel.con)
30507 + * This program is free software; you can redistribute it and/or
30508 + * modify it under the terms of the GNU Lesser General Public License
30509 + * version 2.1 as published by the Free Software Foundation.
30511 + * This module provides a translation layer, via mtd, for smart
30512 + * media card access. It essentially enables the possibility
30513 + * of using cards on a hardware which does not have a hardware translation
30514 + * layer and interchanging them with hardware that does ie: PC card readers
30516 + * I had to write this module for a specific task and in a short timeframe
30517 + * for this reason I have imposed some restricions to make the job easier.
30519 + * To build an compile the driver I added the following lines
30520 + * to mtd/Config.in
30522 + * dep_tristate ' SSFDC support' CONFIG_SSFDC $CONFIG_MTD
30524 + * to /mtd/Makefile
30526 + * obj-$(CONFIG_SSFDC) += ssfdc.o
30528 + * and compiled the kernel via the usual methods.
30530 + * I am sure that there are many problems I don't know about but here are
30531 + * some that I know of
30533 + * Currently the driver uses MAJOR number 44 which I think is FTL or NFTL
30534 + * I did this because I wanted a static number and I didn't know
30535 + * how to go about getting a new one. This needs addressing
30536 + * The dev nodes required are like standard. I only use minor 0
30537 + * (/dev/ssfdca), and minor 1 (/dev/ssfdca1).
30538 + * You should be able to run fdisk on /dev/ssfdca and the first partition
30539 + * is /dev/ssfdca1. There is no working code in the module for changing the
30540 + * SMC and rebuilding the maps so the card should not be changed once the
30541 + * module is loaded. At present I only look for 1 partition. But this is a
30542 + * small commented hack.
30544 + * There is no support cards which do not have a 512 byte page size with 16
30545 + * bytes of oob and an erase size of 16K.
30546 + * There are no checks for this at present. In addition the MTD reported size
30547 + * must be 16M or a multiple.
30549 + * Code to handle multiple partitions or multiple cards is incomplete
30550 + * Need to allocate data buffer and oob buffer on a per partition basis.
30551 + * As I am only concerned with one partition I will do this if I ever need to.
30552 + * The cached physical address variable also needs this attention.
30554 + * Recently I have started to work on media changes. Some of this is specific
30555 + * to my hardware and you will see references to pt_ssfdc_smc and smc_status.
30556 + * This code is incomplete and does not work. I have commented it for the moment
30557 + * but it should give an indication of what I think is required. Maybe there is
30558 + * something it mtd that can help
30560 + * 17th August 2004 MHB
30562 + * Following updating CVS I noticed some single bit data corruption. I believe
30563 + * that this was down to the fact that I was using mtd->read instead of mtd->read_ecc
30564 + * and that mtd->read was applying it's own error corretion from the wrong ecc bytes
30565 + * I have now corrected this.
30567 + * During this time I noticed that while in allocate new I only seem to look for blocks
30568 + * in 1 zone. So this limits the partition size to 16MB with all the other SMC size
30574 +#include <linux/config.h>
30575 +#include <linux/types.h>
30576 +#include <linux/module.h>
30577 +#include <linux/kernel.h>
30578 +#include <linux/fs.h>
30579 +#include <linux/init.h>
30580 +#include <linux/slab.h>
30581 +#include <linux/vmalloc.h>
30582 +#include <linux/mtd/mtd.h>
30583 +#include <linux/mtd/blktrans.h>
30584 +#include <linux/mtd/nand_ecc.h>
30585 +#include <linux/sched.h>
30586 +#include <linux/ptrace.h>
30587 +#include <linux/string.h>
30588 +#include <linux/timer.h>
30589 +#include <linux/major.h>
30590 +#include <linux/ioctl.h>
30591 +#include <linux/hdreg.h>
30592 +#include <linux/list.h>
30593 +#include <asm/semaphore.h>
30594 +#include <asm/uaccess.h>
30597 +#if (LINUX_VERSION_CODE >= 0x20100)
30598 +#include <linux/vmalloc.h>
30600 +#if (LINUX_VERSION_CODE >= 0x20303)
30601 +#include <linux/blkpg.h>
30604 +#include <asm/semaphore.h>
30606 +#define SSFDC_FORMAT 1
30608 +#define PDEBUG(fmt, args...)
30610 +#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT
30611 +#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT
30613 +#if (LINUX_VERSION_CODE < 0x20320)
30614 +#define BLK_DEFAULT_QUEUE(n) blk_dev[n].request_fn
30615 +#define blk_init_queue(q, req) q = (req)
30616 +#define blk_cleanup_queue(q) q = NULL
30617 +#define request_arg_t void
30619 +#define request_arg_t request_queue_t *q
30625 +#define SSFDC_MAJOR 44
30627 +#define MAJOR_NR SSFDC_MAJOR
30628 +#define DEVICE_NAME "ssfdc"
30629 +#define DEVICE_REQUEST do_ssfdc_request
30630 +#define DEVICE_ON(device)
30631 +#define DEVICE_OFF(device)
30633 +#include <linux/blk.h>
30635 +#include "/home/simon/ebony/dbwhatu/dbwhatu/smccontrol.h"
30639 +#define ZONE_SIZE (16 * 1024 * 1024)
30640 +#define SMC_BLOCK_SIZE (16 * 1024)
30641 +#define SECTOR_SIZE 512
30642 +#define SECTORS_PER_ZONE (ZONE_SIZE / SECTOR_SIZE)
30643 +#define BLOCKS_PER_ZONE (ZONE_SIZE / SMC_BLOCK_SIZE)
30644 +#define SECTORS_PER_BLOCK (SMC_BLOCK_SIZE / SECTOR_SIZE)
30645 +#define OOB_SIZE 16
30648 +#define MAX_DEVICES 4
30649 +#define MAX_PARTITIONS 8
30650 +#define PARTITION_BITS 3
30651 +#define MAX_ZONES 8
30654 +int ssfdc_major = SSFDC_MAJOR;
30655 +unsigned int ssfdc_cached = 0xFFFFFFFF;
30656 +static unsigned char ssfdc_scratch[16384];
30657 +static unsigned char ssfdc_buffer[16];
30658 +static unsigned char ssfdc_ffoob_buf[OOB_SIZE * SECTORS_PER_BLOCK];
30659 +static unsigned char ssfdc_oob_buf[OOB_SIZE * SECTORS_PER_BLOCK];
30662 +static struct nand_oobinfo ssfdc_ffoob_info = {
30667 +typedef struct minor_t {
30670 + unsigned char * pt_data;
30671 + unsigned char * pt_oob;
30676 +typedef struct partition_t {
30678 + struct mtd_info *mtd;
30680 + unsigned int *zone;
30681 + unsigned int zoneCount;
30682 + minor_t minor[MAX_PARTITIONS];
30683 + unsigned int last_written[MAX_ZONES];
30686 +partition_t SMCParts[MAX_DEVICES];
30689 +static unsigned char ssfdc_ecc[] = {14, 13, 15, 9, 8, 10};
30691 +static struct hd_struct ssfdc_hd[MAX_DEVICES * MAX_PARTITIONS];
30692 +static int ssfdc_sizes[MAX_DEVICES * MAX_PARTITIONS];
30693 +static int ssfdc_blocksizes[MAX_DEVICES * MAX_PARTITIONS];
30694 +smc_control * pt_ssfdc_smc;
30697 +static struct gendisk ssfdc_gendisk = {
30698 + major: SSFDC_MAJOR,
30699 + major_name: "ssfdc",
30700 + minor_shift: PARTITION_BITS,
30701 + max_p: MAX_PARTITIONS,
30703 + sizes: ssfdc_sizes,
30707 +static int ssfdc_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg);
30708 +static int ssfdc_open(struct inode *inode, struct file *file);
30709 +static int ssfdc_close(struct inode *inode, struct file *file);
30710 +static int ssfdc_write(partition_t *part, caddr_t buffer, u_long sector, u_long nblocks);
30711 +static int ssfdc_read(partition_t *part, caddr_t buffer, u_long sector, u_long nblocks);
30712 +static int ssfdc_physical(partition_t * pt_smcpart, int zone, int block);
30713 +static int ssfdc_erase(partition_t *pt_smcpart, unsigned int offset);
30714 +static int ssfdc_read_partitions(partition_t * pt_smcpart);
30715 +static void ssfdc_notify_add(struct mtd_info *mtd);
30716 +static void ssfdc_notify_remove(struct mtd_info *mtd);
30717 +static void ssfdc_tables(partition_t * pt_smcpart);
30718 +static int ssfdc_sector_blank(partition_t * pt_smcpart, int sc);
30719 +static int ssfdc_allocate_new(partition_t * pt_smcpart, int zone);
30720 +int ssfdc_parity(int number);
30721 +static void ssfdc_erase_callback(struct erase_info *erase);
30725 +static DECLARE_WAIT_QUEUE_HEAD(ssfdc_wq);
30728 +static struct mtd_notifier ssfdc_notifier = {
30729 + add: ssfdc_notify_add,
30730 + remove: ssfdc_notify_remove,
30735 +static struct block_device_operations ssfdc_fops = {
30736 + open: ssfdc_open,
30737 + release: ssfdc_close,
30738 + ioctl: ssfdc_ioctl,
30741 +static struct semaphore ssfdc_semaphore;
30743 +static void ssfdc_notify_add(struct mtd_info *mtd) {
30748 + if(mtd->index >= 1) return; // Hack to limit SSFDC to 1 partition
30750 + if( ((mtd->size % ZONE_SIZE) != 0) && (mtd->size < (ZONE_SIZE * MAX_ZONES)) ){
30751 + PDEBUG("ssfdc_notify_add : mtd partition %d is not modulus 16M, not SSFDC\n", mtd->index);
30754 + memset((void *)&SMCParts[mtd->index].type, 0, sizeof(partition_t));
30755 + SMCParts[mtd->index].mtd = mtd;
30756 + SMCParts[mtd->index].count = mtd->index;
30757 + SMCParts[mtd->index].type = 1;
30758 + SMCParts[mtd->index].zoneCount = mtd->size / ZONE_SIZE;
30759 + SMCParts[mtd->index].zone = kmalloc(SMCParts[mtd->index].zoneCount * 8192, GFP_KERNEL);
30762 + if(!SMCParts[mtd->index].zone) {
30763 + printk(KERN_NOTICE "ssfdc_notify_add : mtd partition %d, failed to allocate mapping table\n", mtd->index);
30764 + SMCParts[mtd->index].type = 0;
30767 + memset((void *)SMCParts[mtd->index].zone, 0xFF, SMCParts[mtd->index].zoneCount * 8192);
30770 + ssfdc_read_partitions((partition_t *)&SMCParts[mtd->index].type);
30775 +static int ssfdc_read_partitions(partition_t * pt_smcpart) {
30777 + int whole, i, j, size;
30779 +//=printk("ssfdc_read_partitions : start\n");
30781 + for(i=0; i<MAX_PARTITIONS; i++)
30782 + if ((atomic_read(&pt_smcpart->minor[i].open) > 1)) {
30783 +//=printk("ssfdc_read_partitions : part %d busy\n", i);
30789 +//=printk("ssfdc_read_partitions : tables start\n");
30790 + ssfdc_tables(pt_smcpart);
30791 +//=printk("ssfdc_read_partitions : tables end\n");
30793 + whole = pt_smcpart->count << PARTITION_BITS;
30796 + j = MAX_PARTITIONS - 1;
30797 + while (j-- > 0) {
30798 + if (ssfdc_hd[whole+j].nr_sects > 0) {
30799 + kdev_t rdev = MKDEV(SSFDC_MAJOR, whole+j);
30800 + invalidate_device(rdev, 1);
30802 + ssfdc_hd[whole+j].start_sect = 0;
30803 + ssfdc_hd[whole+j].nr_sects = 0;
30807 + size = (((pt_smcpart->mtd->size / 16384) * 1000) / 1024) * 32;
30808 + size /= (0x8 * 0x20);
30809 + size = size * (0x8 * 0x20);
30811 +//=printk("ssfdc_read_partitions : register start\n");
30813 + register_disk(&ssfdc_gendisk, whole >> PARTITION_BITS, MAX_PARTITIONS,
30814 + &ssfdc_fops, size);
30816 +//=printk("ssfdc_read_partitions : register end\n");
30823 +static void ssfdc_notify_remove(struct mtd_info *mtd) {
30827 + whole = i << PARTITION_BITS;
30828 + if(SMCParts[i].mtd == mtd) {
30829 + if(SMCParts[i].zone)kfree(SMCParts[i].zone);
30830 + memset((void *)&SMCParts[i].type, 0, sizeof(partition_t));
30831 + for (j = 0; j < MAX_PARTITIONS; j++) {
30832 + if (ssfdc_hd[whole+j].nr_sects > 0) {
30833 + ssfdc_hd[whole+j].start_sect = 0;
30834 + ssfdc_hd[whole+j].nr_sects=0;
30844 +static int ssfdc_ioctl(struct inode *inode, struct file *file,
30845 + u_int cmd, u_long arg) {
30847 + int minor = MINOR(inode->i_rdev);
30848 + int ret = -EINVAL;
30849 + partition_t * pt_smcpart = (partition_t *)&SMCParts[(minor & ~(MAX_PARTITIONS -1)) >> PARTITION_BITS].type;
30850 + struct hd_geometry geo;
30853 + unsigned char smc_status;
30855 + smc_status = in_8((void *)&pt_ssfdc_smc->smc_status);
30856 + if(!(smc_status & SMC_PRESENT)) {
30857 + printk("ssfdc : media not present\n");
30859 + goto ssfdc_ioctl_error;
30862 + if(smc_status & SMC_CHANGED) {
30863 + out_8((void *)&pt_ssfdc_smc->smc_status, smc_status);
30864 + if(minor & ((1<< PARTITION_BITS) - 1)) return -ENOTTY;
30865 + ssfdc_read_partitions(pt_smcpart);
30866 + printk("ssfdc : media change\n");
30871 + case HDIO_GETGEO:
30872 + memset(&geo, 0, sizeof(geo));
30873 + size = (((pt_smcpart->mtd->size / 16384) * 1000) / 1024) * 32;
30874 + size /= (0x8 * 0x20);
30876 + geo.sectors = 0x20;
30877 + geo.cylinders = size;
30878 + geo.start = ssfdc_hd[minor].start_sect;
30879 +// printk(KERN_WARNING "ssfdc : HDIO_GETGEO heads %d, sectors %d, cylinders %d, start %lu\n",
30880 +// geo.heads, geo.sectors, geo.cylinders, geo.start);
30881 + copy_to_user((void *)arg, &geo, sizeof(geo));
30885 + case BLKGETSIZE64:
30887 + size = (((pt_smcpart->mtd->size / 16384) * 1000) / 1024) * 32;
30888 + //=printk(KERN_WARNING "ssfdc : BLKGETSIZE %d, minor %d\n", size, minor);
30889 + ret = copy_to_user((unsigned long *)arg, &size, sizeof(size));
30893 + ret = copy_to_user((unsigned long *)arg, &size, sizeof(size));
30898 + if(minor & ((1<< PARTITION_BITS) - 1)) return -ENOTTY;
30899 + ssfdc_read_partitions(pt_smcpart);
30903 + printk(KERN_WARNING "ssfdc : block ioctl 0x%x\n", cmd);
30907 + printk(KERN_WARNING "ssfdc: unknown ioctl 0x%x\n", cmd);
30910 +//ssfdc_ioctl_error:
30914 +static int ssfdc_open(struct inode *inode, struct file *file)
30916 + int minor = MINOR(inode->i_rdev);
30917 + partition_t *pt_smcpart;
30920 + if (minor >= MAX_MTD_DEVICES)
30923 + index = (minor & ~(MAX_PARTITIONS -1)) >> PARTITION_BITS;
30926 + if(SMCParts[index].type != SSFDC_FORMAT)
30929 + pt_smcpart = &SMCParts[index];
30932 + if(!pt_smcpart->zone)
30936 + BLK_INC_USE_COUNT;
30938 + if (!get_mtd_device(pt_smcpart->mtd, -1)) {
30939 + BLK_DEC_USE_COUNT;
30943 + if ((file->f_mode & 2) && !(pt_smcpart->mtd->flags & MTD_CLEAR_BITS) ) {
30944 + put_mtd_device(pt_smcpart->mtd);
30945 + BLK_DEC_USE_COUNT;
30950 + atomic_inc(&pt_smcpart->minor[minor & ~(MAX_PARTITIONS -1)].open);
30952 + PDEBUG("ssfdc_open : device %d\n", minor);
30957 +static void ssfdc_tables(partition_t * pt_smcpart) {
30959 + int * logical, * physical;
30963 + int block_address, parity;
30966 + for(zone=0; zone<pt_smcpart->zoneCount; zone++) {
30967 + logical = pt_smcpart->zone + (2048 * zone);
30968 + memset((void *)logical, 0xFF, 1024 * sizeof(int));
30969 + physical = pt_smcpart->zone + (2048 * zone) + 1024;
30970 + memset((void *)physical, 0xFF, 1024 * sizeof(int));
30972 + for(block=0; block < 1024; block++) {
30973 + offset = (zone * ZONE_SIZE) + (block * SMC_BLOCK_SIZE);
30974 + pt_smcpart->mtd->read_oob(pt_smcpart->mtd, offset, sizeof(ssfdc_buffer), &retlen, ssfdc_buffer);
30975 + if(retlen != sizeof(ssfdc_buffer)) {
30976 + printk(KERN_WARNING "ssfdc_tables : failed to read OOB\n");
30977 + pt_smcpart->type = 0;
30981 + l = (ssfdc_buffer[7] & 0xFF);
30982 + h = (ssfdc_buffer[6] & 0xFF);
30983 + block_address = l + (h << 8L);
30985 + if((block_address & ~0x7FF) != 0x1000) {
30989 + parity = block_address & 0x01;
30991 + block_address &= 0x7FF;
30992 + block_address >>= 1;
30995 + if(ssfdc_parity(block_address) != parity) {
30996 + printk(KERN_WARNING "ssfdc_tables : parity error offset 0x%x, block 0x%x, parity 0x%x\nOOB : "
30997 + , offset, block_address, parity);
30998 + for(i=0; i<16; i++) {
30999 + printk("0x%02x ", (unsigned char)ssfdc_buffer[i]);
31002 + pt_smcpart->type = 0;
31007 + /* Ok we have a valid block number so insert it */
31008 + *(logical + block_address) = (offset/SMC_BLOCK_SIZE);
31009 + PDEBUG("ssfdc_tables : logical 0x%x + 0x%x = 0x%x\n",
31010 + (unsigned int)logical, block_address, (offset/SMC_BLOCK_SIZE));
31011 + *(physical + block) = block_address;
31012 + PDEBUG("ssfdc_tables : physical 0x%x + 0x%x = 0x%x\n", (unsigned int)physical, block, block_address);
31019 +int ssfdc_parity(int number) {
31021 + int parity = 1; // the 0x1000 bit
31023 + for(i=0; i<10; i++) {
31024 + parity += ((number >> i) & 1);
31026 + PDEBUG("ssfdc_parity : number 0x%x, parity 0x%x\n", number, parity);
31027 + return(parity % 2);
31029 +static int ssfdc_physical(partition_t * pt_smcpart, int zone, int block) {
31031 + unsigned int * logical;
31033 + logical = pt_smcpart->zone + (zone * 2048);
31035 + logical += block;
31037 + if(*logical == 0xFFFFFFFF) {
31038 + PDEBUG("ssfdc_physical : physical for zone %d, block %d invalid\n", zone, block);
31042 + PDEBUG("ssfdc_physical : physical for zone %d, block %d, 0x%x\n", zone, block, (*logical * SMC_BLOCK_SIZE));
31043 + return(*logical * SMC_BLOCK_SIZE);
31046 +static int ssfdc_close(struct inode *inode, struct file *file)
31048 + int minor = MINOR(inode->i_rdev);
31049 + partition_t *pt_smcpart;
31050 + int index = (minor & ~(MAX_PARTITIONS -1)) >> PARTITION_BITS;
31052 + if (minor >= MAX_MTD_DEVICES)
31055 + if(SMCParts[index].type != SSFDC_FORMAT)
31058 + pt_smcpart = &SMCParts[index];
31059 + atomic_dec(&pt_smcpart->minor[minor & ~(MAX_PARTITIONS -1)].open);
31060 + put_mtd_device(pt_smcpart->mtd);
31061 + BLK_DEC_USE_COUNT;
31067 +static void do_ssfdc_request(request_arg_t)
31070 + partition_t *pt_smcpart;
31078 + minor = MINOR(CURRENT->rq_dev);
31079 + index = (minor & ~(MAX_PARTITIONS -1)) >> PARTITION_BITS;
31081 + pt_smcpart = &SMCParts[index];
31082 + if (pt_smcpart->type == SSFDC_FORMAT) {
31084 + switch (CURRENT->cmd) {
31086 + ret = ssfdc_read(pt_smcpart, CURRENT->buffer,
31087 + CURRENT->sector + ssfdc_hd[minor].start_sect,
31088 + CURRENT->current_nr_sectors);
31092 + ret = ssfdc_write(pt_smcpart, CURRENT->buffer,
31093 + CURRENT->sector + ssfdc_hd[minor].start_sect,
31094 + CURRENT->current_nr_sectors);
31098 + panic("do_ssfdc_request : unknown block command!\n");
31103 + PDEBUG("not ssfdc partition type\n");
31107 + CURRENT->sector += CURRENT->current_nr_sectors;
31110 + end_request((ret == 0) ? 1 : 0);
31114 +static int ssfdc_write(partition_t *pt_smcpart, caddr_t buffer,
31115 + u_long sector, u_long nblocks)
31117 + int zone, block, offset;
31118 + int sectors_written = 0;
31120 + int * pt_logical;
31121 + int * pt_physical;
31127 + int ptr_done = 0;
31128 + unsigned char * ptr = (unsigned char *)buffer;
31129 + unsigned char ecc_code[6], ecc_calc[6];
31131 +// unsigned char smc_status;
31135 + offset = (sector % SECTORS_PER_ZONE) % SECTORS_PER_BLOCK ;
31137 + PDEBUG("write device %d, sector %d, count %d\n",
31138 + pt_smcpart->count, sector, nblocks);
31140 + smc_status = in_8((void *)&pt_ssfdc_smc->smc_status);
31141 + if(!(smc_status & SMC_PRESENT)) {
31142 + printk("ssfdc : media not present\n");
31146 + if(smc_status & SMC_CHANGED) {
31147 + out_8((void *)&pt_ssfdc_smc->smc_status, smc_status);
31148 + ssfdc_read_partitions(pt_smcpart);
31149 + printk("ssfdc : media change\n");
31152 + while(sectors_written < nblocks) {
31155 + do_erase = FALSE;
31157 + zone = (sector + sectors_written) / SECTORS_PER_ZONE;
31158 + block = ((sector + sectors_written) % SECTORS_PER_ZONE) / SECTORS_PER_BLOCK ;
31159 + offset = ((sector + sectors_written) % SECTORS_PER_ZONE) % SECTORS_PER_BLOCK ;
31161 + pt_logical = pt_smcpart->zone + (zone * 2048);
31162 + pt_physical = pt_smcpart->zone + (zone * 2048) + 1024;
31164 + size = ((SECTORS_PER_BLOCK - offset) < (nblocks - sectors_written)) ?
31165 + (SECTORS_PER_BLOCK - offset) : (nblocks - sectors_written);
31166 + size *= SECTOR_SIZE;
31168 + PDEBUG("write device %d, sector %d, count %d, zone %d, block %d, offset %d, done %d, size %d, address 0x%x\n",
31169 + pt_smcpart->count, sector, nblocks, zone, block, offset, sectors_written, size, (unsigned int)ptr);
31171 + physical = ssfdc_physical(pt_smcpart, zone, block);
31174 + if(physical >= 0) {
31175 + if(ssfdc_cached != physical) {
31176 + pt_smcpart->mtd->read_ecc(pt_smcpart->mtd, physical, SMC_BLOCK_SIZE, &retlen, ssfdc_scratch,
31177 + ssfdc_oob_buf, &ssfdc_ffoob_info);
31178 + if(retlen != SMC_BLOCK_SIZE) {
31179 + printk(KERN_WARNING "ssfdc_write : failed to read physical\n");
31183 + for(sc=0; sc<SECTORS_PER_BLOCK; sc++) {
31184 + pt_smcpart->mtd->read_oob(pt_smcpart->mtd, physical + (sc * SECTOR_SIZE), sizeof(ssfdc_buffer), &retlen, ssfdc_buffer);
31185 + if(retlen != sizeof(ssfdc_buffer)) {
31186 + printk(KERN_WARNING "ssfdc_write : failed to read physical oob\n");
31190 + nand_calculate_ecc (pt_smcpart->mtd, &ssfdc_scratch[sc * SECTOR_SIZE], &ecc_calc[0]);
31191 + nand_calculate_ecc (pt_smcpart->mtd, &ssfdc_scratch[(sc * SECTOR_SIZE) + 256], &ecc_calc[3]);
31192 + for(i=0; i<6; i++) ecc_code[i] = ssfdc_buffer[ssfdc_ecc[i]];
31193 + nand_correct_data(pt_smcpart->mtd, &ssfdc_scratch[sc * SECTOR_SIZE], &ecc_code[0], &ecc_calc[0]);
31194 + nand_correct_data(pt_smcpart->mtd, &ssfdc_scratch[(sc * SECTOR_SIZE) + 256], &ecc_code[3], &ecc_calc[3]);
31199 + for(sc=0; sc<SECTORS_PER_BLOCK; sc++) {
31200 + if(offset > sc) {
31201 + PDEBUG("offset %d, sector %d\n", offset, sc);
31204 + pt_smcpart->mtd->read_oob(pt_smcpart->mtd, physical + (sc * SECTOR_SIZE), sizeof(ssfdc_buffer), &retlen, ssfdc_buffer);
31205 + if(retlen != sizeof(ssfdc_buffer)) {
31206 + printk(KERN_WARNING "ssfdc_write : failed to read physical oob\n");
31210 + nand_calculate_ecc (pt_smcpart->mtd, &ssfdc_scratch[sc * SECTOR_SIZE], &ecc_calc[0]);
31211 + nand_calculate_ecc (pt_smcpart->mtd, &ssfdc_scratch[(sc * SECTOR_SIZE) + 256], &ecc_calc[3]);
31212 + for(i=0; i<6; i++) ecc_code[i] = ssfdc_buffer[ssfdc_ecc[i]];
31213 + nand_correct_data(pt_smcpart->mtd, &ssfdc_scratch[sc * SECTOR_SIZE], &ecc_code[0], &ecc_calc[0]);
31214 + nand_correct_data(pt_smcpart->mtd, &ssfdc_scratch[(sc * SECTOR_SIZE) + 256], &ecc_code[3], &ecc_calc[3]);
31216 + /* find out if the block is being used */
31219 + if(ssfdc_sector_blank(pt_smcpart, sc)) {
31220 + PDEBUG("ssfdc_write : zone %d, block %d, sector %d, lbn %d, blank, physical 0x%x\n",
31221 + zone, block, sc, sector, physical);
31222 + memcpy(&ssfdc_scratch[(sc * SECTOR_SIZE)], ptr+ptr_done, SECTOR_SIZE);
31223 + nand_calculate_ecc (pt_smcpart->mtd, (ptr + ptr_done), &ecc_calc[0]);
31224 + nand_calculate_ecc (pt_smcpart->mtd, (ptr + ptr_done + 256), &ecc_calc[3]);
31225 + for(i=0; i<6; i++) ssfdc_buffer[ssfdc_ecc[i]] = ecc_calc[i];
31226 + i = (block << 1) | 0x1000;
31227 + i |= ssfdc_parity(block);
31228 + ssfdc_buffer[7] = ssfdc_buffer[12] = i & 0xFF;
31229 + ssfdc_buffer[6] = ssfdc_buffer[11] = (i & 0xFF00) >> 0x08;
31231 + pt_smcpart->mtd->write_ecc(pt_smcpart->mtd, physical + (sc * SECTOR_SIZE), SECTOR_SIZE, &retlen,
31232 + ptr + ptr_done, ssfdc_buffer, &ssfdc_ffoob_info);
31233 + if(retlen != SECTOR_SIZE) {
31234 + printk(KERN_WARNING "ssfdc_write : failed to write physical 0x%x, sector 0x%x, blank, retlen %d\n"
31235 + , physical, sc, retlen);
31239 + ptr_done += SECTOR_SIZE;
31240 + if(ptr_done >= size) break;
31243 + new = ssfdc_allocate_new(pt_smcpart, zone);
31244 + /* erase the old block */
31245 + *(pt_physical + ((physical % ZONE_SIZE) / SMC_BLOCK_SIZE)) = 0xFFFFFFFF;
31247 + PDEBUG("ssfdc_write : physical 0x%x + 0x%x = 0x%x\n",
31248 + (unsigned int)pt_physical, ((physical % ZONE_SIZE) / SMC_BLOCK_SIZE), 0xFFFFFFFF);
31250 + PDEBUG("ssfdc_write : zone %d, block %d, sector %d, lbn %d, written, physical 0x%x, new 0x%x\n",
31251 + zone, block, sc, sector, physical, new);
31257 + ssfdc_cached = 0xFFFFFFFF;
31258 + memset(ssfdc_scratch, 0xFF, sizeof(ssfdc_scratch));
31259 + new = ssfdc_allocate_new(pt_smcpart, zone);
31260 + PDEBUG("ssfdc_write : zone %d, block %d, lbn %d, physical 0x%x, unallocated, new 0x%x\n",
31261 + zone, block, sector, physical, new);
31269 + memcpy(&ssfdc_scratch[(offset * SECTOR_SIZE)], ptr, size);
31270 + PDEBUG("ssfdc_write : new 0x%x, offset 0x%x, size 0x%x, block 0x%x\n", new, offset, size, block);
31271 + for(sc=0; sc<SECTORS_PER_BLOCK; sc++) {
31272 + memset(ssfdc_buffer, 0xFF, OOB_SIZE);
31273 + nand_calculate_ecc (pt_smcpart->mtd, &ssfdc_scratch[sc * SECTOR_SIZE], &ecc_calc[0]);
31274 + nand_calculate_ecc (pt_smcpart->mtd, &ssfdc_scratch[(sc * SECTOR_SIZE) + 256], &ecc_calc[3]);
31275 + for(i=0; i<6; i++) ssfdc_buffer[ssfdc_ecc[i]] = ecc_calc[i];
31276 + i = (block << 1) | 0x1000;
31277 + i |= ssfdc_parity(block);
31278 + ssfdc_buffer[7] = ssfdc_buffer[12] = i & 0xFF;
31279 + ssfdc_buffer[6] = ssfdc_buffer[11] = (i & 0xFF00) >> 0x08;
31280 + memcpy(&ssfdc_oob_buf[sc * OOB_SIZE], ssfdc_buffer, OOB_SIZE);
31284 + pt_smcpart->mtd->write_ecc(pt_smcpart->mtd, new, SMC_BLOCK_SIZE, &retlen, ssfdc_scratch,
31285 + ssfdc_oob_buf, &ssfdc_ffoob_info);
31286 + if(retlen != SMC_BLOCK_SIZE) {
31287 + printk(KERN_WARNING "ssfdc_write : failed to write block, physical 0x%x, returned 0x%x\n", new, retlen);
31290 + /* change the mapping table to reflect the new block placement */
31292 + *(pt_logical + block) = (new % ZONE_SIZE) / SMC_BLOCK_SIZE;
31293 + PDEBUG("ssfdc_write : logical 0x%x + 0x%x = 0x%x\n",
31294 + (unsigned int)pt_logical, block, (new % ZONE_SIZE) / SMC_BLOCK_SIZE);
31296 + *(pt_physical + ((new % ZONE_SIZE) / SMC_BLOCK_SIZE)) = block;
31297 + PDEBUG("ssfdc_write : physical 0x%x + 0x%x = 0x%x\n",
31298 + (unsigned int)pt_physical, ((new % ZONE_SIZE) / SMC_BLOCK_SIZE), block);
31301 + ssfdc_cached = new;
31307 + sectors_written += (size / SECTOR_SIZE);
31308 + if(do_erase) ssfdc_erase(pt_smcpart, physical);
31317 +static int ssfdc_sector_blank(partition_t * pt_smcpart, int sc) {
31320 + for(b=0; b<SECTOR_SIZE; b++) {
31321 + if(ssfdc_scratch[b + (sc * SECTOR_SIZE)] != 0xFF) return(0);
31323 + for(b=0; b<OOB_SIZE; b++) {
31324 + if((b==6) || (b==7) || (b==11) || (b==12)) continue; // Block address fields
31325 + if(ssfdc_buffer[b] != 0xFF) return(0);
31329 +static int ssfdc_allocate_new(partition_t * pt_smcpart, int zone) {
31331 + int new = pt_smcpart->last_written[zone] + 1;
31332 + int * pt_physical;
31336 + unsigned char oob[16];
31339 + if(new >= BLOCKS_PER_ZONE) new = 0;
31342 + while (new != pt_smcpart->last_written[zone]) {
31343 + block = new % BLOCKS_PER_ZONE;
31344 + pt_physical = pt_smcpart->zone + (zone * 2048) + 1024 + block;
31345 + physical = (zone * ZONE_SIZE) + (block * SMC_BLOCK_SIZE);
31347 + PDEBUG("ssfdc_allocate_new : zone %d, block %d, address 0x%08x, data 0x%08x\n",
31348 + zone, block, (unsigned int)pt_physical, *pt_physical);
31349 + if(*pt_physical == 0xFFFFFFFF) {
31350 + PDEBUG("ssfdc_allocate_new : physical 0x%x = 0x%x\n", (unsigned int)pt_physical, *pt_physical);
31351 + memset(oob, 0, OOB_SIZE);
31352 + pt_smcpart->mtd->read_oob(pt_smcpart->mtd, physical, OOB_SIZE, &retlen, oob);
31353 + if((oob[5] == 0xFF) && (retlen == OOB_SIZE)) { // If not a bad block
31354 + pt_smcpart->last_written[zone] = new;
31355 + return((new * SMC_BLOCK_SIZE) + (zone * ZONE_SIZE));
31358 + PDEBUG("ssfdc_allocate_new : new 0x%x, physical 0x%x, block status 0x%x, oob length 0x%x\n", new, physical, oob[5], retlen);
31362 + if(new >= BLOCKS_PER_ZONE) new = 0;
31365 + panic("ssfdc_allocate_new : cant find free block\n");
31371 +static int ssfdc_read(partition_t *pt_smcpart, caddr_t buffer,
31372 + u_long sector, u_long nblocks)
31374 + int zone, block, offset;
31375 + int sectors_read = 0;
31381 + unsigned char * ptr = (unsigned char *)buffer;
31382 + unsigned char ecc_code[6], ecc_calc[6];
31384 + unsigned char smc_status;
31386 + smc_status = in_8((void *)&pt_ssfdc_smc->smc_status);
31387 + if(!(smc_status & SMC_PRESENT)) {
31388 + printk("ssfdc : media not present\n");
31394 + if(smc_status & SMC_CHANGED) {
31395 + out_8((void *)&pt_ssfdc_smc->smc_status, smc_status);
31396 + ssfdc_read_partitions(pt_smcpart);
31397 + printk("ssfdc : media change\n");
31400 + while(sectors_read < nblocks) {
31402 + zone = (sector + sectors_read) / SECTORS_PER_ZONE;
31403 + block = ((sector + sectors_read) % SECTORS_PER_ZONE) / SECTORS_PER_BLOCK ;
31404 + offset = ((sector + sectors_read) % SECTORS_PER_ZONE) % SECTORS_PER_BLOCK ;
31408 + size = ((SECTORS_PER_BLOCK - offset) < (nblocks - sectors_read)) ?
31409 + (SECTORS_PER_BLOCK - offset) : (nblocks - sectors_read);
31412 + size = (SECTORS_PER_BLOCK < (nblocks - sectors_read)) ? SECTORS_PER_BLOCK : nblocks - sectors_read;
31414 + size *= SECTOR_SIZE;
31416 + PDEBUG("ssfdc_read : device %d, sector %d, count %d, zone %d, block %d, offset %d, done %d, size %d, address 0x%x\n",
31417 + pt_smcpart->count, sector, nblocks, zone, block, offset, sectors_read, size, (unsigned int)ptr);
31420 + physical = ssfdc_physical(pt_smcpart, zone, block);
31421 + if(physical >= 0) {
31422 + if(ssfdc_cached != physical) {
31423 + pt_smcpart->mtd->read_ecc(pt_smcpart->mtd, physical, SMC_BLOCK_SIZE, &retlen, ssfdc_scratch,
31424 + ssfdc_oob_buf, &ssfdc_ffoob_info);
31425 + if(retlen != SMC_BLOCK_SIZE) {
31426 + printk(KERN_WARNING "ssfdc_read : failed to read physical\n");
31429 + for(sc=0; sc<SECTORS_PER_BLOCK; sc++) {
31430 + pt_smcpart->mtd->read_oob(pt_smcpart->mtd, physical + (sc * SECTOR_SIZE), sizeof(ssfdc_buffer), &retlen, ssfdc_buffer);
31431 + if(retlen != sizeof(ssfdc_buffer)) {
31432 + printk(KERN_WARNING "ssfdc_read : failed to read physical oob\n");
31435 + nand_calculate_ecc (pt_smcpart->mtd, &ssfdc_scratch[sc * SECTOR_SIZE], &ecc_calc[0]);
31436 + nand_calculate_ecc (pt_smcpart->mtd, &ssfdc_scratch[(sc * SECTOR_SIZE) + 256], &ecc_calc[3]);
31437 + for(i=0; i<3; i++) ecc_code[i] = ssfdc_buffer[ssfdc_ecc[i]];
31438 + for(i=3; i<6; i++) ecc_code[i] = ssfdc_buffer[ssfdc_ecc[i]];
31439 + nand_correct_data(pt_smcpart->mtd, &ssfdc_scratch[sc * SECTOR_SIZE], &ecc_code[0], &ecc_calc[0]);
31440 + nand_correct_data(pt_smcpart->mtd, &ssfdc_scratch[(sc * SECTOR_SIZE) + 256], &ecc_code[3], &ecc_calc[3]);
31443 + /* Get the ecc bytes and check that they are ok */
31447 + ssfdc_cached = physical;
31452 + memset(ssfdc_scratch, 0xFF, sizeof(ssfdc_scratch));
31453 + ssfdc_cached = 0xFFFFFFFF;
31457 + memcpy(ptr, &ssfdc_scratch[(offset * SECTOR_SIZE)], size);
31459 + sectors_read += (size / SECTOR_SIZE);
31467 +static void ssfdc_erase_callback(struct erase_info *erase) {
31469 + PDEBUG("ssfdc_erase_callback : wake erase\n");
31470 + up(&ssfdc_semaphore);
31471 + PDEBUG("ssfdc_erase_callback : woken erase\n");
31474 +static int ssfdc_erase(partition_t *pt_smcpart, unsigned int offset)
31477 + struct erase_info *erase;
31478 + unsigned char * junk;
31479 + unsigned char * oob;
31484 + PDEBUG("ssfdc_erase : offset 0x%08x\n", offset);
31486 + erase=kmalloc(sizeof(struct erase_info), GFP_KERNEL);
31487 + junk=kmalloc(pt_smcpart->mtd->erasesize + 16, GFP_KERNEL);
31488 + oob = junk + pt_smcpart->mtd->erasesize;
31495 + erase->addr = offset;
31496 + erase->len = pt_smcpart->mtd->erasesize;
31497 + erase->callback = ssfdc_erase_callback;
31498 + ret = pt_smcpart->mtd->erase(pt_smcpart->mtd, erase);
31500 + printk(KERN_WARNING "ssfdc_erase : failed status 0x%x\n", ret);
31505 + down(&ssfdc_semaphore);
31507 + pt_smcpart->mtd->read_ecc(pt_smcpart->mtd, offset, SMC_BLOCK_SIZE, &retlen, junk,
31508 + ssfdc_oob_buf, &ssfdc_ffoob_info);
31509 + if(retlen != SMC_BLOCK_SIZE) {
31510 + printk(KERN_WARNING "ssfdc_erase : offset 0x%x, read returned length %d\n", offset, retlen);
31515 + for(sc=0; sc < SECTORS_PER_BLOCK; sc++) {
31516 + for(b=0; b<SECTOR_SIZE; b++) {
31517 + if(*(junk + (b + (sc * SECTOR_SIZE))) != 0xFF) {
31518 + printk(KERN_WARNING "ssfdc_erase : offset 0x%x, sector 0x%x, byte 0x%x, data 0x%02x, expected 0xff\n"
31519 + , offset, sc, b, *(junk + (b + (sc * SECTOR_SIZE))));
31523 + pt_smcpart->mtd->read_oob(pt_smcpart->mtd, offset + (sc * SECTOR_SIZE), OOB_SIZE, &retlen, oob);
31524 + if(retlen != OOB_SIZE) {
31525 + printk(KERN_WARNING "ssfdc_erase : offset 0x%x, read oob returned length %d\n", offset, retlen);
31528 + for(b=0; b<OOB_SIZE; b++) {
31529 + if(*(oob+b) != 0xFF) {
31530 + printk(KERN_WARNING "ssfdc_erase : offset 0x%x, byte 0x%x, oob got 0x%02x, expected 0xff\n",
31531 + offset, b, *(oob+b));
31543 +} /* erase_xfer */
31549 +int init_ssfdc(void)
31553 +// unsigned char smc_status;
31554 +// #define B01159_FIO_PBASE 0x0000000148000000 /* Physical Base address of SMC control chip */
31556 + printk(KERN_INFO "SSFDC block device translation layer V1.0\n");
31558 + pt_ssfdc_smc = ioremap64(B01159_FIO_PBASE, 1024);
31559 + if(!pt_ssfdc_smc){
31560 + printk("ssfdc : failed to map SMC control device\n");
31564 + smc_status = in_8((void *)&pt_ssfdc_smc->smc_status);
31566 + memset(ssfdc_ffoob_buf, 0xFF, sizeof(ssfdc_ffoob_buf));
31568 + for (i = 0; i < MAX_DEVICES*MAX_PARTITIONS; i++) {
31569 + ssfdc_hd[i].nr_sects = 0;
31570 + ssfdc_hd[i].start_sect = 0;
31571 + ssfdc_blocksizes[i] = 4096;
31573 + blksize_size[SSFDC_MAJOR] = ssfdc_blocksizes;
31574 + ssfdc_gendisk.major = SSFDC_MAJOR;
31577 + memset(ssfdc_scratch, 0xFF, sizeof(ssfdc_scratch));
31579 + result = register_blkdev(ssfdc_major, "ssfdc", &ssfdc_fops);
31580 + if(result != 0) {
31581 + printk(KERN_WARNING "ssfdc : failed to get a major number\n");
31584 +// if(ssfdc_major == 0) ssfdc_major = result;
31586 + blk_init_queue(BLK_DEFAULT_QUEUE(ssfdc_major), &do_ssfdc_request);
31588 + add_gendisk(&ssfdc_gendisk);
31592 + register_mtd_user(&ssfdc_notifier);
31595 + init_MUTEX_LOCKED(&ssfdc_semaphore);
31602 +static void __exit cleanup_ssfdc(void)
31606 + for(i=0; i<MAX_DEVICES; i++) {
31607 + if(SMCParts[i].zone)kfree(SMCParts[i].zone);
31611 + unregister_mtd_user(&ssfdc_notifier);
31612 + unregister_blkdev(ssfdc_major, "ssfdc");
31613 + blk_cleanup_queue(BLK_DEFAULT_QUEUE(ssfdc_major));
31617 + blksize_size[SSFDC_MAJOR] = NULL;
31618 + del_gendisk(&ssfdc_gendisk);
31622 +module_init(init_ssfdc);
31623 +module_exit(cleanup_ssfdc);
31626 +MODULE_LICENSE("GPL");
31627 +MODULE_AUTHOR("Simon Haynes <simon@baydel.com>");
31628 +MODULE_DESCRIPTION("SSFDC translation layer support for MTD");
31633 Index: linux-2.6.5/include/linux/mtd/cfi.h
31634 ===================================================================
31635 --- linux-2.6.5.orig/include/linux/mtd/cfi.h 2004-04-03 22:36:56.000000000 -0500
31636 +++ linux-2.6.5/include/linux/mtd/cfi.h 2005-02-01 17:11:17.000000000 -0500
31639 /* Common Flash Interface structures
31640 * See http://support.intel.com/design/flash/technote/index.htm
31641 - * $Id: cfi.h,v 1.35 2003/05/28 15:37:32 dwmw2 Exp $
31642 + * $Id: cfi.h,v 1.46 2004/08/12 07:49:04 eric Exp $
31645 #ifndef __MTD_CFI_H__
31646 @@ -13,200 +13,74 @@
31647 #include <linux/types.h>
31648 #include <linux/interrupt.h>
31649 #include <linux/mtd/flashchip.h>
31650 +#include <linux/mtd/map.h>
31651 #include <linux/mtd/cfi_endian.h>
31654 - * You can optimize the code size and performance by defining only
31655 - * the geometry(ies) available on your hardware.
31656 - * CFIDEV_INTERLEAVE_n, where represents the interleave (number of chips to fill the bus width)
31657 - * CFIDEV_BUSWIDTH_n, where n is the bus width in bytes (1, 2, 4 or 8 bytes)
31659 - * By default, all (known) geometries are supported.
31662 -#ifndef CONFIG_MTD_CFI_GEOMETRY
31664 -/* The default case - support all but 64-bit, which has
31665 - a performance penalty */
31667 -#define CFIDEV_INTERLEAVE_1 (1)
31668 -#define CFIDEV_INTERLEAVE_2 (2)
31669 -#define CFIDEV_INTERLEAVE_4 (4)
31671 -#define CFIDEV_BUSWIDTH_1 (1)
31672 -#define CFIDEV_BUSWIDTH_2 (2)
31673 -#define CFIDEV_BUSWIDTH_4 (4)
31675 -typedef __u32 cfi_word;
31679 -/* Explicitly configured buswidth/interleave support */
31681 #ifdef CONFIG_MTD_CFI_I1
31682 -#define CFIDEV_INTERLEAVE_1 (1)
31684 -#ifdef CONFIG_MTD_CFI_I2
31685 -#define CFIDEV_INTERLEAVE_2 (2)
31687 -#ifdef CONFIG_MTD_CFI_I4
31688 -#define CFIDEV_INTERLEAVE_4 (4)
31690 -#ifdef CONFIG_MTD_CFI_I8
31691 -#define CFIDEV_INTERLEAVE_8 (8)
31694 -#ifdef CONFIG_MTD_CFI_B1
31695 -#define CFIDEV_BUSWIDTH_1 (1)
31697 -#ifdef CONFIG_MTD_CFI_B2
31698 -#define CFIDEV_BUSWIDTH_2 (2)
31700 -#ifdef CONFIG_MTD_CFI_B4
31701 -#define CFIDEV_BUSWIDTH_4 (4)
31703 -#ifdef CONFIG_MTD_CFI_B8
31704 -#define CFIDEV_BUSWIDTH_8 (8)
31707 -/* pick the largest necessary */
31708 -#ifdef CONFIG_MTD_CFI_B8
31709 -typedef __u64 cfi_word;
31711 -/* This only works if asm/io.h is included first */
31712 -#ifndef __raw_readll
31713 -#define __raw_readll(addr) (*(volatile __u64 *)(addr))
31715 -#ifndef __raw_writell
31716 -#define __raw_writell(v, addr) (*(volatile __u64 *)(addr) = (v))
31718 -#define CFI_WORD_64
31719 -#else /* CONFIG_MTD_CFI_B8 */
31720 -/* All others can use 32-bits. It's probably more efficient than
31721 - the smaller types anyway */
31722 -typedef __u32 cfi_word;
31723 -#endif /* CONFIG_MTD_CFI_B8 */
31728 - * The following macros are used to select the code to execute:
31729 - * cfi_buswidth_is_*()
31730 - * cfi_interleave_is_*()
31731 - * [where * is either 1, 2, 4, or 8]
31732 - * Those macros should be used with 'if' statements. If only one of few
31733 - * geometry arrangements are selected, they expand to constants thus allowing
31734 - * the compiler (most of them being 0) to optimize away all the unneeded code,
31735 - * while still validating the syntax (which is not possible with embedded
31736 - * #if ... #endif constructs).
31737 - * The exception to this is the 64-bit versions, which need an extension
31738 - * to the cfi_word type, and cause compiler warnings about shifts being
31742 -#ifdef CFIDEV_INTERLEAVE_1
31743 -# ifdef CFIDEV_INTERLEAVE
31744 -# undef CFIDEV_INTERLEAVE
31745 -# define CFIDEV_INTERLEAVE (cfi->interleave)
31747 -# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_1
31749 -# define cfi_interleave_is_1() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_1)
31750 +#define cfi_interleave(cfi) 1
31751 +#define cfi_interleave_is_1(cfi) (cfi_interleave(cfi) == 1)
31753 -# define cfi_interleave_is_1() (0)
31754 +#define cfi_interleave_is_1(cfi) (0)
31757 -#ifdef CFIDEV_INTERLEAVE_2
31758 -# ifdef CFIDEV_INTERLEAVE
31759 -# undef CFIDEV_INTERLEAVE
31760 -# define CFIDEV_INTERLEAVE (cfi->interleave)
31761 +#ifdef CONFIG_MTD_CFI_I2
31762 +# ifdef cfi_interleave
31763 +# undef cfi_interleave
31764 +# define cfi_interleave(cfi) ((cfi)->interleave)
31766 -# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_2
31767 +# define cfi_interleave(cfi) 2
31769 -# define cfi_interleave_is_2() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_2)
31770 +#define cfi_interleave_is_2(cfi) (cfi_interleave(cfi) == 2)
31772 -# define cfi_interleave_is_2() (0)
31773 +#define cfi_interleave_is_2(cfi) (0)
31776 -#ifdef CFIDEV_INTERLEAVE_4
31777 -# ifdef CFIDEV_INTERLEAVE
31778 -# undef CFIDEV_INTERLEAVE
31779 -# define CFIDEV_INTERLEAVE (cfi->interleave)
31780 +#ifdef CONFIG_MTD_CFI_I4
31781 +# ifdef cfi_interleave
31782 +# undef cfi_interleave
31783 +# define cfi_interleave(cfi) ((cfi)->interleave)
31785 -# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_4
31786 +# define cfi_interleave(cfi) 4
31788 -# define cfi_interleave_is_4() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_4)
31789 +#define cfi_interleave_is_4(cfi) (cfi_interleave(cfi) == 4)
31791 -# define cfi_interleave_is_4() (0)
31792 +#define cfi_interleave_is_4(cfi) (0)
31795 -#ifdef CFIDEV_INTERLEAVE_8
31796 -# ifdef CFIDEV_INTERLEAVE
31797 -# undef CFIDEV_INTERLEAVE
31798 -# define CFIDEV_INTERLEAVE (cfi->interleave)
31799 +#ifdef CONFIG_MTD_CFI_I8
31800 +# ifdef cfi_interleave
31801 +# undef cfi_interleave
31802 +# define cfi_interleave(cfi) ((cfi)->interleave)
31804 -# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_8
31805 +# define cfi_interleave(cfi) 8
31807 -# define cfi_interleave_is_8() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_8)
31808 +#define cfi_interleave_is_8(cfi) (cfi_interleave(cfi) == 8)
31810 -# define cfi_interleave_is_8() (0)
31811 +#define cfi_interleave_is_8(cfi) (0)
31814 -#ifndef CFIDEV_INTERLEAVE
31815 -#error You must define at least one interleave to support!
31816 +static inline int cfi_interleave_supported(int i)
31819 +#ifdef CONFIG_MTD_CFI_I1
31823 -#ifdef CFIDEV_BUSWIDTH_1
31824 -# ifdef CFIDEV_BUSWIDTH
31825 -# undef CFIDEV_BUSWIDTH
31826 -# define CFIDEV_BUSWIDTH (map->buswidth)
31828 -# define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_1
31830 -# define cfi_buswidth_is_1() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_1)
31832 -# define cfi_buswidth_is_1() (0)
31833 +#ifdef CONFIG_MTD_CFI_I2
31837 -#ifdef CFIDEV_BUSWIDTH_2
31838 -# ifdef CFIDEV_BUSWIDTH
31839 -# undef CFIDEV_BUSWIDTH
31840 -# define CFIDEV_BUSWIDTH (map->buswidth)
31842 -# define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_2
31844 -# define cfi_buswidth_is_2() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_2)
31846 -# define cfi_buswidth_is_2() (0)
31847 +#ifdef CONFIG_MTD_CFI_I4
31851 -#ifdef CFIDEV_BUSWIDTH_4
31852 -# ifdef CFIDEV_BUSWIDTH
31853 -# undef CFIDEV_BUSWIDTH
31854 -# define CFIDEV_BUSWIDTH (map->buswidth)
31856 -# define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_4
31858 -# define cfi_buswidth_is_4() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_4)
31860 -# define cfi_buswidth_is_4() (0)
31861 +#ifdef CONFIG_MTD_CFI_I8
31866 -#ifdef CFIDEV_BUSWIDTH_8
31867 -# ifdef CFIDEV_BUSWIDTH
31868 -# undef CFIDEV_BUSWIDTH
31869 -# define CFIDEV_BUSWIDTH (map->buswidth)
31871 -# define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_8
31873 -# define cfi_buswidth_is_8() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_8)
31875 -# define cfi_buswidth_is_8() (0)
31882 -#ifndef CFIDEV_BUSWIDTH
31883 -#error You must define at least one bus width to support!
31886 /* NB: these values must represents the number of bytes needed to meet the
31887 * device type (x8, x16, x32). Eg. a 32 bit device is 4 x 8 bytes.
31888 @@ -223,64 +97,84 @@
31890 /* Basic Query Structure */
31901 - __u8 WordWriteTimeoutTyp;
31902 - __u8 BufWriteTimeoutTyp;
31903 - __u8 BlockEraseTimeoutTyp;
31904 - __u8 ChipEraseTimeoutTyp;
31905 - __u8 WordWriteTimeoutMax;
31906 - __u8 BufWriteTimeoutMax;
31907 - __u8 BlockEraseTimeoutMax;
31908 - __u8 ChipEraseTimeoutMax;
31910 - __u16 InterfaceDesc;
31911 - __u16 MaxBufWriteSize;
31912 - __u8 NumEraseRegions;
31913 - __u32 EraseRegionInfo[0]; /* Not host ordered */
31923 + uint8_t WordWriteTimeoutTyp;
31924 + uint8_t BufWriteTimeoutTyp;
31925 + uint8_t BlockEraseTimeoutTyp;
31926 + uint8_t ChipEraseTimeoutTyp;
31927 + uint8_t WordWriteTimeoutMax;
31928 + uint8_t BufWriteTimeoutMax;
31929 + uint8_t BlockEraseTimeoutMax;
31930 + uint8_t ChipEraseTimeoutMax;
31932 + uint16_t InterfaceDesc;
31933 + uint16_t MaxBufWriteSize;
31934 + uint8_t NumEraseRegions;
31935 + uint32_t EraseRegionInfo[0]; /* Not host ordered */
31936 } __attribute__((packed));
31938 /* Extended Query Structure for both PRI and ALT */
31940 struct cfi_extquery {
31942 - __u8 MajorVersion;
31943 - __u8 MinorVersion;
31945 + uint8_t MajorVersion;
31946 + uint8_t MinorVersion;
31947 } __attribute__((packed));
31949 /* Vendor-Specific PRI for Intel/Sharp Extended Command Set (0x0001) */
31951 struct cfi_pri_intelext {
31953 - __u8 MajorVersion;
31954 - __u8 MinorVersion;
31955 - __u32 FeatureSupport;
31956 - __u8 SuspendCmdSupport;
31957 - __u16 BlkStatusRegMask;
31960 - __u8 NumProtectionFields;
31961 - __u16 ProtRegAddr;
31962 - __u8 FactProtRegSize;
31963 - __u8 UserProtRegSize;
31965 + uint8_t MajorVersion;
31966 + uint8_t MinorVersion;
31967 + uint32_t FeatureSupport; /* if bit 31 is set then an additional uint32_t feature
31968 + block follows - FIXME - not currently supported */
31969 + uint8_t SuspendCmdSupport;
31970 + uint16_t BlkStatusRegMask;
31971 + uint8_t VccOptimal;
31972 + uint8_t VppOptimal;
31973 + uint8_t NumProtectionFields;
31974 + uint16_t ProtRegAddr;
31975 + uint8_t FactProtRegSize;
31976 + uint8_t UserProtRegSize;
31977 +} __attribute__((packed));
31979 +/* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */
31981 +struct cfi_pri_amdstd {
31983 + uint8_t MajorVersion;
31984 + uint8_t MinorVersion;
31985 + uint8_t SiliconRevision; /* bits 1-0: Address Sensitive Unlock */
31986 + uint8_t EraseSuspend;
31988 + uint8_t TmpBlkUnprotect;
31989 + uint8_t BlkProtUnprot;
31990 + uint8_t SimultaneousOps;
31991 + uint8_t BurstMode;
31992 + uint8_t PageMode;
31995 + uint8_t TopBottom;
31996 } __attribute__((packed));
31998 struct cfi_pri_query {
32000 - __u32 ProtField[1]; /* Not host ordered */
32001 + uint8_t NumFields;
32002 + uint32_t ProtField[1]; /* Not host ordered */
32003 } __attribute__((packed));
32005 struct cfi_bri_query {
32006 - __u8 PageModeReadCap;
32008 - __u32 ConfField[1]; /* Not host ordered */
32009 + uint8_t PageModeReadCap;
32010 + uint8_t NumFields;
32011 + uint32_t ConfField[1]; /* Not host ordered */
32012 } __attribute__((packed));
32014 #define P_ID_NONE 0
32015 @@ -288,8 +182,10 @@
32016 #define P_ID_AMD_STD 2
32017 #define P_ID_INTEL_STD 3
32018 #define P_ID_AMD_EXT 4
32019 +#define P_ID_ST_ADV 32
32020 #define P_ID_MITSUBISHI_STD 256
32021 #define P_ID_MITSUBISHI_EXT 257
32022 +#define P_ID_SST_PAGE 258
32023 #define P_ID_RESERVED 65535
32026 @@ -297,14 +193,13 @@
32027 #define CFI_MODE_JEDEC 0
32029 struct cfi_private {
32035 int cfi_mode; /* Are we a JEDEC device pretending to be CFI? */
32039 struct mtd_info *(*cmdset_setup)(struct map_info *);
32040 struct cfi_ident *cfiq; /* For now only one. We insist that all devs
32041 must be of the same type. */
32042 @@ -315,107 +210,81 @@
32043 struct flchip chips[0]; /* per-chip data structure for each chip */
32046 -#define MAX_CFI_CHIPS 8 /* Entirely arbitrary to avoid realloc() */
32049 * Returns the command address according to the given geometry.
32051 -static inline __u32 cfi_build_cmd_addr(__u32 cmd_ofs, int interleave, int type)
32052 +static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int type)
32054 return (cmd_ofs * type) * interleave;
32058 - * Transforms the CFI command for the given geometry (bus width & interleave.
32059 + * Transforms the CFI command for the given geometry (bus width & interleave).
32060 + * It looks too long to be inline, but in the common case it should almost all
32061 + * get optimised away.
32063 -static inline cfi_word cfi_build_cmd(u_char cmd, struct map_info *map, struct cfi_private *cfi)
32064 +static inline map_word cfi_build_cmd(u_char cmd, struct map_info *map, struct cfi_private *cfi)
32066 - cfi_word val = 0;
32068 - if (cfi_buswidth_is_1()) {
32069 - /* 1 x8 device */
32071 - } else if (cfi_buswidth_is_2()) {
32072 - if (cfi_interleave_is_1()) {
32073 - /* 1 x16 device in x16 mode */
32074 - val = cpu_to_cfi16(cmd);
32075 - } else if (cfi_interleave_is_2()) {
32076 - /* 2 (x8, x16 or x32) devices in x8 mode */
32077 - val = cpu_to_cfi16((cmd << 8) | cmd);
32079 - } else if (cfi_buswidth_is_4()) {
32080 - if (cfi_interleave_is_1()) {
32081 - /* 1 x32 device in x32 mode */
32082 - val = cpu_to_cfi32(cmd);
32083 - } else if (cfi_interleave_is_2()) {
32084 - /* 2 x16 device in x16 mode */
32085 - val = cpu_to_cfi32((cmd << 16) | cmd);
32086 - } else if (cfi_interleave_is_4()) {
32087 - /* 4 (x8, x16 or x32) devices in x8 mode */
32088 - val = (cmd << 16) | cmd;
32089 - val = cpu_to_cfi32((val << 8) | val);
32091 -#ifdef CFI_WORD_64
32092 - } else if (cfi_buswidth_is_8()) {
32093 - if (cfi_interleave_is_1()) {
32094 - /* 1 x64 device in x64 mode */
32095 - val = cpu_to_cfi64(cmd);
32096 - } else if (cfi_interleave_is_2()) {
32097 - /* 2 x32 device in x32 mode */
32099 - val = cpu_to_cfi64((val << 32) | val);
32100 - } else if (cfi_interleave_is_4()) {
32101 - /* 4 (x16, x32 or x64) devices in x16 mode */
32102 - val = (cmd << 16) | cmd;
32103 - val = cpu_to_cfi64((val << 32) | val);
32104 - } else if (cfi_interleave_is_8()) {
32105 - /* 8 (x8, x16 or x32) devices in x8 mode */
32106 - val = (cmd << 8) | cmd;
32107 - val = (val << 16) | val;
32108 - val = (val << 32) | val;
32109 - val = cpu_to_cfi64(val);
32111 -#endif /* CFI_WORD_64 */
32115 -#define CMD(x) cfi_build_cmd((x), map, cfi)
32118 - * Read a value according to the bus width.
32121 -static inline cfi_word cfi_read(struct map_info *map, __u32 addr)
32123 - if (cfi_buswidth_is_1()) {
32124 - return map_read8(map, addr);
32125 - } else if (cfi_buswidth_is_2()) {
32126 - return map_read16(map, addr);
32127 - } else if (cfi_buswidth_is_4()) {
32128 - return map_read32(map, addr);
32129 - } else if (cfi_buswidth_is_8()) {
32130 - return map_read64(map, addr);
32131 + map_word val = { {0} };
32132 + int wordwidth, words_per_bus, chip_mode, chips_per_word;
32133 + unsigned long onecmd;
32136 + /* We do it this way to give the compiler a fighting chance
32137 + of optimising away all the crap for 'bankwidth' larger than
32138 + an unsigned long, in the common case where that support is
32140 + if (map_bankwidth_is_large(map)) {
32141 + wordwidth = sizeof(unsigned long);
32142 + words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
32145 + wordwidth = map_bankwidth(map);
32146 + words_per_bus = 1;
32149 + chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
32150 + chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
32152 + /* First, determine what the bit-pattern should be for a single
32153 + device, according to chip mode and endianness... */
32154 + switch (chip_mode) {
32160 + onecmd = cpu_to_cfi16(cmd);
32163 + onecmd = cpu_to_cfi32(cmd);
32169 - * Write a value according to the bus width.
32171 + /* Now replicate it across the size of an unsigned long, or
32172 + just to the bus width as appropriate */
32173 + switch (chips_per_word) {
32175 +#if BITS_PER_LONG >= 64
32177 + onecmd |= (onecmd << (chip_mode * 32));
32180 + onecmd |= (onecmd << (chip_mode * 16));
32182 + onecmd |= (onecmd << (chip_mode * 8));
32187 -static inline void cfi_write(struct map_info *map, cfi_word val, __u32 addr)
32189 - if (cfi_buswidth_is_1()) {
32190 - map_write8(map, val, addr);
32191 - } else if (cfi_buswidth_is_2()) {
32192 - map_write16(map, val, addr);
32193 - } else if (cfi_buswidth_is_4()) {
32194 - map_write32(map, val, addr);
32195 - } else if (cfi_buswidth_is_8()) {
32196 - map_write64(map, val, addr);
32197 + /* And finally, for the multi-word case, replicate it
32198 + in all words in the structure */
32199 + for (i=0; i < words_per_bus; i++) {
32200 + val.x[i] = onecmd;
32205 +#define CMD(x) cfi_build_cmd((x), map, cfi)
32208 * Sends a CFI command to a bank of flash for the given geometry.
32209 @@ -424,48 +293,47 @@
32210 * If prev_val is non-null, it will be set to the value at the command address,
32211 * before the command was written.
32213 -static inline __u32 cfi_send_gen_cmd(u_char cmd, __u32 cmd_addr, __u32 base,
32214 +static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base,
32215 struct map_info *map, struct cfi_private *cfi,
32216 - int type, cfi_word *prev_val)
32217 + int type, map_word *prev_val)
32220 - __u32 addr = base + cfi_build_cmd_addr(cmd_addr, CFIDEV_INTERLEAVE, type);
32222 + uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type);
32224 val = cfi_build_cmd(cmd, map, cfi);
32227 - *prev_val = cfi_read(map, addr);
32228 + *prev_val = map_read(map, addr);
32230 - cfi_write(map, val, addr);
32231 + map_write(map, val, addr);
32233 return addr - base;
32236 -static inline __u8 cfi_read_query(struct map_info *map, __u32 addr)
32237 +static inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr)
32239 - if (cfi_buswidth_is_1()) {
32240 - return map_read8(map, addr);
32241 - } else if (cfi_buswidth_is_2()) {
32242 - return cfi16_to_cpu(map_read16(map, addr));
32243 - } else if (cfi_buswidth_is_4()) {
32244 - return cfi32_to_cpu(map_read32(map, addr));
32245 - } else if (cfi_buswidth_is_8()) {
32246 - return cfi64_to_cpu(map_read64(map, addr));
32247 + map_word val = map_read(map, addr);
32249 + if (map_bankwidth_is_1(map)) {
32251 + } else if (map_bankwidth_is_2(map)) {
32252 + return cfi16_to_cpu(val.x[0]);
32255 + /* No point in a 64-bit byteswap since that would just be
32256 + swapping the responses from different chips, and we are
32257 + only interested in one chip (a representative sample) */
32258 + return cfi32_to_cpu(val.x[0]);
32262 static inline void cfi_udelay(int us)
32264 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
32265 unsigned long t = us * HZ / 1000000;
32267 set_current_state(TASK_UNINTERRUPTIBLE);
32268 schedule_timeout(t);
32275 @@ -480,4 +348,28 @@
32276 spin_unlock_bh(mutex);
32279 +struct cfi_extquery *cfi_read_pri(struct map_info *map, uint16_t adr, uint16_t size,
32280 + const char* name);
32281 +struct cfi_fixup {
32284 + void (*fixup)(struct mtd_info *mtd, void* param);
32288 +#define CFI_MFR_ANY 0xffff
32289 +#define CFI_ID_ANY 0xffff
32291 +#define CFI_MFR_AMD 0x0001
32292 +#define CFI_MFR_ST 0x0020 /* STMicroelectronics */
32294 +void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups);
32296 +typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
32297 + unsigned long adr, int len, void *thunk);
32299 +int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
32300 + loff_t ofs, size_t len, void *thunk);
32303 #endif /* __MTD_CFI_H__ */
32304 Index: linux-2.6.5/include/linux/mtd/compatmac.h
32305 ===================================================================
32306 --- linux-2.6.5.orig/include/linux/mtd/compatmac.h 2004-04-03 22:38:00.000000000 -0500
32307 +++ linux-2.6.5/include/linux/mtd/compatmac.h 2005-02-01 17:11:17.000000000 -0500
32310 + * $Id: compatmac.h,v 1.68 2004/09/17 22:00:30 eric Exp $
32312 + * Extensions and omissions from the normal 'linux/compatmac.h'
32313 + * files. hopefully this will end up empty as the 'real' one
32314 + * becomes fully-featured.
32317 #ifndef __LINUX_MTD_COMPATMAC_H__
32318 #define __LINUX_MTD_COMPATMAC_H__
32320 -/* Nothing to see here. We write 2.5-compatible code and this
32321 - file makes it all OK in older kernels, but it's empty in _current_
32322 - kernels. Include guard just to make GCC ignore it in future inclusions
32324 +#include <linux/version.h>
32326 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
32327 +#error "This kernel is too old: not supported by this file"
32330 + /* O(1) scheduler stuff. */
32332 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5) && !defined(__rh_config_h__)
32333 +#include <linux/sched.h>
32334 +static inline void __recalc_sigpending(void)
32336 + recalc_sigpending(current);
32338 +#undef recalc_sigpending
32339 +#define recalc_sigpending() __recalc_sigpending ()
32341 +#define set_user_nice(tsk, n) do { (tsk)->nice = n; } while(0)
32346 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20)
32349 +#define yield() do { set_current_state(TASK_RUNNING); schedule(); } while(0)
32353 +#define major(d) (MAJOR(to_kdev_t(d)))
32354 +#define minor(d) (MINOR(to_kdev_t(d)))
32358 +#define mk_kdev(ma,mi) MKDEV(ma,mi)
32359 +#define kdev_t_to_nr(x) (x)
32362 +#define need_resched() (current->need_resched)
32363 +#define cond_resched() do { if need_resched() { yield(); } } while(0)
32365 +#endif /* < 2.4.20 */
32366 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,73)
32367 +#define iminor(i) minor((i)->i_rdev)
32368 +#define imajor(i) major((i)->i_rdev)
32369 +#define old_encode_dev(d) ( (major(d)<<8) | minor(d) )
32370 +#define old_decode_dev(rdev) (kdev_t_to_nr(mk_kdev((rdev)>>8, (rdev)&0xff)))
32371 +#define old_valid_dev(d) (1)
32374 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61)
32376 +#include <linux/sched.h>
32378 +#ifdef __rh_config_h__
32379 +#define sigmask_lock sighand->siglock
32380 +#define sig sighand
32383 +static inline void __daemonize_modvers(void)
32387 + spin_lock_irq(¤t->sigmask_lock);
32388 + sigfillset(¤t->blocked);
32389 + recalc_sigpending();
32390 + spin_unlock_irq(¤t->sigmask_lock);
32393 +#define daemonize(fmt, ...) do { \
32394 + snprintf(current->comm, sizeof(current->comm), fmt ,##__VA_ARGS__); \
32395 + __daemonize_modvers(); \
32398 +static inline int dequeue_signal_lock(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
32400 + unsigned long flags;
32401 + unsigned long ret;
32403 + spin_lock_irqsave(¤t->sigmask_lock, flags);
32404 + ret = dequeue_signal(mask, info);
32405 + spin_unlock_irqrestore(¤t->sigmask_lock, flags);
32410 +static inline int allow_signal(int sig)
32412 + if (sig < 1 || sig > _NSIG)
32415 + spin_lock_irq(¤t->sigmask_lock);
32416 + sigdelset(¤t->blocked, sig);
32417 + recalc_sigpending();
32418 + /* Make sure the kernel neither eats it now converts to SIGKILL */
32419 + current->sig->action[sig-1].sa.sa_handler = (void *)2;
32420 + spin_unlock_irq(¤t->sigmask_lock);
32423 +static inline int disallow_signal(int sig)
32425 + if (sig < 1 || sig > _NSIG)
32428 + spin_lock_irq(¤t->sigmask_lock);
32429 + sigaddset(¤t->blocked, sig);
32430 + recalc_sigpending();
32432 + current->sig->action[sig-1].sa.sa_handler = SIG_DFL;
32433 + spin_unlock_irq(¤t->sigmask_lock);
32437 +#define PF_FREEZE 0
32438 +#define refrigerator(x) do { ; } while(0)
32441 + /* Module bits */
32444 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
32445 +#define try_module_get(m) try_inc_mod_count(m)
32446 +#define __module_get(m) do { if (!try_inc_mod_count(m)) BUG(); } while(0)
32447 +#define module_put(m) do { if (m) __MOD_DEC_USE_COUNT((struct module *)(m)); } while(0)
32448 +#define set_module_owner(x) do { x->owner = THIS_MODULE; } while(0)
32452 + /* Random filesystem stuff, only for JFFS2 really */
32454 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5)
32455 +#define parent_ino(d) ((d)->d_parent->d_inode->i_ino)
32458 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,12)
32459 +#define PageUptodate(x) Page_Uptodate(x)
32462 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)
32463 +#define get_seconds() CURRENT_TIME
32466 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,53)
32467 +#define generic_file_readonly_mmap generic_file_mmap
32470 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,70)
32472 +#include <linux/kmod.h>
32473 +#include <linux/string.h>
32475 +static inline char *strlcpy(char *dest, const char *src, int len)
32478 + return strncpy(dest, src, len-1);
32481 +static inline int do_old_request_module(const char *mod)
32483 + return request_module(mod);
32485 +#undef request_module
32486 +#define request_module(fmt, ...) \
32487 + ({ char modname[32]; snprintf(modname, 31, fmt ,##__VA_ARGS__); do_old_request_module(modname); })
32489 +#endif /* 2.5.70 */
32491 +#ifndef container_of
32492 +#define container_of(ptr, type, member) ({ \
32493 + const typeof( ((type *)0)->member ) *__mptr = (ptr); \
32494 + (type *)( (char *)__mptr - offsetof(type,member) );})
32497 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
32498 +#define kvec iovec
32506 +#ifndef list_for_each_entry_safe
32508 + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
32509 + * @pos: the type * to use as a loop counter.
32510 + * @n: another type * to use as temporary storage
32511 + * @head: the head for your list.
32512 + * @member: the name of the list_struct within the struct.
32514 +#define list_for_each_entry_safe(pos, n, head, member) \
32515 + for (pos = list_entry((head)->next, typeof(*pos), member), \
32516 + n = list_entry(pos->member.next, typeof(*pos), member); \
32517 + &pos->member != (head); \
32518 + pos = n, n = list_entry(n->member.next, typeof(*n), member))
32522 #endif /* __LINUX_MTD_COMPATMAC_H__ */
32523 Index: linux-2.6.5/include/linux/mtd/doc2000.h
32524 ===================================================================
32525 --- linux-2.6.5.orig/include/linux/mtd/doc2000.h 2004-04-03 22:37:07.000000000 -0500
32526 +++ linux-2.6.5/include/linux/mtd/doc2000.h 2005-02-01 17:11:17.000000000 -0500
32529 -/* Linux driver for Disk-On-Chip 2000 */
32530 -/* (c) 1999 Machine Vision Holdings, Inc. */
32531 -/* Author: David Woodhouse <dwmw2@mvhi.com> */
32532 -/* $Id: doc2000.h,v 1.17 2003/06/12 01:20:46 gerg Exp $ */
32534 + * Linux driver for Disk-On-Chip devices
32536 + * Copyright (C) 1999 Machine Vision Holdings, Inc.
32537 + * Copyright (C) 2001-2003 David Woodhouse <dwmw2@infradead.org>
32538 + * Copyright (C) 2002-2003 Greg Ungerer <gerg@snapgear.com>
32539 + * Copyright (C) 2002-2003 SnapGear Inc
32541 + * $Id: doc2000.h,v 1.23 2004/09/16 23:26:08 gleixner Exp $
32543 + * Released under GPL
32546 #ifndef __MTD_DOC2000_H__
32547 #define __MTD_DOC2000_H__
32549 #include <linux/mtd/mtd.h>
32550 +#include <asm/semaphore.h>
32554 @@ -73,16 +81,16 @@
32555 * Others use readb/writeb
32557 #if defined(__arm__)
32558 -#define ReadDOC_(adr, reg) ((unsigned char)(*(__u32 *)(((unsigned long)adr)+((reg)<<2))))
32559 -#define WriteDOC_(d, adr, reg) do{ *(__u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0)
32560 +#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2))))
32561 +#define WriteDOC_(d, adr, reg) do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0)
32562 #define DOC_IOREMAP_LEN 0x8000
32563 #elif defined(__ppc__)
32564 -#define ReadDOC_(adr, reg) ((unsigned char)(*(__u16 *)(((unsigned long)adr)+((reg)<<1))))
32565 -#define WriteDOC_(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0)
32566 +#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u16 *)(((unsigned long)adr)+((reg)<<1))))
32567 +#define WriteDOC_(d, adr, reg) do{ *(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0)
32568 #define DOC_IOREMAP_LEN 0x4000
32570 -#define ReadDOC_(adr, reg) readb(((unsigned long)adr) + (reg))
32571 -#define WriteDOC_(d, adr, reg) writeb(d, ((unsigned long)adr) + (reg))
32572 +#define ReadDOC_(adr, reg) readb((void __iomem *)(((unsigned long)adr) + (reg)))
32573 +#define WriteDOC_(d, adr, reg) writeb(d, (void __iomem *)(((unsigned long)adr) + (reg)))
32574 #define DOC_IOREMAP_LEN 0x2000
32577 @@ -106,6 +114,7 @@
32578 #define DOC_MODE_MDWREN 0x04
32580 #define DOC_ChipID_Doc2k 0x20
32581 +#define DOC_ChipID_Doc2kTSOP 0x21 /* internal number for MTD */
32582 #define DOC_ChipID_DocMil 0x30
32583 #define DOC_ChipID_DocMilPlus32 0x40
32584 #define DOC_ChipID_DocMilPlus16 0x41
32585 @@ -147,10 +156,10 @@
32586 #define MAX_FLOORS 4
32587 #define MAX_CHIPS 4
32589 -#define MAX_FLOORS_MIL 4
32590 +#define MAX_FLOORS_MIL 1
32591 #define MAX_CHIPS_MIL 1
32593 -#define MAX_FLOORS_MPLUS 1
32594 +#define MAX_FLOORS_MPLUS 2
32595 #define MAX_CHIPS_MPLUS 1
32597 #define ADDR_COLUMN 1
32598 @@ -159,9 +168,9 @@
32600 struct DiskOnChip {
32601 unsigned long physadr;
32602 - unsigned long virtadr;
32603 + void __iomem *virtadr;
32604 unsigned long totlen;
32605 - char ChipID; /* Type of DiskOnChip */
32606 + unsigned char ChipID; /* Type of DiskOnChip */
32609 unsigned long mfr; /* Flash IDs - only one type of flash per device */
32610 Index: linux-2.6.5/include/linux/mtd/flashchip.h
32611 ===================================================================
32612 --- linux-2.6.5.orig/include/linux/mtd/flashchip.h 2004-04-03 22:38:13.000000000 -0500
32613 +++ linux-2.6.5/include/linux/mtd/flashchip.h 2005-02-01 17:11:17.000000000 -0500
32616 * (C) 2000 Red Hat. GPLd.
32618 - * $Id: flashchip.h,v 1.9 2003/04/30 11:15:22 dwmw2 Exp $
32619 + * $Id: flashchip.h,v 1.14 2004/06/15 16:44:59 nico Exp $
32626 /* NOTE: confusingly, this can be used to refer to more than one chip at a time,
32627 - if they're interleaved. */
32628 + if they're interleaved. This can even refer to individual partitions on
32629 + the same physical chip when present. */
32632 unsigned long start; /* Offset within the map */
32635 int write_suspended:1;
32636 int erase_suspended:1;
32637 + unsigned long in_progress_block_addr;
32640 spinlock_t _spinlock; /* We do it like this because sometimes they'll be shared. */
32642 int word_write_time;
32643 int buffer_write_time;
32649 +/* This is used to handle contention on write/erase operations
32650 + between partitions of the same physical chip. */
32651 +struct flchip_shared {
32653 + struct flchip *writing;
32654 + struct flchip *erasing;
32658 #endif /* __MTD_FLASHCHIP_H__ */
32659 Index: linux-2.6.5/include/linux/mtd/ftl.h
32660 ===================================================================
32661 --- linux-2.6.5.orig/include/linux/mtd/ftl.h 2004-04-03 22:37:37.000000000 -0500
32662 +++ linux-2.6.5/include/linux/mtd/ftl.h 2005-02-01 17:11:17.000000000 -0500
32665 - * $Id: ftl.h,v 1.5 2001/06/02 20:35:51 dwmw2 Exp $
32666 + * $Id: ftl.h,v 1.6 2003/01/24 13:20:04 dwmw2 Exp $
32668 * Derived from (and probably identical to):
32669 * ftl.h 1.7 1999/10/25 20:23:17
32670 Index: linux-2.6.5/include/linux/mtd/gen_probe.h
32671 ===================================================================
32672 --- linux-2.6.5.orig/include/linux/mtd/gen_probe.h 2004-04-03 22:37:25.000000000 -0500
32673 +++ linux-2.6.5/include/linux/mtd/gen_probe.h 2005-02-01 17:11:17.000000000 -0500
32676 * (C) 2001, 2001 Red Hat, Inc.
32678 - * $Id: gen_probe.h,v 1.1 2001/09/02 18:50:13 dwmw2 Exp $
32679 + * $Id: gen_probe.h,v 1.2 2003/11/08 00:51:21 dsaxena Exp $
32682 #ifndef __LINUX_MTD_GEN_PROBE_H__
32683 @@ -10,12 +10,12 @@
32684 #include <linux/mtd/flashchip.h>
32685 #include <linux/mtd/map.h>
32686 #include <linux/mtd/cfi.h>
32687 +#include <asm/bitops.h>
32689 struct chip_probe {
32691 int (*probe_chip)(struct map_info *map, __u32 base,
32692 - struct flchip *chips, struct cfi_private *cfi);
32694 + unsigned long *chip_map, struct cfi_private *cfi);
32697 struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp);
32698 Index: linux-2.6.5/include/linux/mtd/inftl.h
32699 ===================================================================
32700 --- linux-2.6.5.orig/include/linux/mtd/inftl.h 2004-04-03 22:38:14.000000000 -0500
32701 +++ linux-2.6.5/include/linux/mtd/inftl.h 2005-02-01 17:11:17.000000000 -0500
32704 * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
32706 - * $Id: inftl.h,v 1.3 2003/05/23 11:35:34 dwmw2 Exp $
32707 + * $Id: inftl.h,v 1.6 2004/06/30 14:49:00 dbrown Exp $
32710 #ifndef __MTD_INFTL_H__
32711 #define __MTD_INFTL_H__
32713 +#ifndef __KERNEL__
32714 +#error This is a kernel header. Perhaps include nftl-user.h instead?
32717 #include <linux/mtd/blktrans.h>
32718 #include <linux/mtd/mtd.h>
32719 #include <linux/mtd/nftl.h>
32721 -#define OSAK_VERSION 0x5120
32722 -#define PERCENTUSED 98
32724 -#define SECTORSIZE 512
32725 +#include <mtd/inftl-user.h>
32727 #ifndef INFTL_MAJOR
32728 -#define INFTL_MAJOR 93 /* FIXME */
32729 +#define INFTL_MAJOR 94
32731 #define INFTL_PARTN_BITS 4
32733 -/* Block Control Information */
32735 -struct inftl_bci {
32739 -} __attribute__((packed));
32741 -struct inftl_unithead1 {
32742 - __u16 virtualUnitNo;
32743 - __u16 prevUnitNo;
32746 - __u8 parityPerField;
32748 -} __attribute__((packed));
32750 -struct inftl_unithead2 {
32751 - __u8 parityPerField;
32753 - __u16 prevUnitNo;
32754 - __u16 virtualUnitNo;
32757 -} __attribute__((packed));
32759 -struct inftl_unittail {
32760 - __u8 Reserved[4];
32762 - __u16 EraseMark1;
32763 -} __attribute__((packed));
32766 - struct inftl_unithead1 a;
32767 - struct inftl_unithead2 b;
32768 - struct inftl_unittail c;
32771 -struct inftl_oob {
32772 - struct inftl_bci b;
32773 - union inftl_uci u;
32777 -/* INFTL Media Header */
32779 -struct INFTLPartition {
32780 - __u32 virtualUnits;
32784 - __u32 spareUnits;
32787 -} __attribute__((packed));
32789 -struct INFTLMediaHeader {
32790 - char bootRecordID[8];
32791 - __u32 NoOfBootImageBlocks;
32792 - __u32 NoOfBinaryPartitions;
32793 - __u32 NoOfBDTLPartitions;
32794 - __u32 BlockMultiplierBits;
32795 - __u32 FormatFlags;
32796 - __u32 OsakVersion;
32797 - __u32 PercentUsed;
32798 - struct INFTLPartition Partitions[4];
32799 -} __attribute__((packed));
32801 -/* Partition flag types */
32802 -#define INFTL_BINARY 0x20000000
32803 -#define INFTL_BDTL 0x40000000
32804 -#define INFTL_LAST 0x80000000
32809 struct INFTLrecord {
32810 struct mtd_blktrans_dev mbd;
32811 - __u16 MediaUnit, SpareMediaUnit;
32814 struct INFTLMediaHeader MediaHdr;
32817 unsigned int nb_blocks; /* number of physical blocks */
32818 unsigned int nb_boot_blocks; /* number of blocks used by the bios */
32819 struct erase_info instr;
32820 + struct nand_oobinfo oobinfo;
32823 int INFTL_mount(struct INFTLrecord *s);
32824 Index: linux-2.6.5/include/linux/mtd/map.h
32825 ===================================================================
32826 --- linux-2.6.5.orig/include/linux/mtd/map.h 2004-04-03 22:36:56.000000000 -0500
32827 +++ linux-2.6.5/include/linux/mtd/map.h 2005-02-01 17:11:17.000000000 -0500
32830 /* Overhauled routines for dealing with different mmap regions of flash */
32831 -/* $Id: map.h,v 1.34 2003/05/28 12:42:22 dwmw2 Exp $ */
32832 +/* $Id: map.h,v 1.44 2004/09/16 23:26:08 gleixner Exp $ */
32834 #ifndef __LINUX_MTD_MAP_H__
32835 #define __LINUX_MTD_MAP_H__
32837 #include <linux/config.h>
32838 #include <linux/types.h>
32839 #include <linux/list.h>
32840 +#include <linux/mtd/compatmac.h>
32841 +#include <asm/unaligned.h>
32842 #include <asm/system.h>
32843 #include <asm/io.h>
32844 +#include <asm/bug.h>
32846 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
32847 +#define map_bankwidth(map) 1
32848 +#define map_bankwidth_is_1(map) (map_bankwidth(map) == 1)
32849 +#define map_bankwidth_is_large(map) (0)
32850 +#define map_words(map) (1)
32851 +#define MAX_MAP_BANKWIDTH 1
32853 +#define map_bankwidth_is_1(map) (0)
32856 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
32857 +# ifdef map_bankwidth
32858 +# undef map_bankwidth
32859 +# define map_bankwidth(map) ((map)->bankwidth)
32861 +# define map_bankwidth(map) 2
32862 +# define map_bankwidth_is_large(map) (0)
32863 +# define map_words(map) (1)
32865 +#define map_bankwidth_is_2(map) (map_bankwidth(map) == 2)
32866 +#undef MAX_MAP_BANKWIDTH
32867 +#define MAX_MAP_BANKWIDTH 2
32869 +#define map_bankwidth_is_2(map) (0)
32872 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
32873 +# ifdef map_bankwidth
32874 +# undef map_bankwidth
32875 +# define map_bankwidth(map) ((map)->bankwidth)
32877 +# define map_bankwidth(map) 4
32878 +# define map_bankwidth_is_large(map) (0)
32879 +# define map_words(map) (1)
32881 +#define map_bankwidth_is_4(map) (map_bankwidth(map) == 4)
32882 +#undef MAX_MAP_BANKWIDTH
32883 +#define MAX_MAP_BANKWIDTH 4
32885 +#define map_bankwidth_is_4(map) (0)
32888 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
32889 +# ifdef map_bankwidth
32890 +# undef map_bankwidth
32891 +# define map_bankwidth(map) ((map)->bankwidth)
32892 +# if BITS_PER_LONG < 64
32893 +# undef map_bankwidth_is_large
32894 +# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
32896 +# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long))
32899 +# define map_bankwidth(map) 8
32900 +# define map_bankwidth_is_large(map) (BITS_PER_LONG < 64)
32901 +# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long))
32903 +#define map_bankwidth_is_8(map) (map_bankwidth(map) == 8)
32904 +#undef MAX_MAP_BANKWIDTH
32905 +#define MAX_MAP_BANKWIDTH 8
32907 +#define map_bankwidth_is_8(map) (0)
32910 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
32911 +# ifdef map_bankwidth
32912 +# undef map_bankwidth
32913 +# define map_bankwidth(map) ((map)->bankwidth)
32914 +# undef map_bankwidth_is_large
32915 +# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
32917 +# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long))
32919 +# define map_bankwidth(map) 16
32920 +# define map_bankwidth_is_large(map) (1)
32921 +# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long))
32923 +#define map_bankwidth_is_16(map) (map_bankwidth(map) == 16)
32924 +#undef MAX_MAP_BANKWIDTH
32925 +#define MAX_MAP_BANKWIDTH 16
32927 +#define map_bankwidth_is_16(map) (0)
32930 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
32931 +# ifdef map_bankwidth
32932 +# undef map_bankwidth
32933 +# define map_bankwidth(map) ((map)->bankwidth)
32934 +# undef map_bankwidth_is_large
32935 +# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
32937 +# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long))
32939 +# define map_bankwidth(map) 32
32940 +# define map_bankwidth_is_large(map) (1)
32941 +# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long))
32943 +#define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
32944 +#undef MAX_MAP_BANKWIDTH
32945 +#define MAX_MAP_BANKWIDTH 32
32947 +#define map_bankwidth_is_32(map) (0)
32950 +#ifndef map_bankwidth
32951 +#error "No bus width supported. What's the point?"
32954 +static inline int map_bankwidth_supported(int w)
32957 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
32960 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
32963 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
32966 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
32969 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
32972 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
32982 +#define MAX_MAP_LONGS ( ((MAX_MAP_BANKWIDTH*8) + BITS_PER_LONG - 1) / BITS_PER_LONG )
32985 + unsigned long x[MAX_MAP_LONGS];
32988 /* The map stuff is very simple. You fill in your struct map_info with
32989 a handful of routines for accessing the device, making sure they handle
32990 paging etc. correctly if your device needs it. Then you pass it off
32991 - to a chip driver which deals with a mapped device - generally either
32992 - do_cfi_probe() or do_ram_probe(), either of which will return a
32993 - struct mtd_info if they liked what they saw. At which point, you
32994 - fill in the mtd->module with your own module address, and register
32996 + to a chip probe routine -- either JEDEC or CFI probe or both -- via
32997 + do_map_probe(). If a chip is recognised, the probe code will invoke the
32998 + appropriate chip driver (if present) and return a struct mtd_info.
32999 + At which point, you fill in the mtd->module with your own module
33000 + address, and register it with the MTD core code. Or you could partition
33001 + it and register the partitions instead, or keep it for your own private
33004 The mtd->priv field will point to the struct map_info, and any further
33005 private data required by the chip driver is linked from the
33006 @@ -33,31 +180,32 @@
33007 unsigned long phys;
33008 #define NO_XIP (-1UL)
33010 - unsigned long virt;
33011 + void __iomem *virt;
33014 - int buswidth; /* in octets */
33015 + int bankwidth; /* in octets. This isn't necessarily the width
33016 + of actual bus cycles -- it's the repeat interval
33017 + in bytes, before you are talking to the first chip again.
33020 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS
33021 - u8 (*read8)(struct map_info *, unsigned long);
33022 - u16 (*read16)(struct map_info *, unsigned long);
33023 - u32 (*read32)(struct map_info *, unsigned long);
33024 - u64 (*read64)(struct map_info *, unsigned long);
33025 - /* If it returned a 'long' I'd call it readl.
33030 + map_word (*read)(struct map_info *, unsigned long);
33031 void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
33032 - void (*write8)(struct map_info *, u8, unsigned long);
33033 - void (*write16)(struct map_info *, u16, unsigned long);
33034 - void (*write32)(struct map_info *, u32, unsigned long);
33035 - void (*write64)(struct map_info *, u64, unsigned long);
33037 + void (*write)(struct map_info *, const map_word, unsigned long);
33038 void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
33040 /* We can perhaps put in 'point' and 'unpoint' methods, if we really
33041 want to enable XIP for non-linear mappings. Not yet though. */
33043 + /* It's possible for the map driver to use cached memory in its
33044 + copy_from implementation (and _only_ with copy_from). However,
33045 + when the chip driver knows some flash area has changed contents,
33046 + it will signal it to the map driver through this routine to let
33047 + the map driver invalidate the corresponding cache as needed.
33048 + If there is no cache to care about this can be set to NULL. */
33049 + void (*inval_cache)(struct map_info *, unsigned long, ssize_t);
33051 /* set_vpp() must handle being reentered -- enable, enable, disable
33052 must leave it enabled. */
33053 void (*set_vpp)(struct map_info *, int);
33054 @@ -85,86 +233,173 @@
33055 #define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0)
33056 #define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0)
33058 -#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
33059 -#define map_read8(map, ofs) (map)->read8(map, ofs)
33060 -#define map_read16(map, ofs) (map)->read16(map, ofs)
33061 -#define map_read32(map, ofs) (map)->read32(map, ofs)
33062 -#define map_read64(map, ofs) (map)->read64(map, ofs)
33063 -#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len)
33064 -#define map_write8(map, datum, ofs) (map)->write8(map, datum, ofs)
33065 -#define map_write16(map, datum, ofs) (map)->write16(map, datum, ofs)
33066 -#define map_write32(map, datum, ofs) (map)->write32(map, datum, ofs)
33067 -#define map_write64(map, datum, ofs) (map)->write64(map, datum, ofs)
33068 -#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len)
33069 +#define INVALIDATE_CACHED_RANGE(map, from, size) \
33070 + do { if(map->inval_cache) map->inval_cache(map, from, size); } while(0)
33072 -extern void simple_map_init(struct map_info *);
33073 -#define map_is_linear(map) (map->phys != NO_XIP)
33076 -static inline u8 map_read8(struct map_info *map, unsigned long ofs)
33077 +static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2)
33079 - return __raw_readb(map->virt + ofs);
33081 + for (i=0; i<map_words(map); i++) {
33082 + if (val1.x[i] != val2.x[i])
33088 -static inline u16 map_read16(struct map_info *map, unsigned long ofs)
33089 +static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2)
33091 - return __raw_readw(map->virt + ofs);
33095 + for (i=0; i<map_words(map); i++) {
33096 + r.x[i] = val1.x[i] & val2.x[i];
33101 -static inline u32 map_read32(struct map_info *map, unsigned long ofs)
33102 +static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2)
33104 - return __raw_readl(map->virt + ofs);
33108 + for (i=0; i<map_words(map); i++) {
33109 + r.x[i] = val1.x[i] | val2.x[i];
33113 +#define map_word_andequal(m, a, b, z) map_word_equal(m, z, map_word_and(m, a, b))
33115 -static inline u64 map_read64(struct map_info *map, unsigned long ofs)
33116 +static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2)
33118 -#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */
33122 + for (i=0; i<map_words(map); i++) {
33123 + if (val1.x[i] & val2.x[i])
33128 - return __raw_readll(map->virt + ofs);
33132 -static inline void map_write8(struct map_info *map, u8 datum, unsigned long ofs)
33133 +static inline map_word map_word_load(struct map_info *map, const void *ptr)
33135 - __raw_writeb(datum, map->virt + ofs);
33139 + if (map_bankwidth_is_1(map))
33140 + r.x[0] = *(unsigned char *)ptr;
33141 + else if (map_bankwidth_is_2(map))
33142 + r.x[0] = get_unaligned((uint16_t *)ptr);
33143 + else if (map_bankwidth_is_4(map))
33144 + r.x[0] = get_unaligned((uint32_t *)ptr);
33145 +#if BITS_PER_LONG >= 64
33146 + else if (map_bankwidth_is_8(map))
33147 + r.x[0] = get_unaligned((uint64_t *)ptr);
33149 + else if (map_bankwidth_is_large(map))
33150 + memcpy(r.x, ptr, map->bankwidth);
33155 -static inline void map_write16(struct map_info *map, u16 datum, unsigned long ofs)
33156 +static inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len)
33158 - __raw_writew(datum, map->virt + ofs);
33162 + if (map_bankwidth_is_large(map)) {
33163 + char *dest = (char *)&orig;
33164 + memcpy(dest+start, buf, len);
33166 + for (i=start; i < start+len; i++) {
33168 +#ifdef __LITTLE_ENDIAN
33170 +#else /* __BIG_ENDIAN */
33171 + bitpos = (map_bankwidth(map)-1-i)*8;
33173 + orig.x[0] &= ~(0xff << bitpos);
33174 + orig.x[0] |= buf[i] << bitpos;
33180 -static inline void map_write32(struct map_info *map, u32 datum, unsigned long ofs)
33181 +static inline map_word map_word_ff(struct map_info *map)
33183 - __raw_writel(datum, map->virt + ofs);
33188 + for (i=0; i<map_words(map); i++) {
33193 +static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
33197 + if (map_bankwidth_is_1(map))
33198 + r.x[0] = __raw_readb(map->virt + ofs);
33199 + else if (map_bankwidth_is_2(map))
33200 + r.x[0] = __raw_readw(map->virt + ofs);
33201 + else if (map_bankwidth_is_4(map))
33202 + r.x[0] = __raw_readl(map->virt + ofs);
33203 +#if BITS_PER_LONG >= 64
33204 + else if (map_bankwidth_is_8(map))
33205 + r.x[0] = __raw_readq(map->virt + ofs);
33207 + else if (map_bankwidth_is_large(map))
33208 + memcpy_fromio(r.x, map->virt+ofs, map->bankwidth);
33213 -static inline void map_write64(struct map_info *map, u64 datum, unsigned long ofs)
33214 +static inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
33216 -#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */
33219 - __raw_writell(datum, map->virt + ofs);
33220 + if (map_bankwidth_is_1(map))
33221 + __raw_writeb(datum.x[0], map->virt + ofs);
33222 + else if (map_bankwidth_is_2(map))
33223 + __raw_writew(datum.x[0], map->virt + ofs);
33224 + else if (map_bankwidth_is_4(map))
33225 + __raw_writel(datum.x[0], map->virt + ofs);
33226 +#if BITS_PER_LONG >= 64
33227 + else if (map_bankwidth_is_8(map))
33228 + __raw_writeq(datum.x[0], map->virt + ofs);
33230 + else if (map_bankwidth_is_large(map))
33231 + memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
33233 -#endif /* CFI_B8 */
33236 -static inline void map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
33237 +static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
33239 - memcpy_fromio(to, map->virt + from, len);
33241 + memcpy(to, (char *)map->cached + from, len);
33243 + memcpy_fromio(to, map->virt + from, len);
33246 -static inline void map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
33247 +static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
33249 memcpy_toio(map->virt + to, from, len);
33252 -#define simple_map_init(map) do { } while (0)
33253 +#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
33254 +#define map_read(map, ofs) (map)->read(map, ofs)
33255 +#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len)
33256 +#define map_write(map, datum, ofs) (map)->write(map, datum, ofs)
33257 +#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len)
33259 +extern void simple_map_init(struct map_info *);
33260 +#define map_is_linear(map) (map->phys != NO_XIP)
33263 +#define map_read(map, ofs) inline_map_read(map, ofs)
33264 +#define map_copy_from(map, to, from, len) inline_map_copy_from(map, to, from, len)
33265 +#define map_write(map, datum, ofs) inline_map_write(map, datum, ofs)
33266 +#define map_copy_to(map, to, from, len) inline_map_copy_to(map, to, from, len)
33269 +#define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
33270 #define map_is_linear(map) (1)
33272 #endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */
33273 Index: linux-2.6.5/include/linux/mtd/mtd.h
33274 ===================================================================
33275 --- linux-2.6.5.orig/include/linux/mtd/mtd.h 2005-02-01 16:55:50.000000000 -0500
33276 +++ linux-2.6.5/include/linux/mtd/mtd.h 2005-02-01 17:11:17.000000000 -0500
33279 -/* $Id: mtd.h,v 1.45 2003/05/20 21:56:40 dwmw2 Exp $ */
33281 + * $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $
33283 + * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
33285 + * Released under GPL
33288 #ifndef __MTD_MTD_H__
33289 #define __MTD_MTD_H__
33292 +#ifndef __KERNEL__
33293 +#error This is a kernel header. Perhaps include mtd-user.h instead?
33296 #include <linux/config.h>
33297 #include <linux/version.h>
33298 @@ -12,115 +19,27 @@
33299 #include <linux/module.h>
33300 #include <linux/uio.h>
33302 -#endif /* __KERNEL__ */
33304 -struct erase_info_user {
33306 - u_int32_t length;
33309 -struct mtd_oob_buf {
33311 - u_int32_t length;
33312 - unsigned char *ptr;
33314 +#include <linux/mtd/compatmac.h>
33315 +#include <mtd/mtd-abi.h>
33317 #define MTD_CHAR_MAJOR 90
33318 #define MTD_BLOCK_MAJOR 31
33319 #define MAX_MTD_DEVICES 16
33323 -#define MTD_ABSENT 0
33326 -#define MTD_NORFLASH 3
33327 -#define MTD_NANDFLASH 4
33328 -#define MTD_PEROM 5
33329 -#define MTD_OTHER 14
33330 -#define MTD_UNKNOWN 15
33334 -#define MTD_CLEAR_BITS 1 // Bits can be cleared (flash)
33335 -#define MTD_SET_BITS 2 // Bits can be set
33336 -#define MTD_ERASEABLE 4 // Has an erase function
33337 -#define MTD_WRITEB_WRITEABLE 8 // Direct IO is possible
33338 -#define MTD_VOLATILE 16 // Set for RAMs
33339 -#define MTD_XIP 32 // eXecute-In-Place possible
33340 -#define MTD_OOB 64 // Out-of-band data (NAND flash)
33341 -#define MTD_ECC 128 // Device capable of automatic ECC
33343 -// Some common devices / combinations of capabilities
33344 -#define MTD_CAP_ROM 0
33345 -#define MTD_CAP_RAM (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
33346 -#define MTD_CAP_NORFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE)
33347 -#define MTD_CAP_NANDFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE|MTD_OOB)
33348 -#define MTD_WRITEABLE (MTD_CLEAR_BITS|MTD_SET_BITS)
33351 -// Types of automatic ECC/Checksum available
33352 -#define MTD_ECC_NONE 0 // No automatic ECC available
33353 -#define MTD_ECC_RS_DiskOnChip 1 // Automatic ECC on DiskOnChip
33354 -#define MTD_ECC_SW 2 // SW ECC for Toshiba & Samsung devices
33356 -struct mtd_info_user {
33359 - u_int32_t size; // Total size of the MTD
33360 - u_int32_t erasesize;
33361 - u_int32_t oobblock; // Size of OOB blocks (e.g. 512)
33362 - u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
33363 - u_int32_t ecctype;
33364 - u_int32_t eccsize;
33367 -struct region_info_user {
33368 - u_int32_t offset; /* At which this region starts,
33369 - * from the beginning of the MTD */
33370 - u_int32_t erasesize; /* For this region */
33371 - u_int32_t numblocks; /* Number of blocks in this region */
33372 - u_int32_t regionindex;
33375 -#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
33376 -#define MEMERASE _IOW('M', 2, struct erase_info_user)
33377 -#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
33378 -#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
33379 -#define MEMLOCK _IOW('M', 5, struct erase_info_user)
33380 -#define MEMUNLOCK _IOW('M', 6, struct erase_info_user)
33381 -#define MEMGETREGIONCOUNT _IOR('M', 7, int)
33382 -#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user)
33383 -#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo)
33385 -struct nand_oobinfo {
33391 -#ifndef __KERNEL__
33393 -typedef struct mtd_info_user mtd_info_t;
33394 -typedef struct erase_info_user erase_info_t;
33395 -typedef struct region_info_user region_info_t;
33396 -typedef struct nand_oobinfo nand_oobinfo_t;
33398 - /* User-space ioctl definitions */
33400 -#else /* __KERNEL__ */
33403 #define MTD_ERASE_PENDING 0x01
33404 #define MTD_ERASING 0x02
33405 #define MTD_ERASE_SUSPEND 0x04
33406 #define MTD_ERASE_DONE 0x08
33407 #define MTD_ERASE_FAILED 0x10
33409 +/* If the erase fails, fail_addr might indicate exactly which block failed. If
33410 + fail_addr = 0xffffffff, the failure was not at the device level or was not
33411 + specific to any particular block. */
33412 struct erase_info {
33413 struct mtd_info *mtd;
33416 + u_int32_t fail_addr;
33422 u_int32_t oobblock; // Size of OOB blocks (e.g. 512)
33423 u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
33424 + u_int32_t oobavail; // Number of bytes in OOB area available for fs
33428 @@ -200,16 +120,16 @@
33429 /* This function is not yet implemented */
33430 int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
33432 - /* iovec-based read/write methods. We need these especially for NAND flash,
33433 + /* kvec-based read/write methods. We need these especially for NAND flash,
33434 with its limited number of write cycles per erase.
33435 NB: The 'count' parameter is the number of _vectors_, each of
33436 which contains an (ofs, len) tuple.
33438 - int (*readv) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, size_t *retlen);
33439 - int (*readv_ecc) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from,
33440 + int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen);
33441 + int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from,
33442 size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
33443 - int (*writev) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen);
33444 - int (*writev_ecc) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to,
33445 + int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
33446 + int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to,
33447 size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
33450 @@ -222,9 +142,10 @@
33451 /* Power Management functions */
33452 int (*suspend) (struct mtd_info *mtd);
33453 void (*resume) (struct mtd_info *mtd);
33456 - struct semaphore mutex;
33458 + /* Bad block management functions */
33459 + int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
33460 + int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
33464 @@ -253,10 +174,10 @@
33465 extern void register_mtd_user (struct mtd_notifier *new);
33466 extern int unregister_mtd_user (struct mtd_notifier *old);
33468 -int default_mtd_writev(struct mtd_info *mtd, const struct iovec *vecs,
33469 +int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
33470 unsigned long count, loff_t to, size_t *retlen);
33472 -int default_mtd_readv(struct mtd_info *mtd, struct iovec *vecs,
33473 +int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
33474 unsigned long count, loff_t from, size_t *retlen);
33476 #define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
33477 @@ -272,6 +193,17 @@
33478 #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
33479 #define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0)
33482 +#ifdef CONFIG_MTD_PARTITIONS
33483 +void mtd_erase_callback(struct erase_info *instr);
33485 +static inline void mtd_erase_callback(struct erase_info *instr)
33487 + if (instr->callback)
33488 + instr->callback(instr);
33493 * Debugging macro and defines
33495 @@ -291,6 +223,4 @@
33497 #endif /* CONFIG_MTD_DEBUG */
33499 -#endif /* __KERNEL__ */
33501 #endif /* __MTD_MTD_H__ */
33502 Index: linux-2.6.5/include/linux/mtd/nand.h
33503 ===================================================================
33504 --- linux-2.6.5.orig/include/linux/mtd/nand.h 2004-04-03 22:38:14.000000000 -0500
33505 +++ linux-2.6.5/include/linux/mtd/nand.h 2005-02-01 17:11:17.000000000 -0500
33507 * Steven J. Hill <sjhill@realitydiluted.com>
33508 * Thomas Gleixner <tglx@linutronix.de>
33510 - * $Id: nand.h,v 1.25 2003/05/21 15:15:02 dwmw2 Exp $
33511 + * $Id: nand.h,v 1.64 2004/09/16 23:26:08 gleixner Exp $
33513 * This program is free software; you can redistribute it and/or modify
33514 * it under the terms of the GNU General Public License version 2 as
33517 * 11-25-2002 tglx Added Manufacturer code FUJITSU, NATIONAL
33518 * Split manufacturer and device ID structures
33520 + * 02-08-2004 tglx added option field to nand structure for chip anomalities
33521 + * 05-25-2004 tglx added bad block table support, ST-MICRO manufacturer id
33522 + * update of nand_chip structure description
33524 #ifndef __LINUX_MTD_NAND_H
33525 #define __LINUX_MTD_NAND_H
33526 @@ -51,22 +55,46 @@
33527 #include <linux/config.h>
33528 #include <linux/wait.h>
33529 #include <linux/spinlock.h>
33530 +#include <linux/mtd/mtd.h>
33534 - * Searches for a NAND device
33535 +/* Scan and identify a NAND device */
33536 +extern int nand_scan (struct mtd_info *mtd, int max_chips);
33537 +/* Free resources held by the NAND device */
33538 +extern void nand_release (struct mtd_info *mtd);
33540 +/* Read raw data from the device without ECC */
33541 +extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
33544 +/* The maximum number of NAND chips in an array */
33545 +#define NAND_MAX_CHIPS 8
33547 +/* This constant declares the max. oobsize / page, which
33548 + * is supported now. If you add a chip with bigger oobsize/page
33549 + * adjust this accordingly.
33551 -extern int nand_scan (struct mtd_info *mtd);
33552 +#define NAND_MAX_OOBSIZE 64
33555 * Constants for hardware specific CLE/ALE/NCE function
33557 +/* Select the chip by setting nCE to low */
33558 #define NAND_CTL_SETNCE 1
33559 +/* Deselect the chip by setting nCE to high */
33560 #define NAND_CTL_CLRNCE 2
33561 +/* Select the command latch by setting CLE to high */
33562 #define NAND_CTL_SETCLE 3
33563 +/* Deselect the command latch by setting CLE to low */
33564 #define NAND_CTL_CLRCLE 4
33565 +/* Select the address latch by setting ALE to high */
33566 #define NAND_CTL_SETALE 5
33567 +/* Deselect the address latch by setting ALE to low */
33568 #define NAND_CTL_CLRALE 6
33569 +/* Set write protection by setting WP to high. Not used! */
33570 +#define NAND_CTL_SETWP 7
33571 +/* Clear write protection by setting WP to low. Not used! */
33572 +#define NAND_CTL_CLRWP 8
33575 * Standard NAND flash commands
33576 @@ -77,35 +105,102 @@
33577 #define NAND_CMD_READOOB 0x50
33578 #define NAND_CMD_ERASE1 0x60
33579 #define NAND_CMD_STATUS 0x70
33580 +#define NAND_CMD_STATUS_MULTI 0x71
33581 #define NAND_CMD_SEQIN 0x80
33582 #define NAND_CMD_READID 0x90
33583 #define NAND_CMD_ERASE2 0xd0
33584 #define NAND_CMD_RESET 0xff
33586 +/* Extended commands for large page devices */
33587 +#define NAND_CMD_READSTART 0x30
33588 +#define NAND_CMD_CACHEDPROG 0x15
33591 +#define NAND_STATUS_FAIL 0x01
33592 +#define NAND_STATUS_FAIL_N1 0x02
33593 +#define NAND_STATUS_TRUE_READY 0x20
33594 +#define NAND_STATUS_READY 0x40
33595 +#define NAND_STATUS_WP 0x80
33598 * Constants for ECC_MODES
33601 - * SOFT: Software ECC 3 byte ECC per 256 Byte data
33602 - * HW3_256: Hardware ECC 3 byte ECC per 256 Byte data
33603 - * HW3_512: Hardware ECC 3 byte ECC per 512 Byte data
33609 +/* No ECC. Usage is not recommended ! */
33610 #define NAND_ECC_NONE 0
33611 +/* Software ECC 3 byte ECC per 256 Byte data */
33612 #define NAND_ECC_SOFT 1
33613 +/* Hardware ECC 3 byte ECC per 256 Byte data */
33614 #define NAND_ECC_HW3_256 2
33615 +/* Hardware ECC 3 byte ECC per 512 Byte data */
33616 #define NAND_ECC_HW3_512 3
33617 +/* Hardware ECC 3 byte ECC per 512 Byte data */
33618 #define NAND_ECC_HW6_512 4
33619 -#define NAND_ECC_DISKONCHIP 5
33620 +/* Hardware ECC 8 byte ECC per 512 Byte data */
33621 +#define NAND_ECC_HW8_512 6
33624 * Constants for Hardware ECC
33626 +/* Reset Hardware ECC for read */
33627 #define NAND_ECC_READ 0
33628 +/* Reset Hardware ECC for write */
33629 #define NAND_ECC_WRITE 1
33631 +/* Enable Hardware ECC before syndrom is read back from flash */
33632 +#define NAND_ECC_READSYN 2
33634 +/* Option constants for bizarre disfunctionality and real
33637 +/* Chip can not auto increment pages */
33638 +#define NAND_NO_AUTOINCR 0x00000001
33639 +/* Buswitdh is 16 bit */
33640 +#define NAND_BUSWIDTH_16 0x00000002
33641 +/* Device supports partial programming without padding */
33642 +#define NAND_NO_PADDING 0x00000004
33643 +/* Chip has cache program function */
33644 +#define NAND_CACHEPRG 0x00000008
33645 +/* Chip has copy back function */
33646 +#define NAND_COPYBACK 0x00000010
33647 +/* AND Chip which has 4 banks and a confusing page / block
33648 + * assignment. See Renesas datasheet for further information */
33649 +#define NAND_IS_AND 0x00000020
33650 +/* Chip has a array of 4 pages which can be read without
33651 + * additional ready /busy waits */
33652 +#define NAND_4PAGE_ARRAY 0x00000040
33654 +/* Options valid for Samsung large page devices */
33655 +#define NAND_SAMSUNG_LP_OPTIONS \
33656 + (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
33658 +/* Macros to identify the above */
33659 +#define NAND_CANAUTOINCR(chip) (!(chip->options & NAND_NO_AUTOINCR))
33660 +#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
33661 +#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
33662 +#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
33664 +/* Mask to zero out the chip options, which come from the id table */
33665 +#define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR)
33667 +/* Non chip related options */
33668 +/* Use a flash based bad block table. This option is passed to the
33669 + * default bad block table function. */
33670 +#define NAND_USE_FLASH_BBT 0x00010000
33671 +/* The hw ecc generator provides a syndrome instead a ecc value on read
33672 + * This can only work if we have the ecc bytes directly behind the
33673 + * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
33674 +#define NAND_HWECC_SYNDROME 0x00020000
33677 +/* Options set by nand scan */
33678 +/* Nand scan has allocated oob_buf */
33679 +#define NAND_OOBBUF_ALLOC 0x40000000
33680 +/* Nand scan has allocated data_buf */
33681 +#define NAND_DATABUF_ALLOC 0x80000000
33685 + * nand_state_t - chip states
33686 * Enumeration for NAND flash chip state
33689 @@ -113,71 +208,116 @@
33700 - * NAND Private Flash Chip Data
33702 - * Structure overview:
33704 - * IO_ADDR_R - address to read the 8 I/O lines of the flash device
33706 - * IO_ADDR_W - address to write the 8 I/O lines of the flash device
33708 - * hwcontrol - hardwarespecific function for accesing control-lines
33710 - * dev_ready - hardwarespecific function for accesing device ready/busy line
33712 - * waitfunc - hardwarespecific function for wait on ready
33714 - * calculate_ecc - function for ecc calculation or readback from ecc hardware
33716 - * correct_data - function for ecc correction, matching to ecc generator (sw/hw)
33718 - * enable_hwecc - function to enable (reset) hardware ecc generator
33720 - * eccmod - mode of ecc: see constants
33722 - * eccsize - databytes used per ecc-calculation
33724 - * chip_delay - chip dependent delay for transfering data from array to read regs (tR)
33726 - * chip_lock - spinlock used to protect access to this structure
33728 - * wq - wait queue to sleep on if a NAND operation is in progress
33730 - * state - give the current state of the NAND device
33732 - * page_shift - number of address bits in a page (column address bits)
33734 - * data_buf - data buffer passed to/from MTD user modules
33736 - * data_cache - data cache for redundant page access and shadow for
33739 - * cache_page - number of last valid page in page_cache
33741 + * struct nand_chip - NAND Private Flash Chip Data
33742 + * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
33743 + * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
33744 + * @read_byte: [REPLACEABLE] read one byte from the chip
33745 + * @write_byte: [REPLACEABLE] write one byte to the chip
33746 + * @read_word: [REPLACEABLE] read one word from the chip
33747 + * @write_word: [REPLACEABLE] write one word to the chip
33748 + * @write_buf: [REPLACEABLE] write data from the buffer to the chip
33749 + * @read_buf: [REPLACEABLE] read data from the chip into the buffer
33750 + * @verify_buf: [REPLACEABLE] verify buffer contents against the chip data
33751 + * @select_chip: [REPLACEABLE] select chip nr
33752 + * @block_bad: [REPLACEABLE] check, if the block is bad
33753 + * @block_markbad: [REPLACEABLE] mark the block bad
33754 + * @hwcontrol: [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
33755 + * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
33756 + * If set to NULL no access to ready/busy is available and the ready/busy information
33757 + * is read from the chip status register
33758 + * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip
33759 + * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready
33760 + * @calculate_ecc: [REPLACEABLE] function for ecc calculation or readback from ecc hardware
33761 + * @correct_data: [REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
33762 + * @enable_hwecc: [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
33763 + * be provided if a hardware ECC is available
33764 + * @erase_cmd: [INTERN] erase command write function, selectable due to AND support
33765 + * @scan_bbt: [REPLACEABLE] function to scan bad block table
33766 + * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines
33767 + * @eccsize: [INTERN] databytes used per ecc-calculation
33768 + * @eccsteps: [INTERN] number of ecc calculation steps per page
33769 + * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
33770 + * @chip_lock: [INTERN] spinlock used to protect access to this structure and the chip
33771 + * @wq: [INTERN] wait queue to sleep on if a NAND operation is in progress
33772 + * @state: [INTERN] the current state of the NAND device
33773 + * @page_shift: [INTERN] number of address bits in a page (column address bits)
33774 + * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock
33775 + * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry
33776 + * @chip_shift: [INTERN] number of address bits in one chip
33777 + * @data_buf: [INTERN] internal buffer for one page + oob
33778 + * @oob_buf: [INTERN] oob buffer for one eraseblock
33779 + * @oobdirty: [INTERN] indicates that oob_buf must be reinitialized
33780 + * @data_poi: [INTERN] pointer to a data buffer
33781 + * @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
33782 + * special functionality. See the defines for further explanation
33783 + * @badblockpos: [INTERN] position of the bad block marker in the oob area
33784 + * @numchips: [INTERN] number of physical chips
33785 + * @chipsize: [INTERN] the size of one chip for multichip arrays
33786 + * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
33787 + * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf
33788 + * @autooob: [REPLACEABLE] the default (auto)placement scheme
33789 + * @bbt: [INTERN] bad block table pointer
33790 + * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup
33791 + * @bbt_md: [REPLACEABLE] bad block table mirror descriptor
33792 + * @priv: [OPTIONAL] pointer to private chip date
33796 - unsigned long IO_ADDR_R;
33797 - unsigned long IO_ADDR_W;
33798 - void (*hwcontrol)(int cmd);
33799 - int (*dev_ready)(void);
33800 + void __iomem *IO_ADDR_R;
33801 + void __iomem *IO_ADDR_W;
33803 + u_char (*read_byte)(struct mtd_info *mtd);
33804 + void (*write_byte)(struct mtd_info *mtd, u_char byte);
33805 + u16 (*read_word)(struct mtd_info *mtd);
33806 + void (*write_word)(struct mtd_info *mtd, u16 word);
33808 + void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
33809 + void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
33810 + int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
33811 + void (*select_chip)(struct mtd_info *mtd, int chip);
33812 + int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
33813 + int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
33814 + void (*hwcontrol)(struct mtd_info *mtd, int cmd);
33815 + int (*dev_ready)(struct mtd_info *mtd);
33816 void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
33817 int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
33818 - void (*calculate_ecc)(const u_char *dat, u_char *ecc_code);
33819 - int (*correct_data)(u_char *dat, u_char *read_ecc, u_char *calc_ecc);
33820 - void (*enable_hwecc)(int mode);
33821 + int (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
33822 + int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
33823 + void (*enable_hwecc)(struct mtd_info *mtd, int mode);
33824 + void (*erase_cmd)(struct mtd_info *mtd, int page);
33825 + int (*scan_bbt)(struct mtd_info *mtd);
33830 - spinlock_t chip_lock;
33831 + spinlock_t chip_lock;
33832 wait_queue_head_t wq;
33833 nand_state_t state;
33835 + int phys_erase_shift;
33836 + int bbt_erase_shift;
33842 + unsigned int options;
33845 + unsigned long chipsize;
33848 + struct nand_oobinfo *autooob;
33850 + struct nand_bbt_descr *bbt_td;
33851 + struct nand_bbt_descr *bbt_md;
33856 @@ -187,46 +327,35 @@
33857 #define NAND_MFR_SAMSUNG 0xec
33858 #define NAND_MFR_FUJITSU 0x04
33859 #define NAND_MFR_NATIONAL 0x8f
33860 +#define NAND_MFR_RENESAS 0x07
33861 +#define NAND_MFR_STMICRO 0x20
33864 - * NAND Flash Device ID Structure
33866 - * Structure overview:
33868 + * struct nand_flash_dev - NAND Flash Device ID Structure
33870 - * name - Identify the device type
33872 - * id - device ID code
33874 - * chipshift - total number of address bits for the device which
33875 - * is used to calculate address offsets and the total
33876 - * number of bytes the device is capable of.
33878 - * page256 - denotes if flash device has 256 byte pages or not.
33880 - * pageadrlen - number of bytes minus one needed to hold the
33881 - * complete address into the flash array. Keep in
33882 - * mind that when a read or write is done to a
33883 - * specific address, the address is input serially
33884 - * 8 bits at a time. This structure member is used
33885 - * by the read/write routines as a loop index for
33886 - * shifting the address out 8 bits at a time.
33888 - * erasesize - size of an erase block in the flash device.
33889 + * @name: Identify the device type
33890 + * @id: device ID code
33891 + * @pagesize: Pagesize in bytes. Either 256 or 512 or 0
33892 + * If the pagesize is 0, then the real pagesize
33893 + * and the eraseize are determined from the
33894 + * extended id bytes in the chip
33895 + * @erasesize: Size of an erase block in the flash device.
33896 + * @chipsize: Total chipsize in Mega Bytes
33897 + * @options: Bitfield to store chip relevant options
33899 struct nand_flash_dev {
33904 + unsigned long pagesize;
33905 + unsigned long chipsize;
33906 unsigned long erasesize;
33908 + unsigned long options;
33912 - * NAND Flash Manufacturer ID Structure
33914 - * name - Manufacturer name
33916 - * id - manufacturer ID code of device.
33918 + * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
33919 + * @name: Manufacturer name
33920 + * @id: manufacturer ID code of device.
33922 struct nand_manufacturers {
33924 @@ -236,9 +365,85 @@
33925 extern struct nand_flash_dev nand_flash_ids[];
33926 extern struct nand_manufacturers nand_manuf_ids[];
33929 + * struct nand_bbt_descr - bad block table descriptor
33930 + * @options: options for this descriptor
33931 + * @pages: the page(s) where we find the bbt, used with option BBT_ABSPAGE
33932 + * when bbt is searched, then we store the found bbts pages here.
33933 + * Its an array and supports up to 8 chips now
33934 + * @offs: offset of the pattern in the oob area of the page
33935 + * @veroffs: offset of the bbt version counter in the oob are of the page
33936 + * @version: version read from the bbt page during scan
33937 + * @len: length of the pattern, if 0 no pattern check is performed
33938 + * @maxblocks: maximum number of blocks to search for a bbt. This number of
33939 + * blocks is reserved at the end of the device where the tables are
33941 + * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
33942 + * bad) block in the stored bbt
33943 + * @pattern: pattern to identify bad block table or factory marked good /
33944 + * bad blocks, can be NULL, if len = 0
33946 + * Descriptor for the bad block table marker and the descriptor for the
33947 + * pattern which identifies good and bad blocks. The assumption is made
33948 + * that the pattern and the version count are always located in the oob area
33949 + * of the first block.
33951 +struct nand_bbt_descr {
33953 + int pages[NAND_MAX_CHIPS];
33956 + uint8_t version[NAND_MAX_CHIPS];
33959 + int reserved_block_code;
33960 + uint8_t *pattern;
33963 +/* Options for the bad block table descriptors */
33965 +/* The number of bits used per block in the bbt on the device */
33966 +#define NAND_BBT_NRBITS_MSK 0x0000000F
33967 +#define NAND_BBT_1BIT 0x00000001
33968 +#define NAND_BBT_2BIT 0x00000002
33969 +#define NAND_BBT_4BIT 0x00000004
33970 +#define NAND_BBT_8BIT 0x00000008
33971 +/* The bad block table is in the last good block of the device */
33972 +#define NAND_BBT_LASTBLOCK 0x00000010
33973 +/* The bbt is at the given page, else we must scan for the bbt */
33974 +#define NAND_BBT_ABSPAGE 0x00000020
33975 +/* The bbt is at the given page, else we must scan for the bbt */
33976 +#define NAND_BBT_SEARCH 0x00000040
33977 +/* bbt is stored per chip on multichip devices */
33978 +#define NAND_BBT_PERCHIP 0x00000080
33979 +/* bbt has a version counter at offset veroffs */
33980 +#define NAND_BBT_VERSION 0x00000100
33981 +/* Create a bbt if none axists */
33982 +#define NAND_BBT_CREATE 0x00000200
33983 +/* Search good / bad pattern through all pages of a block */
33984 +#define NAND_BBT_SCANALLPAGES 0x00000400
33985 +/* Scan block empty during good / bad block scan */
33986 +#define NAND_BBT_SCANEMPTY 0x00000800
33987 +/* Write bbt if neccecary */
33988 +#define NAND_BBT_WRITE 0x00001000
33989 +/* Read and write back block contents when writing bbt */
33990 +#define NAND_BBT_SAVECONTENT 0x00002000
33991 +/* Search good / bad pattern on the first and the second page */
33992 +#define NAND_BBT_SCAN2NDPAGE 0x00004000
33994 +/* The maximum number of blocks to scan for a bbt */
33995 +#define NAND_BBT_SCAN_MAXBLOCKS 4
33997 +extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
33998 +extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs);
33999 +extern int nand_default_bbt (struct mtd_info *mtd);
34000 +extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);
34001 +extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
34004 * Constants for oob configuration
34006 -#define NAND_BADBLOCK_POS 5
34007 +#define NAND_SMALL_BADBLOCK_POS 5
34008 +#define NAND_LARGE_BADBLOCK_POS 0
34010 #endif /* __LINUX_MTD_NAND_H */
34011 Index: linux-2.6.5/include/linux/mtd/nand_ecc.h
34012 ===================================================================
34013 --- linux-2.6.5.orig/include/linux/mtd/nand_ecc.h 2004-04-03 22:37:07.000000000 -0500
34014 +++ linux-2.6.5/include/linux/mtd/nand_ecc.h 2005-02-01 17:11:17.000000000 -0500
34017 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
34019 - * $Id: nand_ecc.h,v 1.2 2003/02/20 13:34:20 sjhill Exp $
34020 + * $Id: nand_ecc.h,v 1.4 2004/06/17 02:35:02 dbrown Exp $
34022 * This program is free software; you can redistribute it and/or modify
34023 * it under the terms of the GNU General Public License version 2 as
34024 @@ -12,17 +12,19 @@
34025 * This file is the header for the ECC algorithm.
34029 - * Creates non-inverted ECC code from line parity
34031 -void nand_trans_result(u_char reg2, u_char reg3, u_char *ecc_code);
34032 +#ifndef __MTD_NAND_ECC_H__
34033 +#define __MTD_NAND_ECC_H__
34038 * Calculate 3 byte ECC code for 256 byte block
34040 -void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
34041 +int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
34044 * Detect and correct a 1 bit error for 256 byte block
34046 -int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
34047 +int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
34049 +#endif /* __MTD_NAND_ECC_H__ */
34050 Index: linux-2.6.5/include/linux/mtd/nftl.h
34051 ===================================================================
34052 --- linux-2.6.5.orig/include/linux/mtd/nftl.h 2004-04-03 22:37:43.000000000 -0500
34053 +++ linux-2.6.5/include/linux/mtd/nftl.h 2005-02-01 17:11:17.000000000 -0500
34056 - * $Id: nftl.h,v 1.13 2003/05/23 11:25:02 dwmw2 Exp $
34057 + * $Id: nftl.h,v 1.16 2004/06/30 14:49:00 dbrown Exp $
34059 * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
34062 #include <linux/mtd/mtd.h>
34063 #include <linux/mtd/blktrans.h>
34065 -/* Block Control Information */
34068 - unsigned char ECCSig[6];
34071 -}__attribute__((packed));
34073 -/* Unit Control Information */
34075 -struct nftl_uci0 {
34076 - __u16 VirtUnitNum;
34077 - __u16 ReplUnitNum;
34078 - __u16 SpareVirtUnitNum;
34079 - __u16 SpareReplUnitNum;
34080 -} __attribute__((packed));
34082 -struct nftl_uci1 {
34085 - __u16 EraseMark1;
34086 -} __attribute__((packed));
34088 -struct nftl_uci2 {
34092 -} __attribute__((packed));
34095 - struct nftl_uci0 a;
34096 - struct nftl_uci1 b;
34097 - struct nftl_uci2 c;
34101 - struct nftl_bci b;
34102 - union nftl_uci u;
34105 -/* NFTL Media Header */
34107 -struct NFTLMediaHeader {
34108 - char DataOrgID[6];
34109 - __u16 NumEraseUnits;
34110 - __u16 FirstPhysicalEUN;
34111 - __u32 FormattedSize;
34112 - unsigned char UnitSizeFactor;
34113 -} __attribute__((packed));
34115 -#define MAX_ERASE_ZONES (8192 - 512)
34117 -#define ERASE_MARK 0x3c69
34118 -#define SECTOR_FREE 0xff
34119 -#define SECTOR_USED 0x55
34120 -#define SECTOR_IGNORE 0x11
34121 -#define SECTOR_DELETED 0x00
34123 -#define FOLD_MARK_IN_PROGRESS 0x5555
34125 -#define ZONE_GOOD 0xff
34126 -#define ZONE_BAD_ORIGINAL 0
34127 -#define ZONE_BAD_MARKED 7
34130 +#include <mtd/nftl-user.h>
34132 /* these info are used in ReplUnitTable */
34133 #define BLOCK_NIL 0xffff /* last block of a chain */
34135 unsigned int nb_blocks; /* number of physical blocks */
34136 unsigned int nb_boot_blocks; /* number of blocks used by the bios */
34137 struct erase_info instr;
34138 + struct nand_oobinfo oobinfo;
34141 int NFTL_mount(struct NFTLrecord *s);
34143 #define MAX_SECTORS_PER_UNIT 64
34144 #define NFTL_PARTN_BITS 4
34146 -#endif /* __KERNEL__ */
34148 #endif /* __MTD_NFTL_H__ */
34149 Index: linux-2.6.5/include/linux/mtd/partitions.h
34150 ===================================================================
34151 --- linux-2.6.5.orig/include/linux/mtd/partitions.h 2004-04-03 22:38:16.000000000 -0500
34152 +++ linux-2.6.5/include/linux/mtd/partitions.h 2005-02-01 17:11:17.000000000 -0500
34157 - * $Id: partitions.h,v 1.14 2003/05/20 21:56:29 dwmw2 Exp $
34158 + * $Id: partitions.h,v 1.15 2003/07/09 11:15:43 dwmw2 Exp $
34161 #ifndef MTD_PARTITIONS_H
34163 #define MTDPART_SIZ_FULL (0)
34166 -int add_mtd_partitions(struct mtd_info *, struct mtd_partition *, int);
34167 +int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
34168 int del_mtd_partitions(struct mtd_info *);
34171 Index: linux-2.6.5/include/linux/mtd/physmap.h
34172 ===================================================================
34173 --- linux-2.6.5.orig/include/linux/mtd/physmap.h 1969-12-31 19:00:00.000000000 -0500
34174 +++ linux-2.6.5/include/linux/mtd/physmap.h 2005-02-01 17:11:17.000000000 -0500
34177 + * For boards with physically mapped flash and using
34178 + * drivers/mtd/maps/physmap.c mapping driver.
34180 + * $Id: physmap.h,v 1.3 2004/07/21 00:16:15 jwboyer Exp $
34182 + * Copyright (C) 2003 MontaVista Software Inc.
34183 + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
34185 + * This program is free software; you can redistribute it and/or modify it
34186 + * under the terms of the GNU General Public License as published by the
34187 + * Free Software Foundation; either version 2 of the License, or (at your
34188 + * option) any later version.
34192 +#ifndef __LINUX_MTD_PHYSMAP__
34194 +#include <linux/config.h>
34196 +#if defined(CONFIG_MTD_PHYSMAP)
34198 +#include <linux/mtd/mtd.h>
34199 +#include <linux/mtd/map.h>
34200 +#include <linux/mtd/partitions.h>
34203 + * The map_info for physmap. Board can override size, buswidth, phys,
34204 + * (*set_vpp)(), etc in their initial setup routine.
34206 +extern struct map_info physmap_map;
34209 + * Board needs to specify the exact mapping during their setup time.
34211 +static inline void physmap_configure(unsigned long addr, unsigned long size, int bankwidth, void (*set_vpp)(struct map_info *, int) )
34213 + physmap_map.phys = addr;
34214 + physmap_map.size = size;
34215 + physmap_map.bankwidth = bankwidth;
34216 + physmap_map.set_vpp = set_vpp;
34219 +#if defined(CONFIG_MTD_PARTITIONS)
34222 + * Machines that wish to do flash partition may want to call this function in
34223 + * their setup routine.
34225 + * physmap_set_partitions(mypartitions, num_parts);
34227 + * Note that one can always override this hard-coded partition with
34228 + * command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS).
34230 +void physmap_set_partitions(struct mtd_partition *parts, int num_parts);
34232 +#endif /* defined(CONFIG_MTD_PARTITIONS) */
34233 +#endif /* defined(CONFIG_MTD) */
34235 +#endif /* __LINUX_MTD_PHYSMAP__ */
34237 Index: linux-2.6.5/include/linux/rslib.h
34238 ===================================================================
34239 --- linux-2.6.5.orig/include/linux/rslib.h 1969-12-31 19:00:00.000000000 -0500
34240 +++ linux-2.6.5/include/linux/rslib.h 2005-02-01 17:11:17.000000000 -0500
34243 + * include/linux/rslib.h
34246 + * Generic Reed Solomon encoder / decoder library
34248 + * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
34250 + * RS code lifted from reed solomon library written by Phil Karn
34251 + * Copyright 2002 Phil Karn, KA9Q
34253 + * $Id: rslib.h,v 1.1 2004/09/16 23:58:55 gleixner Exp $
34255 + * This program is free software; you can redistribute it and/or modify
34256 + * it under the terms of the GNU General Public License version 2 as
34257 + * published by the Free Software Foundation.
34263 +#include <linux/list.h>
34266 + * struct rs_contol - rs control structure
34268 + * @mm: Bits per symbol
34269 + * @nn: Symbols per block (= (1<<mm)-1)
34270 + * @alpha_to: log lookup table
34271 + * @index_of: Antilog lookup table
34272 + * @genpoly: Generator polynomial
34273 + * @nroots: Number of generator roots = number of parity symbols
34274 + * @fcr: First consecutive root, index form
34275 + * @prim: Primitive element, index form
34276 + * @iprim: prim-th root of 1, index form
34277 + * @gfpoly: The primitive generator polynominal
34278 + * @users: Users of this structure
34279 + * @list: List entry for the rs control list
34281 +struct rs_control {
34284 + uint16_t *alpha_to;
34285 + uint16_t *index_of;
34286 + uint16_t *genpoly;
34293 + struct list_head list;
34296 +/* General purpose RS codec, 8-bit data width, symbol width 1-15 bit */
34297 +int encode_rs8 (struct rs_control *rs, uint8_t *data, int len, uint16_t *par, uint16_t invmsk);
34298 +int decode_rs8 (struct rs_control *rs, uint8_t *data, uint16_t *par,
34299 + int len, uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk);
34301 +/* General purpose RS codec, 16-bit data width, symbol width 1-15 bit */
34302 +int encode_rs16 (struct rs_control *rs, uint16_t *data, int len, uint16_t *par, uint16_t invmsk);
34303 +int decode_rs16 (struct rs_control *rs, uint16_t *data, uint16_t *par,
34304 + int len, uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk);
34306 +/* General purpose RS codec, 32-bit data width, symbol width 1-15 bit */
34307 +int encode_rs32 (struct rs_control *rs, uint32_t *data, int len, uint16_t *par, uint16_t invmsk);
34308 +int decode_rs32 (struct rs_control *rs, uint32_t *data, uint16_t *par,
34309 + int len, uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk);
34311 +/* Create or get a matching rs control structure */
34312 +struct rs_control *init_rs (int symsize, int gfpoly, int fcr, int prim, int nroots);
34314 +/* Release a rs control structure */
34315 +void free_rs (struct rs_control *rs);
34317 +/* Internal usage only */
34318 +static inline int modnn (struct rs_control *rs, int x)
34320 + while (x >= rs->nn) {
34322 + x = (x >> rs->mm) + (x & rs->nn);
34327 +#define MODNN(x) modnn(rs,x)
34328 +#define MM (rs->mm)
34329 +#define NN (rs->nn)
34330 +#define ALPHA_TO (rs->alpha_to)
34331 +#define INDEX_OF (rs->index_of)
34332 +#define GENPOLY (rs->genpoly)
34333 +#define NROOTS (rs->nroots)
34334 +#define FCR (rs->fcr)
34335 +#define PRIM (rs->prim)
34336 +#define IPRIM (rs->iprim)
34341 Index: linux-2.6.5/include/mtd/inftl-user.h
34342 ===================================================================
34343 --- linux-2.6.5.orig/include/mtd/inftl-user.h 1969-12-31 19:00:00.000000000 -0500
34344 +++ linux-2.6.5/include/mtd/inftl-user.h 2005-02-01 17:11:17.000000000 -0500
34347 + * $Id: inftl-user.h,v 1.1 2004/05/05 15:17:00 dwmw2 Exp $
34349 + * Parts of INFTL headers shared with userspace
34353 +#ifndef __MTD_INFTL_USER_H__
34354 +#define __MTD_INFTL_USER_H__
34356 +#define OSAK_VERSION 0x5120
34357 +#define PERCENTUSED 98
34359 +#define SECTORSIZE 512
34361 +/* Block Control Information */
34363 +struct inftl_bci {
34364 + uint8_t ECCsig[6];
34367 +} __attribute__((packed));
34369 +struct inftl_unithead1 {
34370 + uint16_t virtualUnitNo;
34371 + uint16_t prevUnitNo;
34374 + uint8_t parityPerField;
34375 + uint8_t discarded;
34376 +} __attribute__((packed));
34378 +struct inftl_unithead2 {
34379 + uint8_t parityPerField;
34381 + uint16_t prevUnitNo;
34382 + uint16_t virtualUnitNo;
34384 + uint8_t discarded;
34385 +} __attribute__((packed));
34387 +struct inftl_unittail {
34388 + uint8_t Reserved[4];
34389 + uint16_t EraseMark;
34390 + uint16_t EraseMark1;
34391 +} __attribute__((packed));
34394 + struct inftl_unithead1 a;
34395 + struct inftl_unithead2 b;
34396 + struct inftl_unittail c;
34399 +struct inftl_oob {
34400 + struct inftl_bci b;
34401 + union inftl_uci u;
34405 +/* INFTL Media Header */
34407 +struct INFTLPartition {
34408 + __u32 virtualUnits;
34412 + __u32 spareUnits;
34415 +} __attribute__((packed));
34417 +struct INFTLMediaHeader {
34418 + char bootRecordID[8];
34419 + __u32 NoOfBootImageBlocks;
34420 + __u32 NoOfBinaryPartitions;
34421 + __u32 NoOfBDTLPartitions;
34422 + __u32 BlockMultiplierBits;
34423 + __u32 FormatFlags;
34424 + __u32 OsakVersion;
34425 + __u32 PercentUsed;
34426 + struct INFTLPartition Partitions[4];
34427 +} __attribute__((packed));
34429 +/* Partition flag types */
34430 +#define INFTL_BINARY 0x20000000
34431 +#define INFTL_BDTL 0x40000000
34432 +#define INFTL_LAST 0x80000000
34434 +#endif /* __MTD_INFTL_USER_H__ */
34437 Index: linux-2.6.5/include/mtd/jffs2-user.h
34438 ===================================================================
34439 --- linux-2.6.5.orig/include/mtd/jffs2-user.h 1969-12-31 19:00:00.000000000 -0500
34440 +++ linux-2.6.5/include/mtd/jffs2-user.h 2005-02-01 17:11:17.000000000 -0500
34443 + * $Id: jffs2-user.h,v 1.1 2004/05/05 11:57:54 dwmw2 Exp $
34445 + * JFFS2 definitions for use in user space only
34448 +#ifndef __JFFS2_USER_H__
34449 +#define __JFFS2_USER_H__
34451 +/* This file is blessed for inclusion by userspace */
34452 +#include <linux/jffs2.h>
34453 +#include <endian.h>
34454 +#include <byteswap.h>
34456 +#undef cpu_to_je16
34457 +#undef cpu_to_je32
34458 +#undef cpu_to_jemode
34459 +#undef je16_to_cpu
34460 +#undef je32_to_cpu
34461 +#undef jemode_to_cpu
34463 +extern int target_endian;
34465 +#define t16(x) ({ uint16_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_16(__b); })
34466 +#define t32(x) ({ uint32_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_32(__b); })
34468 +#define cpu_to_je16(x) ((jint16_t){t16(x)})
34469 +#define cpu_to_je32(x) ((jint32_t){t32(x)})
34470 +#define cpu_to_jemode(x) ((jmode_t){t32(x)})
34472 +#define je16_to_cpu(x) (t16((x).v16))
34473 +#define je32_to_cpu(x) (t32((x).v32))
34474 +#define jemode_to_cpu(x) (t32((x).m))
34476 +#endif /* __JFFS2_USER_H__ */
34477 Index: linux-2.6.5/include/mtd/mtd-abi.h
34478 ===================================================================
34479 --- linux-2.6.5.orig/include/mtd/mtd-abi.h 1969-12-31 19:00:00.000000000 -0500
34480 +++ linux-2.6.5/include/mtd/mtd-abi.h 2005-02-01 17:11:17.000000000 -0500
34483 + * $Id: mtd-abi.h,v 1.6 2004/08/09 13:38:30 dwmw2 Exp $
34485 + * Portions of MTD ABI definition which are shared by kernel and user space
34488 +#ifndef __MTD_ABI_H__
34489 +#define __MTD_ABI_H__
34491 +#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into
34492 + separate files was to avoid #ifdef __KERNEL__ */
34496 +struct erase_info_user {
34501 +struct mtd_oob_buf {
34504 + unsigned char __user *ptr;
34507 +#define MTD_ABSENT 0
34510 +#define MTD_NORFLASH 3
34511 +#define MTD_NANDFLASH 4
34512 +#define MTD_PEROM 5
34513 +#define MTD_OTHER 14
34514 +#define MTD_UNKNOWN 15
34516 +#define MTD_CLEAR_BITS 1 // Bits can be cleared (flash)
34517 +#define MTD_SET_BITS 2 // Bits can be set
34518 +#define MTD_ERASEABLE 4 // Has an erase function
34519 +#define MTD_WRITEB_WRITEABLE 8 // Direct IO is possible
34520 +#define MTD_VOLATILE 16 // Set for RAMs
34521 +#define MTD_XIP 32 // eXecute-In-Place possible
34522 +#define MTD_OOB 64 // Out-of-band data (NAND flash)
34523 +#define MTD_ECC 128 // Device capable of automatic ECC
34525 +// Some common devices / combinations of capabilities
34526 +#define MTD_CAP_ROM 0
34527 +#define MTD_CAP_RAM (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
34528 +#define MTD_CAP_NORFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE)
34529 +#define MTD_CAP_NANDFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE|MTD_OOB)
34530 +#define MTD_WRITEABLE (MTD_CLEAR_BITS|MTD_SET_BITS)
34533 +// Types of automatic ECC/Checksum available
34534 +#define MTD_ECC_NONE 0 // No automatic ECC available
34535 +#define MTD_ECC_RS_DiskOnChip 1 // Automatic ECC on DiskOnChip
34536 +#define MTD_ECC_SW 2 // SW ECC for Toshiba & Samsung devices
34538 +/* ECC byte placement */
34539 +#define MTD_NANDECC_OFF 0 // Switch off ECC (Not recommended)
34540 +#define MTD_NANDECC_PLACE 1 // Use the given placement in the structure (YAFFS1 legacy mode)
34541 +#define MTD_NANDECC_AUTOPLACE 2 // Use the default placement scheme
34542 +#define MTD_NANDECC_PLACEONLY 3 // Use the given placement in the structure (Do not store ecc result on read)
34544 +struct mtd_info_user {
34547 + uint32_t size; // Total size of the MTD
34548 + uint32_t erasesize;
34549 + uint32_t oobblock; // Size of OOB blocks (e.g. 512)
34550 + uint32_t oobsize; // Amount of OOB data per block (e.g. 16)
34551 + uint32_t ecctype;
34552 + uint32_t eccsize;
34555 +struct region_info_user {
34556 + uint32_t offset; /* At which this region starts,
34557 + * from the beginning of the MTD */
34558 + uint32_t erasesize; /* For this region */
34559 + uint32_t numblocks; /* Number of blocks in this region */
34560 + uint32_t regionindex;
34563 +#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
34564 +#define MEMERASE _IOW('M', 2, struct erase_info_user)
34565 +#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
34566 +#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
34567 +#define MEMLOCK _IOW('M', 5, struct erase_info_user)
34568 +#define MEMUNLOCK _IOW('M', 6, struct erase_info_user)
34569 +#define MEMGETREGIONCOUNT _IOR('M', 7, int)
34570 +#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user)
34571 +#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo)
34572 +#define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo)
34573 +#define MEMGETBADBLOCK _IOW('M', 11, loff_t)
34574 +#define MEMSETBADBLOCK _IOW('M', 12, loff_t)
34576 +struct nand_oobinfo {
34578 + uint32_t eccbytes;
34579 + uint32_t oobfree[8][2];
34580 + uint32_t eccpos[32];
34583 +#endif /* __MTD_ABI_H__ */
34584 Index: linux-2.6.5/include/mtd/mtd-user.h
34585 ===================================================================
34586 --- linux-2.6.5.orig/include/mtd/mtd-user.h 1969-12-31 19:00:00.000000000 -0500
34587 +++ linux-2.6.5/include/mtd/mtd-user.h 2005-02-01 17:11:17.000000000 -0500
34590 + * $Id: mtd-user.h,v 1.2 2004/05/05 14:44:57 dwmw2 Exp $
34592 + * MTD ABI header for use by user space only.
34595 +#ifndef __MTD_USER_H__
34596 +#define __MTD_USER_H__
34598 +#include <stdint.h>
34600 +/* This file is blessed for inclusion by userspace */
34601 +#include <mtd/mtd-abi.h>
34603 +typedef struct mtd_info_user mtd_info_t;
34604 +typedef struct erase_info_user erase_info_t;
34605 +typedef struct region_info_user region_info_t;
34606 +typedef struct nand_oobinfo nand_oobinfo_t;
34608 +#endif /* __MTD_USER_H__ */
34609 Index: linux-2.6.5/include/mtd/nftl-user.h
34610 ===================================================================
34611 --- linux-2.6.5.orig/include/mtd/nftl-user.h 1969-12-31 19:00:00.000000000 -0500
34612 +++ linux-2.6.5/include/mtd/nftl-user.h 2005-02-01 17:11:17.000000000 -0500
34615 + * $Id: nftl-user.h,v 1.1 2004/05/05 14:44:57 dwmw2 Exp $
34617 + * Parts of NFTL headers shared with userspace
34621 +#ifndef __MTD_NFTL_USER_H__
34622 +#define __MTD_NFTL_USER_H__
34624 +/* Block Control Information */
34627 + unsigned char ECCSig[6];
34630 +}__attribute__((packed));
34632 +/* Unit Control Information */
34634 +struct nftl_uci0 {
34635 + uint16_t VirtUnitNum;
34636 + uint16_t ReplUnitNum;
34637 + uint16_t SpareVirtUnitNum;
34638 + uint16_t SpareReplUnitNum;
34639 +} __attribute__((packed));
34641 +struct nftl_uci1 {
34642 + uint32_t WearInfo;
34643 + uint16_t EraseMark;
34644 + uint16_t EraseMark1;
34645 +} __attribute__((packed));
34647 +struct nftl_uci2 {
34648 + uint16_t FoldMark;
34649 + uint16_t FoldMark1;
34651 +} __attribute__((packed));
34654 + struct nftl_uci0 a;
34655 + struct nftl_uci1 b;
34656 + struct nftl_uci2 c;
34660 + struct nftl_bci b;
34661 + union nftl_uci u;
34664 +/* NFTL Media Header */
34666 +struct NFTLMediaHeader {
34667 + char DataOrgID[6];
34668 + uint16_t NumEraseUnits;
34669 + uint16_t FirstPhysicalEUN;
34670 + uint32_t FormattedSize;
34671 + unsigned char UnitSizeFactor;
34672 +} __attribute__((packed));
34674 +#define MAX_ERASE_ZONES (8192 - 512)
34676 +#define ERASE_MARK 0x3c69
34677 +#define SECTOR_FREE 0xff
34678 +#define SECTOR_USED 0x55
34679 +#define SECTOR_IGNORE 0x11
34680 +#define SECTOR_DELETED 0x00
34682 +#define FOLD_MARK_IN_PROGRESS 0x5555
34684 +#define ZONE_GOOD 0xff
34685 +#define ZONE_BAD_ORIGINAL 0
34686 +#define ZONE_BAD_MARKED 7
34689 +#endif /* __MTD_NFTL_USER_H__ */
34690 Index: linux-2.6.5/lib/Kconfig
34691 ===================================================================
34692 --- linux-2.6.5.orig/lib/Kconfig 2005-02-01 16:55:08.000000000 -0500
34693 +++ linux-2.6.5/lib/Kconfig 2005-02-01 17:11:17.000000000 -0500
34695 config ZLIB_DEFLATE
34699 +# reed solomon support is select'ed if needed
34701 +config REED_SOLOMON
34706 Index: linux-2.6.5/lib/Kconfig.orig
34707 ===================================================================
34708 --- linux-2.6.5.orig/lib/Kconfig.orig 1969-12-31 19:00:00.000000000 -0500
34709 +++ linux-2.6.5/lib/Kconfig.orig 2005-02-01 17:11:17.000000000 -0500
34712 +# Library configuration
34715 +menu "Library routines"
34718 + tristate "CRC32 functions"
34720 + This option is provided for the case where no in-kernel-tree
34721 + modules require CRC32 functions, but a module built outside the
34722 + kernel tree does. Such modules that use library CRC32 functions
34726 + bool "Quick Sort"
34729 +# compression support is select'ed if needed
34731 +config ZLIB_INFLATE
34734 +config ZLIB_DEFLATE
34739 Index: linux-2.6.5/lib/Makefile
34740 ===================================================================
34741 --- linux-2.6.5.orig/lib/Makefile 2005-02-01 16:55:56.000000000 -0500
34742 +++ linux-2.6.5/lib/Makefile 2005-02-01 17:11:17.000000000 -0500
34745 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
34746 obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
34747 +obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
34749 host-progs := gen_crc32table
34750 clean-files := crc32table.h
34751 Index: linux-2.6.5/lib/reed_solomon/Makefile
34752 ===================================================================
34753 --- linux-2.6.5.orig/lib/reed_solomon/Makefile 1969-12-31 19:00:00.000000000 -0500
34754 +++ linux-2.6.5/lib/reed_solomon/Makefile 2005-02-01 17:11:17.000000000 -0500
34757 +# This is a modified version of reed solomon lib,
34760 +obj-$(CONFIG_REED_SOLOMON) += reed_solomon.o
34762 Index: linux-2.6.5/lib/reed_solomon/decode_rs.c
34763 ===================================================================
34764 --- linux-2.6.5.orig/lib/reed_solomon/decode_rs.c 1969-12-31 19:00:00.000000000 -0500
34765 +++ linux-2.6.5/lib/reed_solomon/decode_rs.c 2005-02-01 17:11:17.000000000 -0500
34768 + * lib/reed_solomon/decode_rs.c
34771 + * Generic Reed Solomon encoder / decoder library
34773 + * Copyright 2002, Phil Karn, KA9Q
34774 + * May be used under the terms of the GNU General Public License (GPL)
34776 + * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
34778 + * $Id: decode_rs.c,v 1.1 2004/09/16 23:58:56 gleixner Exp $
34782 +/* Generic data witdh independend code which is included by the
34786 + int deg_lambda, el, deg_omega;
34787 + int i, j, r, k, PAD;
34788 + uint16_t u, q, tmp, num1, num2, den, discr_r, syn_error;
34789 + /* Err+Eras Locator poly and syndrome poly */
34790 + uint16_t lambda[NROOTS + 1], syn[NROOTS];
34791 + uint16_t b[NROOTS + 1], t[NROOTS + 1], omega[NROOTS + 1];
34792 + uint16_t root[NROOTS], reg[NROOTS + 1], loc[NROOTS];
34794 + uint16_t msk = (uint16_t) rs->nn;
34796 + /* Check length parameter for validity */
34797 + PAD = NN - NROOTS - len;
34798 + if (PAD < 0 || PAD >= NN)
34801 + /* The caller does not provide the syndrome */
34803 + /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */
34804 + for (i = 0; i < NROOTS; i++)
34805 + syn[i] = (((uint16_t) data[0]) ^ invmsk) & msk;
34807 + for (j = 1; j < len; j++) {
34808 + for (i = 0; i < NROOTS; i++) {
34809 + if (syn[i] == 0) {
34810 + syn[i] = (((uint16_t) data[j]) ^ invmsk) & msk;
34812 + syn[i] = ((((uint16_t) data[j]) ^ invmsk) & msk) ^ ALPHA_TO[MODNN(INDEX_OF[syn[i]] + (FCR+i)*PRIM)];
34817 + for (j = 0; j < NROOTS; j++) {
34818 + for (i = 0; i < NROOTS; i++) {
34819 + if (syn[i] == 0) {
34820 + syn[i] = ((uint16_t) par[j]) & msk;
34822 + syn[i] = (((uint16_t) par[j]) & msk) ^ ALPHA_TO[MODNN(INDEX_OF[syn[i]] + (FCR+i)*PRIM)];
34829 + /* Convert syndromes to index form, checking for nonzero condition */
34831 + for (i = 0; i < NROOTS; i++) {
34832 + syn_error |= s[i];
34833 + s[i] = INDEX_OF[s[i]];
34836 + if (!syn_error) {
34837 + /* if syndrome is zero, data[] is a codeword and there are no
34838 + * errors to correct. So return data[] unmodified
34843 + memset (&lambda[1], 0, NROOTS * sizeof (lambda[0]));
34846 + if (no_eras > 0) {
34847 + /* Init lambda to be the erasure locator polynomial */
34848 + lambda[1] = ALPHA_TO[MODNN (PRIM * (NN - 1 - eras_pos[0]))];
34849 + for (i = 1; i < no_eras; i++) {
34850 + u = MODNN (PRIM * (NN - 1 - eras_pos[i]));
34851 + for (j = i + 1; j > 0; j--) {
34852 + tmp = INDEX_OF[lambda[j - 1]];
34854 + lambda[j] ^= ALPHA_TO[MODNN (u + tmp)];
34859 + for (i = 0; i < NROOTS + 1; i++)
34860 + b[i] = INDEX_OF[lambda[i]];
34863 + * Begin Berlekamp-Massey algorithm to determine error+erasure
34864 + * locator polynomial
34868 + while (++r <= NROOTS) { /* r is the step number */
34869 + /* Compute discrepancy at the r-th step in poly-form */
34871 + for (i = 0; i < r; i++) {
34872 + if ((lambda[i] != 0) && (s[r - i - 1] != A0)) {
34873 + discr_r ^= ALPHA_TO[MODNN (INDEX_OF[lambda[i]] + s[r - i - 1])];
34876 + discr_r = INDEX_OF[discr_r]; /* Index form */
34877 + if (discr_r == A0) {
34878 + /* 2 lines below: B(x) <-- x*B(x) */
34879 + memmove (&b[1], b, NROOTS * sizeof (b[0]));
34882 + /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
34883 + t[0] = lambda[0];
34884 + for (i = 0; i < NROOTS; i++) {
34886 + t[i + 1] = lambda[i + 1] ^ ALPHA_TO[MODNN (discr_r + b[i])];
34888 + t[i + 1] = lambda[i + 1];
34890 + if (2 * el <= r + no_eras - 1) {
34891 + el = r + no_eras - el;
34893 + * 2 lines below: B(x) <-- inv(discr_r) *
34896 + for (i = 0; i <= NROOTS; i++)
34897 + b[i] = (lambda[i] == 0) ? A0 : MODNN (INDEX_OF[lambda[i]] - discr_r + NN);
34899 + /* 2 lines below: B(x) <-- x*B(x) */
34900 + memmove (&b[1], b, NROOTS * sizeof (b[0]));
34903 + memcpy (lambda, t, (NROOTS + 1) * sizeof (t[0]));
34907 + /* Convert lambda to index form and compute deg(lambda(x)) */
34909 + for (i = 0; i < NROOTS + 1; i++) {
34910 + lambda[i] = INDEX_OF[lambda[i]];
34911 + if (lambda[i] != A0)
34914 + /* Find roots of the error+erasure locator polynomial by Chien search */
34915 + memcpy (®[1], &lambda[1], NROOTS * sizeof (reg[0]));
34916 + count = 0; /* Number of roots of lambda(x) */
34917 + for (i = 1, k = IPRIM - 1; i <= NN; i++, k = MODNN (k + IPRIM)) {
34918 + q = 1; /* lambda[0] is always 0 */
34919 + for (j = deg_lambda; j > 0; j--) {
34920 + if (reg[j] != A0) {
34921 + reg[j] = MODNN (reg[j] + j);
34922 + q ^= ALPHA_TO[reg[j]];
34926 + continue; /* Not a root */
34927 + /* store root (index-form) and error location number */
34930 + /* If we've already found max possible roots,
34931 + * abort the search to save time
34933 + if (++count == deg_lambda)
34936 + if (deg_lambda != count) {
34938 + * deg(lambda) unequal to number of roots => uncorrectable
34945 + * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
34946 + * x**NROOTS). in index form. Also find deg(omega).
34948 + deg_omega = deg_lambda - 1;
34949 + for (i = 0; i <= deg_omega; i++) {
34951 + for (j = i; j >= 0; j--) {
34952 + if ((s[i - j] != A0) && (lambda[j] != A0))
34954 + ALPHA_TO[MODNN (s[i - j] + lambda[j])];
34956 + omega[i] = INDEX_OF[tmp];
34960 + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
34961 + * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form
34963 + for (j = count - 1; j >= 0; j--) {
34965 + for (i = deg_omega; i >= 0; i--) {
34966 + if (omega[i] != A0)
34967 + num1 ^= ALPHA_TO[MODNN (omega[i] + i * root[j])];
34969 + num2 = ALPHA_TO[MODNN (root[j] * (FCR - 1) + NN)];
34972 + /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
34973 + for (i = min (deg_lambda, NROOTS - 1) & ~1; i >= 0; i -= 2) {
34974 + if (lambda[i + 1] != A0)
34975 + den ^= ALPHA_TO[MODNN (lambda[i + 1] + i * root[j])];
34977 + /* Apply error to data */
34978 + if (num1 != 0 && loc[j] >= PAD) {
34979 + uint16_t cor = ALPHA_TO[MODNN (INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])];
34980 + data[loc[j] - PAD] ^= cor ^ invmsk;
34985 + if (eras_pos != NULL) {
34986 + for (i = 0; i < count; i++)
34987 + eras_pos[i] = loc[i] - PAD;
34992 Index: linux-2.6.5/lib/reed_solomon/encode_rs.c
34993 ===================================================================
34994 --- linux-2.6.5.orig/lib/reed_solomon/encode_rs.c 1969-12-31 19:00:00.000000000 -0500
34995 +++ linux-2.6.5/lib/reed_solomon/encode_rs.c 2005-02-01 17:11:17.000000000 -0500
34998 + * lib/reed_solomon/encode_rs.c
35001 + * Generic Reed Solomon encoder / decoder library
35003 + * Copyright 2002, Phil Karn, KA9Q
35004 + * May be used under the terms of the GNU General Public License (GPL)
35006 + * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
35008 + * $Id: encode_rs.c,v 1.1 2004/09/16 23:58:56 gleixner Exp $
35012 +/* Generic data witdh independend code which is included by the
35014 + * int encode_rsX (struct rs_control *rs, uintX_t *data, int len, uintY_t *par)
35018 + uint16_t feedback;
35019 + uint16_t msk = (uint16_t) NN;
35021 + /* Check length parameter for validity */
35022 + pad = NN - NROOTS - len;
35023 + if (pad < 0 || pad >= NN)
35026 + memset (par, 0, NROOTS * sizeof (uint16_t));
35028 + for (i = 0; i < len; i++) {
35029 + feedback = INDEX_OF[((((uint16_t) data[i])^invmsk) & msk) ^ par[0]];
35030 + /* feedback term is non-zero */
35031 + if (feedback != A0) {
35032 + for (j = 1; j < NROOTS; j++)
35033 + par[j] ^= ALPHA_TO[MODNN (feedback + GENPOLY[NROOTS - j])];
35036 + memmove (&par[0], &par[1], sizeof (uint16_t) * (NROOTS - 1));
35037 + if (feedback != A0)
35038 + par[NROOTS - 1] = ALPHA_TO[MODNN (feedback + GENPOLY[0])];
35040 + par[NROOTS - 1] = 0;
35044 Index: linux-2.6.5/lib/reed_solomon/rslib.c
35045 ===================================================================
35046 --- linux-2.6.5.orig/lib/reed_solomon/rslib.c 1969-12-31 19:00:00.000000000 -0500
35047 +++ linux-2.6.5/lib/reed_solomon/rslib.c 2005-02-01 17:11:17.000000000 -0500
35050 + * lib/reed_solomon/lib_rs.c
35053 + * Generic Reed Solomon encoder / decoder library
35055 + * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
35057 + * Reed Solomon code lifted from reed solomon library written by Phil Karn
35058 + * Copyright 2002 Phil Karn, KA9Q
35060 + * $Id: rslib.c,v 1.1 2004/09/16 23:58:56 gleixner Exp $
35062 + * This program is free software; you can redistribute it and/or modify
35063 + * it under the terms of the GNU General Public License version 2 as
35064 + * published by the Free Software Foundation.
35068 + * The generic Reed Solomon library provides runtime configurable
35069 + * encoding / decoding of RS codes.
35070 + * Each user must call init_rs to get a pointer to a rs_control
35071 + * structure for the given rs parameters. This structure is either
35072 + * generated or a already available matching control structure is used.
35073 + * If a structure is generated then the polynominal arrays for
35074 + * fast encoding / decoding are built. This can take some time so
35075 + * make sure not to call this function from a timecritical path.
35076 + * Usually a module / driver should initialize the neccecary
35077 + * rs_control structure on module / driver init and release it
35079 + * The encoding puts the calculated syndrome into a given syndrom
35081 + * The decoding is a two step process. The first step calculates
35082 + * the syndrome over the received (data + syndrom) and calls the
35083 + * second stage, which does the decoding / error correction itself.
35084 + * Many hw encoders provide a syndrom calculation over the received
35085 + * data + syndrom and can call the second stage directly.
35089 +#include <linux/errno.h>
35090 +#include <linux/kernel.h>
35091 +#include <linux/init.h>
35092 +#include <linux/module.h>
35093 +#include <linux/rslib.h>
35094 +#include <linux/slab.h>
35095 +#include <asm/semaphore.h>
35097 +/* This list holds all currently allocated rs control structures */
35098 +static LIST_HEAD (rslist);
35099 +/* Protection for the list */
35100 +static DECLARE_MUTEX(rslistlock);
35103 + * rs_init - Initialize a Reed-Solomon codec
35105 + * @symsize: symbol size, bits (1-8)
35106 + * @gfpoly: Field generator polynomial coefficients
35107 + * @fcr: first root of RS code generator polynomial, index form
35108 + * @prim: primitive element to generate polynomial roots
35109 + * @nroots: RS code generator polynomial degree (number of roots)
35111 + * Allocate a control structure and the polynom arrays for faster
35112 + * en/decoding. Fill the arrays according to the given parameters
35114 +static struct rs_control *rs_init (int symsize, int gfpoly, int fcr, int prim, int nroots)
35116 + struct rs_control *rs;
35117 + int i, j, sr, root, iprim;
35119 + /* Allocate the control structure */
35120 + rs = (struct rs_control *) kmalloc (sizeof (struct rs_control), GFP_KERNEL);
35124 + INIT_LIST_HEAD(&rs->list);
35126 + rs->mm = symsize;
35127 + rs->nn = (1 << symsize) - 1;
35130 + rs->nroots = nroots;
35131 + rs->gfpoly = gfpoly;
35133 + /* Allocate the arrays */
35134 + rs->alpha_to = (uint16_t *) kmalloc (sizeof (uint16_t) * (rs->nn + 1), GFP_KERNEL);
35135 + if (rs->alpha_to == NULL)
35138 + rs->index_of = (uint16_t *) kmalloc (sizeof (uint16_t) * (rs->nn + 1), GFP_KERNEL);
35139 + if (rs->index_of == NULL)
35142 + rs->genpoly = (uint16_t *) kmalloc (sizeof (uint16_t) * (rs->nroots + 1), GFP_KERNEL);
35143 + if (rs->genpoly == NULL)
35146 + /* Generate Galois field lookup tables */
35147 + rs->index_of[0] = rs->nn; /* log(zero) = -inf */
35148 + rs->alpha_to[rs->nn] = 0; /* alpha**-inf = 0 */
35150 + for (i = 0; i < rs->nn; i++) {
35151 + rs->index_of[sr] = i;
35152 + rs->alpha_to[i] = sr;
35154 + if (sr & (1 << symsize))
35158 + /* If it's not primitive, exit */
35162 + /* Find prim-th root of 1, used in decoding */
35163 + for (iprim = 1; (iprim % prim) != 0; iprim += rs->nn);
35164 + /* prim-th root of 1, index form */
35165 + rs->iprim = iprim / prim;
35167 + /* Form RS code generator polynomial from its roots */
35168 + rs->genpoly[0] = 1;
35169 + for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) {
35170 + rs->genpoly[i + 1] = 1;
35172 + /* Multiply rs->genpoly[] by @**(root + x) */
35173 + for (j = i; j > 0; j--) {
35174 + if (rs->genpoly[j] != 0)
35175 + rs->genpoly[j] = rs->genpoly[j -1] ^ rs->alpha_to[(rs->index_of[rs->genpoly[j]] + root) % rs->nn];
35177 + rs->genpoly[j] = rs->genpoly[j - 1];
35179 + /* rs->genpoly[0] can never be zero */
35180 + rs->genpoly[0] = rs->alpha_to[(rs->index_of[rs->genpoly[0]] + root) % rs->nn];
35182 + /* convert rs->genpoly[] to index form for quicker encoding */
35183 + for (i = 0; i <= nroots; i++)
35184 + rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
35189 + kfree (rs->genpoly);
35191 + kfree (rs->index_of);
35193 + kfree (rs->alpha_to);
35201 + * free_rs - Free the rs control structure, if its not longer used
35203 + * @rs: the control structure which is not longer used by the
35206 +void free_rs (struct rs_control *rs)
35208 + down (&rslistlock);
35210 + if (!rs->users) {
35211 + list_del (&rs->list);
35212 + kfree (rs->alpha_to);
35213 + kfree (rs->index_of);
35214 + kfree (rs->genpoly);
35217 + up (&rslistlock);
35221 + * init_rs - Find a matching or allocate a new rs control structure
35223 + * @symsize: the symbol size (number of bits)
35224 + * @gfpoly: the extended Galois field generator polynomial coefficients,
35225 + * with the 0th coefficient in the low order bit. The polynomial
35226 + * must be primitive;
35227 + * @fcr: the first consecutive root of the rs code generator polynomial
35229 + * @prim: primitive element to generate polynomial roots
35230 + * @nroots: RS code generator polynomial degree (number of roots)
35232 +struct rs_control *init_rs (int symsize, int gfpoly, int fcr, int prim, int nroots)
35234 + struct list_head *tmp;
35235 + struct rs_control *rs;
35237 + /* Sanity checks */
35240 + if (fcr < 0 || fcr >= (1<<symsize))
35242 + if (prim <= 0 || prim >= (1<<symsize))
35244 + if (nroots < 0 || nroots >= (1<<symsize))
35247 + down (&rslistlock);
35250 + /* Walk through the list and look for a matching entry */
35251 + list_for_each (tmp, &rslist) {
35252 + rs = list_entry (tmp, struct rs_control, list);
35253 + if (symsize != rs->mm)
35255 + if (gfpoly != rs->gfpoly)
35257 + if (fcr != rs->fcr)
35259 + if (prim != rs->prim)
35261 + if (nroots != rs->nroots)
35263 + /* We have a matching one already */
35269 + /* Create a new one */
35270 + rs = rs_init (symsize, gfpoly, fcr, prim, nroots);
35273 + list_add (&rs->list, &rslist);
35276 + up (&rslistlock);
35281 + * encode_rs8 - Calculate the parity for data values (8bit data width)
35283 + * @rs: the rs control structure
35284 + * @data: data field of a given type
35285 + * @len: data length
35286 + * @par: parity data field
35287 + * @invmsk: invert data mask
35289 + * The parity uses a uint16_t data type to enable
35290 + * symbol size > 8. The calling code must take care of encoding of the
35291 + * syndrome result for storage itself.
35293 +int encode_rs8 (struct rs_control *rs, uint8_t *data, int len, uint16_t *par, uint16_t invmsk)
35295 +#define RSINVMSK 0xFF
35296 +#include "encode_rs.c"
35300 + * decode_rs8 - Decode codeword (8bit data width)
35302 + * @rs: the rs control structure
35303 + * @data: data field of a given type
35304 + * @par: received parity data field
35305 + * @len: data length
35306 + * @s: syndrome data field (if NULL, syndrome must be calculated)
35307 + * @no_eras: number of erasures
35308 + * @eras_pos: position of erasures, can be NULL
35309 + * @invmsk: invert data mask
35311 + * The syndrome and parity uses a uint16_t data type to enable
35312 + * symbol size > 8. The calling code must take care of decoding of the
35313 + * syndrome result and the received parity before calling this code.
35315 +int decode_rs8 (struct rs_control *rs, uint8_t *data, uint16_t *par,
35316 + int len, uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk)
35318 +#include "decode_rs.c"
35322 + * encode_rs16 - Calculate the parity for data values (16bit data width)
35324 + * @rs: the rs control structure
35325 + * @data: data field of a given type
35326 + * @len: data length
35327 + * @par: parity data field
35328 + * @invmsk: invert data mask
35330 + * Each field in the data array contains up to symbol size bits of valid data.
35332 +int encode_rs16 (struct rs_control *rs, uint16_t *data, int len, uint16_t *par, uint16_t invmsk)
35335 +#define RSINVMSK 0xFFFF
35336 +#include "encode_rs.c"
35340 + * decode_rs16 - Decode codeword (16bit data width)
35342 + * @rs: the rs control structure
35343 + * @data: data field of a given type
35344 + * @par: received parity data field
35345 + * @len: data length
35346 + * @s: syndrome data field (if NULL, syndrome must be calculated)
35347 + * @no_eras: number of erasures
35348 + * @eras_pos: position of erasures, can be NULL
35349 + * @invmsk: invert data mask
35351 + * Each field in the data array contains up to symbol size bits of valid data.
35353 +int decode_rs16 (struct rs_control *rs, uint16_t *data, uint16_t *par,
35354 + int len, uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk)
35356 +#include "decode_rs.c"
35360 + * encode_rs32 - Calculate the parity for data values (32bit data width)
35362 + * @rs: the rs control structure
35363 + * @data: data field of a given type
35364 + * @len: data length
35365 + * @par: parity data field
35366 + * @invmsk: invert data mask
35368 + * The parity uses a uint16_t data type due to the fact that
35369 + * we can't handle symbol size >= 16 bit as the polynominal arrays would
35370 + * be to large and the computation would be extreme slow.
35371 + * Each field in the data array contains up to symbol size bits of data.
35373 +int encode_rs32 (struct rs_control *rs, uint32_t *data, int len, uint16_t *par, uint16_t invmsk)
35375 +#include "encode_rs.c"
35379 + * decode_rs32 - Decode codeword (32bit data width)
35381 + * @rs: the rs control structure
35382 + * @data: data field of a given type
35383 + * @par: received parity data field
35384 + * @len: data length
35385 + * @s: syndrome data field (if NULL, syndrome must be calculated)
35386 + * @no_eras: number of erasures
35387 + * @eras_pos: position of erasures, can be NULL
35388 + * @invmsk: invert data mask
35390 + * The syndrome and parity use a uint16_t data type due to the fact that
35391 + * we can't handle symbol size > 16 as the polynominal arrays would be to
35392 + * large and the computation would be extreme slow. The calling code must
35393 + * take care of decoding of the syndrome result and the received parity
35394 + * before calling this code.
35395 + * Each field in the data array contains up to symbol size bits of data.
35397 +int decode_rs32 (struct rs_control *rs, uint32_t *data, uint16_t *par,
35398 + int len, uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk)
35400 +#include "decode_rs.c"
35403 +EXPORT_SYMBOL(encode_rs8);
35404 +EXPORT_SYMBOL(encode_rs16);
35405 +EXPORT_SYMBOL(encode_rs32);
35406 +EXPORT_SYMBOL(decode_rs8);
35407 +EXPORT_SYMBOL(decode_rs16);
35408 +EXPORT_SYMBOL(decode_rs32);
35409 +EXPORT_SYMBOL(init_rs);
35410 +EXPORT_SYMBOL(free_rs);
35412 +MODULE_LICENSE("GPL");
35413 +MODULE_DESCRIPTION("Reed Solomon encoder/decoder");
35414 +MODULE_AUTHOR("Phil Karn, Thomas Gleixner");