Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / mtd-2.6-suse-lnxi.patch
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
5 @@ -1,4 +1,4 @@
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 $
8  
9  menu "Memory Technology Devices (MTD)"
10  
11 @@ -28,7 +28,7 @@
12           Determines the verbosity level of the MTD debugging messages.
13  
14  config MTD_PARTITIONS
15 -       tristate "MTD partitioning support"
16 +       bool "MTD partitioning support"
17         depends on MTD
18         help
19           If you have a device which needs to divide its flash chip(s) up
20 @@ -68,9 +68,23 @@
21           SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for 
22           example.
23  
24 +config MTD_REDBOOT_PARTS_UNALLOCATED
25 +       bool "  Include unallocated flash regions"
26 +       depends on MTD_REDBOOT_PARTS
27 +       help
28 +         If you need to register each unallocated flash region as a MTD
29 +         'partition', enable this option.
30 +
31 +config MTD_REDBOOT_PARTS_READONLY
32 +       bool "  Force read-only for RedBoot system images"
33 +       depends on MTD_REDBOOT_PARTS
34 +       help
35 +         If you need to force read-only for 'RedBoot', 'RedBoot Config' and
36 +         'FIS directory' images, enable this option.
37 +
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"
43         ---help---
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
50 @@ -1,28 +1,14 @@
51  #
52  # Makefile for the memory technology device drivers.
53  #
54 -# $Id: Makefile.common,v 1.2 2003/05/23 11:38:29 dwmw2 Exp $
55 -
56 -#                       *** BIG UGLY NOTE ***
57 -#
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
62 -# docprobe.
63 -#
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
66 -# to stay like that.
67 -#
68 -# Urgh.
69 -# 
70 -# dwmw2 21/11/0
71 +# $Id: Makefile.common,v 1.5 2004/08/10 20:51:49 dwmw2 Exp $
72  
73  # Core functionality.
74 -obj-$(CONFIG_MTD)              += mtdcore.o
75 +mtd-y                          := mtdcore.o
76 +mtd-$(CONFIG_MTD_PARTITIONS)   += mtdpart.o
77 +obj-$(CONFIG_MTD)              += $(mtd-y)
78 +
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
88 @@ -21,7 +21,7 @@
89     This is access code for flashes using ARM's flash partitioning 
90     standards.
91  
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 $
94  
95  ======================================================================*/
96  
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
101 @@ -1,5 +1,5 @@
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 $
105  
106  menu "RAM/ROM/Flash chip drivers"
107         depends on MTD!=n
108 @@ -85,59 +85,72 @@
109           arrangements of CFI chips. If unsure, say 'N' and all options 
110           which are supported by the current code will be enabled.
111  
112 -config MTD_CFI_B1
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
117 +       default y
118         help
119           If you wish to support CFI devices on a physical bus which is
120           8 bits wide, say 'Y'.
121  
122 -config MTD_CFI_B2
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
127 +       default y
128         help
129           If you wish to support CFI devices on a physical bus which is
130           16 bits wide, say 'Y'.
131  
132 -config MTD_CFI_B4
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
137 +       default y
138         help
139           If you wish to support CFI devices on a physical bus which is
140           32 bits wide, say 'Y'.
141  
142 -config MTD_CFI_B8
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
147 +       default n
148         help
149           If you wish to support CFI devices on a physical bus which is
150           64 bits wide, say 'Y'.
151  
152 +config MTD_MAP_BANK_WIDTH_16
153 +       bool "Support 128-bit buswidth" if MTD_CFI_GEOMETRY
154 +       default n
155 +       help
156 +         If you wish to support CFI devices on a physical bus which is
157 +         128 bits wide, say 'Y'.
158 +
159 +config MTD_MAP_BANK_WIDTH_32
160 +       bool "Support 256-bit buswidth" if MTD_CFI_GEOMETRY
161 +       default n
162 +       help
163 +         If you wish to support CFI devices on a physical bus which is
164 +         256 bits wide, say 'Y'.
165 +
166  config MTD_CFI_I1
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
171 +       default y
172         help
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'.
175  
176  config MTD_CFI_I2
177 -       bool "Support 2-chip flash interleave"
178 -       depends on MTD_CFI_GEOMETRY
179 +       bool "Support 2-chip flash interleave" if MTD_CFI_GEOMETRY
180 +       default y
181         help
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'.
184  
185  config MTD_CFI_I4
186 -       bool "Support 4-chip flash interleave"
187 -       depends on MTD_CFI_GEOMETRY
188 +       bool "Support 4-chip flash interleave" if MTD_CFI_GEOMETRY
189 +       default n
190         help
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'.
193  
194  config MTD_CFI_I8
195 -       bool "Support 8-chip flash interleave"
196 -       depends on MTD_CFI_GEOMETRY
197 +       bool "Support 8-chip flash interleave" if MTD_CFI_GEOMETRY
198 +       default n
199         help
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'.
202 @@ -160,6 +173,27 @@
203           provides support for one of those command sets, used on chips 
204           including the AMD Am29LV320.
205  
206 +config MTD_CFI_AMDSTD_RETRY
207 +       int "Retry failed commands (erase/program)"
208 +       depends on MTD_CFI_AMDSTD
209 +       default "0"
210 +       help
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.
215 +
216 +         SST49LF040 (and related) chips are know to be broken.
217 +
218 +config MTD_CFI_AMDSTD_RETRY_MAX
219 +       int "Max retries of failed commands (erase/program)"
220 +       depends on MTD_CFI_AMDSTD_RETRY
221 +       default "0"
222 +       help
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.
226 +
227  config MTD_CFI_STAA
228         tristate "Support for ST (Advanced Architecture) flash chips"
229         depends on MTD_GEN_PROBE
230 @@ -168,6 +202,11 @@
231           sets which a CFI-compliant chip may claim to implement. This code
232           provides support for one of those command sets.
233  
234 +config MTD_CFI_UTIL
235 +       tristate
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
238 +
239  config MTD_RAM
240         tristate "Support for RAM chips in bus mapping"
241         depends on MTD
242 @@ -194,6 +233,7 @@
243           with this driver will return -ENODEV upon access.
244  
245  config MTD_OBSOLETE_CHIPS
246 +       depends on MTD && BROKEN
247         bool "Older (theoretically obsoleted now) drivers for non-CFI chips"
248         help
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
254 @@ -1,18 +1,19 @@
255  #
256  # linux/drivers/chips/Makefile
257  #
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 $
260  
261  #                       *** BIG UGLY NOTE ***
262  #
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
268  
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
280 @@ -3,7 +3,7 @@
281   *
282   * Author: Jonas Holmberg <jonas.holmberg@axis.com>
283   *
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 $
286   *
287   * Copyright (c) 2001 Axis Communications AB
288   *
289 @@ -718,7 +718,7 @@
290                        "memory for MTD erase region info\n", map->name);
291                 kfree(mtd);
292                 map->fldrv_priv = NULL;
293 -               return 0;
294 +               return NULL;
295         }
296  
297         reg_idx = 0;
298 @@ -780,8 +780,8 @@
299         map->fldrv_priv = private;
300  
301         map->fldrv = &amd_flash_chipdrv;
302 -       MOD_INC_USE_COUNT;
303  
304 +       __module_get(THIS_MODULE);
305         return mtd;
306  }
307  
308 @@ -1307,9 +1307,7 @@
309         }
310                 
311         instr->state = MTD_ERASE_DONE;
312 -       if (instr->callback) {
313 -               instr->callback(instr);
314 -       }
315 +       mtd_erase_callback(instr);
316         
317         return 0;
318  }
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
323 @@ -4,7 +4,7 @@
324   *
325   * (C) 2000 Red Hat. GPL'd
326   *
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 $
329   *
330   * 
331   * 10/10/2000  Nicolas Pitre <nico@cam.org>
332 @@ -34,12 +34,20 @@
333  #include <linux/mtd/compatmac.h>
334  #include <linux/mtd/cfi.h>
335  
336 +/* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */
337 +
338  // debugging, turns off buffer write mode if set to 1
339  #define FORCE_WORD_WRITE 0
340  
341 +#define MANUFACTURER_INTEL     0x0089
342 +#define I82802AB       0x00ad
343 +#define I82802AC       0x00ac
344 +#define MANUFACTURER_ST         0x0020
345 +#define M50LPW080       0x002F
346 +
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 *);
355 @@ -53,13 +61,19 @@
356  
357  struct mtd_info *cfi_cmdset_0001(struct map_info *, int);
358  
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 **);
362  
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,
366                         size_t len);
367  
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"
371 +
372 +
373  
374  /*
375   *  *********** SETUP AND PROBE BITS  ***********
376 @@ -79,17 +93,18 @@
377  static void cfi_tell_features(struct cfi_pri_intelext *extp)
378  {
379         int i;
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);
405         }
406 @@ -110,13 +125,93 @@
407         }
408         
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);
416 +}
417 +#endif
418 +
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)
422 +{
423 +       struct map_info *map = mtd->priv;
424 +       struct cfi_private *cfi = map->fldrv_priv;
425 +       struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
426 +
427 +       printk(KERN_WARNING "cfi_cmdset_0001: Suspend "
428 +                           "erase on write disabled.\n");
429 +       extp->SuspendCmdSupport &= ~1;
430  }
431  #endif
432  
433 +static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param)
434 +{
435 +       struct map_info *map = mtd->priv;
436 +       struct cfi_private *cfi = map->fldrv_priv;
437 +       
438 +       cfi->cfiq->BufWriteTimeoutTyp = 0;      /* Not supported */
439 +       cfi->cfiq->BufWriteTimeoutMax = 0;      /* Not supported */
440 +}
441 +
442 +static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param)
443 +{
444 +       struct map_info *map = mtd->priv;
445 +       struct cfi_private *cfi = map->fldrv_priv;
446 +       
447 +       /* Note this is done after the region info is endian swapped */
448 +       cfi->cfiq->EraseRegionInfo[1] =
449 +               (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e;
450 +};
451 +
452 +static void fixup_use_point(struct mtd_info *mtd, void *param)
453 +{
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;
458 +       }
459 +}
460 +
461 +static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
462 +{
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;
468 +       }
469 +}
470 +
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 }, 
474 +#endif
475 +#if !FORCE_WORD_WRITE
476 +       { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL },
477 +#endif
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 }
481 +};
482 +
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 }
488 +};
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.
494 +        */
495 +       { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point, NULL },
496 +       { 0, 0, NULL, NULL }
497 +};
498 +
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
502 @@ -127,9 +222,30 @@
503  struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
504  {
505         struct cfi_private *cfi = map->fldrv_priv;
506 +       struct mtd_info *mtd;
507         int i;
508 -       __u32 base = cfi->chips[0].start;
509  
510 +       mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
511 +       if (!mtd) {
512 +               printk(KERN_ERR "Failed to allocate memory for MTD device\n");
513 +               return NULL;
514 +       }
515 +       memset(mtd, 0, sizeof(*mtd));
516 +       mtd->priv = map;
517 +       mtd->type = MTD_NORFLASH;
518 +
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;
530 +       
531         if (cfi->cfi_mode == CFI_MODE_CFI) {
532                 /* 
533                  * It's a real CFI chip, not one for which the probe
534 @@ -138,33 +254,10 @@
535                  */
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;
539 -
540 -               //printk(" Intel/Sharp Extended Query Table at 0x%4.4X\n", adr);
541 -               if (!adr)
542 -                       return NULL;
543  
544 -               /* Switch it into Query Mode */
545 -               cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
546 -
547 -               extp = kmalloc(sizeof(*extp), GFP_KERNEL);
548 +               extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "Intel/Sharp");
549                 if (!extp) {
550 -                       printk(KERN_ERR "Failed to allocate memory\n");
551 -                       return NULL;
552 -               }
553 -               
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)));
558 -               }
559 -               
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);
565 -                       kfree(extp);
566 +                       kfree(mtd);
567                         return NULL;
568                 }
569                 
570 @@ -172,6 +265,11 @@
571                 extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport);
572                 extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask);
573                 extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr);
574 +
575 +               /* Install our own private info structure */
576 +               cfi->cmdset_priv = extp;        
577 +
578 +               cfi_fixup(mtd, cfi_fixup_table);
579                         
580  #ifdef DEBUG_CFI_FEATURES
581                 /* Tell the user about it in lots of lovely detail */
582 @@ -179,19 +277,15 @@
583  #endif 
584  
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;
592 -#else
593                         printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n");
594 -#endif
595                 }
596 -               /* Install our own private info structure */
597 -               cfi->cmdset_priv = extp;        
598         }
599 +       else if (cfi->cfi_mode == CFI_MODE_JEDEC) {
600 +               /* Apply jedec specific fixups */
601 +               cfi_fixup(mtd, jedec_fixup_table);
602 +       }
603 +       /* Apply generic fixups */
604 +       cfi_fixup(mtd, fixup_table);
605  
606         for (i=0; i< cfi->numchips; i++) {
607                 cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
608 @@ -202,30 +296,19 @@
609  
610         map->fldrv = &cfi_intelext_chipdrv;
611         
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);
616  }
617  
618 -static struct mtd_info *cfi_intelext_setup(struct map_info *map)
619 +static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
620  {
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;
625         int i,j;
626         unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
627  
628 -       mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
629         //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
630  
631 -       if (!mtd) {
632 -               printk(KERN_ERR "Failed to allocate memory for MTD device\n");
633 -               goto setup_err;
634 -       }
635 -
636 -       memset(mtd, 0, sizeof(*mtd));
637 -       mtd->priv = map;
638 -       mtd->type = MTD_NORFLASH;
639         mtd->size = devsize * cfi->numchips;
640  
641         mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
642 @@ -265,32 +348,16 @@
643                        mtd->eraseregions[i].numblocks);
644         }
645  
646 -       /* Also select the correct geometry setup too */ 
647 -       mtd->erase = cfi_intelext_erase_varsize;
648 -       mtd->read = cfi_intelext_read;
649 -
650 -       if (map_is_linear(map)) {
651 -               mtd->point = cfi_intelext_point;
652 -               mtd->unpoint = cfi_intelext_unpoint;
653 -       }
654 -
655 -       if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) {
656 -               printk(KERN_INFO "Using buffer write method\n" );
657 -               mtd->write = cfi_intelext_write_buffers;
658 -       } else {
659 -               printk(KERN_INFO "Using word write method\n" );
660 -               mtd->write = cfi_intelext_write_words;
661 -       }
662 +#if 0
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;
673 +#endif
674 +
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)
678 +               goto setup_err;
679 +
680         __module_get(THIS_MODULE);
681         return mtd;
682  
683 @@ -301,10 +368,87 @@
684                 kfree(mtd);
685         }
686         kfree(cfi->cmdset_priv);
687 -       kfree(cfi->cfiq);
688         return NULL;
689  }
690  
691 +static int cfi_intelext_partition_fixup(struct map_info *map,
692 +                                       struct cfi_private **pcfi)
693 +{
694 +       struct cfi_private *cfi = *pcfi;
695 +       struct cfi_pri_intelext *extp = cfi->cmdset_priv;
696 +
697 +       /*
698 +        * Probing of multi-partition flash ships.
699 +        *
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
703 +        * detected.
704 +        *
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
712 +        */
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;
718 +
719 +               /*
720 +                * The L18 flash memory array is divided
721 +                * into multiple 8-Mbit partitions.
722 +                */
723 +               numparts = 1 << (cfi->cfiq->DevSize - 20);
724 +               partshift = 20 + __ffs(cfi->interleave);
725 +               numvirtchips = cfi->numchips * numparts;
726 +
727 +               newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL);
728 +               if (!newcfi)
729 +                       return -ENOMEM;
730 +               shared = kmalloc(sizeof(struct flchip_shared) * cfi->numchips, GFP_KERNEL);
731 +               if (!shared) {
732 +                       kfree(newcfi);
733 +                       return -ENOMEM;
734 +               }
735 +               memcpy(newcfi, cfi, sizeof(struct cfi_private));
736 +               newcfi->numchips = numvirtchips;
737 +               newcfi->chipshift = partshift;
738 +
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;
752 +                               chip++;
753 +                       }
754 +               }
755 +
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);
760 +
761 +               map->fldrv_priv = newcfi;
762 +               *pcfi = newcfi;
763 +               kfree(cfi);
764 +       }
765 +
766 +       return 0;
767 +}
768 +
769  /*
770   *  *********** CHIP ACCESS FUNCTIONS ***********
771   */
772 @@ -313,25 +457,87 @@
773  {
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);
778         unsigned long timeo;
779 -       struct cfi_pri_intelext *cfip = (struct cfi_pri_intelext *)cfi->cmdset_priv;
780 +       struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
781  
782   resettime:
783         timeo = jiffies + HZ;
784   retry:
785 +       if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING)) {
786 +               /*
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.
791 +                *
792 +                * The rules are as follows:
793 +                *
794 +                * - any write operation must own shared->writing.
795 +                *
796 +                * - any erase operation must own _both_ shared->writing and
797 +                *   shared->erasing.
798 +                *
799 +                * - contension arbitration is handled in the owner's context.
800 +                *
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.
804 +                */
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) {
810 +                       /*
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.
818 +                        */
819 +                       int ret = spin_trylock(contender->mutex);
820 +                       spin_unlock(&shared->lock);
821 +                       if (!ret)
822 +                               goto retry;
823 +                       spin_unlock(chip->mutex);
824 +                       ret = get_chip(map, contender, contender->start, mode);
825 +                       spin_lock(chip->mutex);
826 +                       if (ret) {
827 +                               spin_unlock(contender->mutex);
828 +                               return ret;
829 +                       }
830 +                       timeo = jiffies + HZ;
831 +                       spin_lock(&shared->lock);
832 +               }
833 +
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);
841 +       }
842 +
843         switch (chip->state) {
844  
845         case FL_STATUS:
846                 for (;;) {
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))
851 +                               break;
852 +
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))
856                                 break;
857  
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", 
863 +                                      status.x[0]);
864                                 return -EIO;
865                         }
866                         spin_unlock(chip->mutex);
867 @@ -347,38 +553,39 @@
868                 return 0;
869  
870         case FL_ERASING:
871 -               if (!(cfip->FeatureSupport & 2) ||
872 +               if (!cfip ||
873 +                   !(cfip->FeatureSupport & 2) ||
874                     !(mode == FL_READY || mode == FL_POINT ||
875                      (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1))))
876                         goto sleep;
877  
878  
879                 /* Erase suspend */
880 -               cfi_write(map, CMD(0xB0), adr);
881 +               map_write(map, CMD(0xB0), adr);
882  
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
887                  */
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;
893                 for (;;) {
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))
898                                 break;
899  
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]);
912                                 return -EIO;
913                         }
914  
915 @@ -412,6 +619,32 @@
916  {
917         struct cfi_private *cfi = map->fldrv_priv;
918  
919 +       if (chip->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);
934 +                       } else {
935 +                               if (chip->oldstate != FL_ERASING) {
936 +                                       shared->erasing = NULL;
937 +                                       if (chip->oldstate != FL_WRITING)
938 +                                               shared->writing = NULL;
939 +                               }
940 +                               spin_unlock(&shared->lock);
941 +                       }
942 +               }
943 +       }
944 +
945         switch(chip->oldstate) {
946         case FL_ERASING:
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 
951                    do. */
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;
958                 break;
959  
960         case FL_READY:
961 +       case FL_STATUS:
962 +       case FL_JEDEC_QUERY:
963                 /* We should really make set_vpp() count, rather than doing this */
964                 DISABLE_VPP(map);
965                 break;
966 @@ -449,7 +684,7 @@
967         adr += chip->start;
968  
969         /* Ensure cmd read/writes are aligned. */ 
970 -       cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); 
971 +       cmd_addr = adr & ~(map_bankwidth(map)-1); 
972  
973         spin_lock(chip->mutex);
974  
975 @@ -457,7 +692,7 @@
976  
977         if (!ret) {
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);
981  
982                 chip->state = FL_POINT;
983                 chip->ref_point_counter++;
984 @@ -475,12 +710,10 @@
985         int chipnum;
986         int ret = 0;
987  
988 -       if (from + len > mtd->size)
989 +       if (!map->virt || (from + len > mtd->size))
990                 return -EINVAL;
991         
992         *mtdbuf = (void *)map->virt + from;
993 -       if(*mtdbuf == NULL)
994 -               return -EINVAL; /* can not point this region */
995         *retlen = 0;
996  
997         /* Now lock the chip(s) to POINT state */
998 @@ -565,7 +798,7 @@
999         adr += chip->start;
1000  
1001         /* Ensure cmd read/writes are aligned. */ 
1002 -       cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); 
1003 +       cmd_addr = adr & ~(map_bankwidth(map)-1); 
1004  
1005         spin_lock(chip->mutex);
1006         ret = get_chip(map, chip, cmd_addr, FL_READY);
1007 @@ -575,7 +808,7 @@
1008         }
1009  
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);
1013  
1014                 chip->state = FL_READY;
1015         }
1016 @@ -626,7 +859,7 @@
1017         }
1018         return ret;
1019  }
1020 -
1021 +#if 0
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)
1023  {
1024         struct map_info *map = mtd->priv;
1025 @@ -657,7 +890,7 @@
1026                 }
1027  
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;
1032                 }
1033  
1034 @@ -688,7 +921,7 @@
1035         int base_offst,reg_sz;
1036         
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);
1041                 return 0;
1042         }
1043 @@ -707,7 +940,7 @@
1044         int base_offst,reg_sz;
1045         
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);
1050                 return 0;
1051         }
1052 @@ -717,12 +950,12 @@
1053  
1054         return cfi_intelext_read_prot_reg(mtd, from, len, retlen, buf, base_offst, reg_sz);
1055  }
1056 +#endif
1057  
1058 -
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)
1061  {
1062         struct cfi_private *cfi = map->fldrv_priv;
1063 -       cfi_word status, status_OK;
1064 +       map_word status, status_OK;
1065         unsigned long timeo;
1066         int z, ret=0;
1067  
1068 @@ -739,11 +972,12 @@
1069         }
1070  
1071         ENABLE_VPP(map);
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;
1077  
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);
1082  
1083 @@ -764,8 +998,8 @@
1084                         continue;
1085                 }
1086  
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))
1091                         break;
1092                 
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))) {
1100                 /* clear status */
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);
1106                 ret = -EROFS;
1107         }
1108   out:
1109 @@ -824,35 +1058,22 @@
1110         ofs = to  - (chipnum << cfi->chipshift);
1111  
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;
1118 -               int i = 0, n = 0;
1119 -               u_char tmp_buf[8];
1120 -               cfi_word datum;
1121 -
1122 -               while (gap--)
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;
1128 -
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;
1135 -               } else {
1136 -                       return -EINVAL;  /* should never happen, but be safe */
1137 -               }
1138 +               int n;
1139 +               map_word datum;
1140 +
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);
1144  
1145                 ret = do_write_oneword(map, &cfi->chips[chipnum],
1146                                                bus_ofs, datum);
1147                 if (ret) 
1148                         return ret;
1149 -               
1150 +
1151 +               len -= n;
1152                 ofs += n;
1153                 buf += n;
1154                 (*retlen) += n;
1155 @@ -865,30 +1086,18 @@
1156                 }
1157         }
1158         
1159 -       while(len >= CFIDEV_BUSWIDTH) {
1160 -               cfi_word datum;
1161 -
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;
1170 -               } else {
1171 -                       return -EINVAL;
1172 -               }
1173 +       while(len >= map_bankwidth(map)) {
1174 +               map_word datum = map_word_load(map, buf);
1175  
1176                 ret = do_write_oneword(map, &cfi->chips[chipnum],
1177                                 ofs, datum);
1178                 if (ret)
1179                         return ret;
1180  
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);
1189  
1190                 if (ofs >> cfi->chipshift) {
1191                         chipnum ++; 
1192 @@ -898,32 +1107,18 @@
1193                 }
1194         }
1195  
1196 -       if (len & (CFIDEV_BUSWIDTH-1)) {
1197 -               int i = 0, n = 0;
1198 -               u_char tmp_buf[8];
1199 -               cfi_word datum;
1200 -
1201 -               while (len--)
1202 -                       tmp_buf[i++] = buf[n++];
1203 -               while (i < CFIDEV_BUSWIDTH)
1204 -                       tmp_buf[i++] = 0xff;
1205 -
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;
1212 -               } else {
1213 -                       return -EINVAL;  /* should never happen, but be safe */
1214 -               }
1215 +       if (len & (map_bankwidth(map)-1)) {
1216 +               map_word datum;
1217 +
1218 +               datum = map_word_ff(map);
1219 +               datum = map_word_load_partial(map, datum, buf, 0, len);
1220  
1221                 ret = do_write_oneword(map, &cfi->chips[chipnum],
1222                                                ofs, datum);
1223                 if (ret) 
1224                         return ret;
1225                 
1226 -               (*retlen) += n;
1227 +               (*retlen) += len;
1228         }
1229  
1230         return 0;
1231 @@ -934,11 +1129,11 @@
1232                                   unsigned long adr, const u_char *buf, int len)
1233  {
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;
1239  
1240 -       wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize;
1241 +       wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
1242         adr += chip->start;
1243         cmd_adr = adr & ~(wbufsize-1);
1244         
1245 @@ -952,29 +1147,28 @@
1246                 return ret;
1247         }
1248  
1249 -       if (chip->state != FL_STATUS)
1250 -               cfi_write(map, CMD(0x70), cmd_adr);
1251 -
1252 -       status = cfi_read(map, cmd_adr);
1253 -
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);
1269         }
1270 +
1271         ENABLE_VPP(map);
1272         chip->state = FL_WRITING_TO_BUFFER;
1273  
1274         z = 0;
1275         for (;;) {
1276 -               cfi_write(map, CMD(0xe8), cmd_adr);
1277 +               map_write(map, CMD(0xe8), cmd_adr);
1278  
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))
1283                         break;
1284  
1285                 spin_unlock(chip->mutex);
1286 @@ -983,84 +1177,47 @@
1287  
1288                 if (++z > 20) {
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);
1301                         ret = -EIO;
1302                         goto out;
1303                 }
1304         }
1305  
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 );
1313  
1314         /* Write data */
1315         z = 0;
1316 -       while(z < words * CFIDEV_BUSWIDTH) {
1317 -               if (cfi_buswidth_is_1()) {
1318 -                       u8 *b = (u8 *)buf;
1319 -
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;
1324 -
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;
1329 -
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;
1334 -
1335 -                       map_write64 (map, *b++, adr+z);
1336 -                       buf = (const u_char *)b;
1337 -               } else {
1338 -                       ret = -EINVAL;
1339 -                       goto out;
1340 -               }
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);
1345 +
1346 +               z += map_bankwidth(map);
1347 +               buf += map_bankwidth(map);
1348         }
1349 +
1350         if (bytes) {
1351 -               int i = 0, n = 0;
1352 -               u_char tmp_buf[8], *tmp_p = tmp_buf;
1353 +               map_word datum;
1354  
1355 -               while (bytes--)
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;
1361 -
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;
1366 -
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;
1371 -
1372 -                       map_write64 (map, *b++, adr+z);
1373 -                       tmp_p = (u_char *)b;
1374 -               } else {
1375 -                       ret = -EINVAL;
1376 -                       goto out;
1377 -               }
1378 +               datum = map_word_ff(map);
1379 +               datum = map_word_load_partial(map, datum, buf, 0, bytes);
1380 +               map_write(map, datum, adr+z);
1381         }
1382 +
1383         /* GO GO GO */
1384 -       cfi_write(map, CMD(0xd0), cmd_adr);
1385 +       map_write(map, CMD(0xd0), cmd_adr);
1386         chip->state = FL_WRITING;
1387  
1388         spin_unlock(chip->mutex);
1389 +       INVALIDATE_CACHED_RANGE(map, adr, len);
1390         cfi_udelay(chip->buffer_write_time);
1391         spin_lock(chip->mutex);
1392  
1393 @@ -1080,8 +1237,8 @@
1394                         continue;
1395                 }
1396  
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))
1401                         break;
1402  
1403                 /* OK Still waiting */
1404 @@ -1110,11 +1267,11 @@
1405         chip->state = FL_STATUS;
1406  
1407         /* check for lock bit */
1408 -       if (status & CMD(0x02)) {
1409 +       if (map_word_bitsset(map, status, CMD(0x02))) {
1410                 /* clear status */
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);
1416                 ret = -EROFS;
1417         }
1418  
1419 @@ -1129,7 +1286,7 @@
1420  {
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;
1425         int ret = 0;
1426         int chipnum;
1427         unsigned long ofs;
1428 @@ -1142,8 +1299,8 @@
1429         ofs = to  - (chipnum << cfi->chipshift);
1430  
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)
1437                         local_len = len;
1438                 ret = cfi_intelext_write_words(mtd, to, local_len,
1439 @@ -1162,7 +1319,6 @@
1440                 }
1441         }
1442  
1443 -       /* Write buffer is worth it only if more than one word to write... */
1444         while(len) {
1445                 /* We must not cross write block boundaries */
1446                 int size = wbufsize - (ofs & (wbufsize-1));
1447 @@ -1189,102 +1345,11 @@
1448         return 0;
1449  }
1450  
1451 -typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
1452 -                             unsigned long adr, void *thunk);
1453 -
1454 -static int cfi_intelext_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
1455 -                                    loff_t ofs, size_t len, void *thunk)
1456 -{
1457 -       struct map_info *map = mtd->priv;
1458 -       struct cfi_private *cfi = map->fldrv_priv;
1459 -       unsigned long adr;
1460 -       int chipnum, ret = 0;
1461 -       int i, first;
1462 -       struct mtd_erase_region_info *regions = mtd->eraseregions;
1463 -
1464 -       if (ofs > mtd->size)
1465 -               return -EINVAL;
1466 -
1467 -       if ((len + ofs) > mtd->size)
1468 -               return -EINVAL;
1469 -
1470 -       /* Check that both start and end of the requested erase are
1471 -        * aligned with the erasesize at the appropriate addresses.
1472 -        */
1473 -
1474 -       i = 0;
1475 -
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.
1480 -       */
1481 -       
1482 -       while (i < mtd->numeraseregions && ofs >= regions[i].offset)
1483 -              i++;
1484 -       i--;
1485 -
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
1489 -          effect here.
1490 -       */
1491 -
1492 -       if (ofs & (regions[i].erasesize-1))
1493 -               return -EINVAL;
1494 -
1495 -       /* Remember the erase region we start on */
1496 -       first = i;
1497 -
1498 -       /* Next, check that the end of the requested erase is aligned
1499 -        * with the erase region at that address.
1500 -        */
1501 -
1502 -       while (i<mtd->numeraseregions && (ofs + len) >= regions[i].offset)
1503 -               i++;
1504 -
1505 -       /* As before, drop back one to point at the region in which
1506 -          the address actually falls
1507 -       */
1508 -       i--;
1509 -       
1510 -       if ((ofs + len) & (regions[i].erasesize-1))
1511 -               return -EINVAL;
1512 -
1513 -       chipnum = ofs >> cfi->chipshift;
1514 -       adr = ofs - (chipnum << cfi->chipshift);
1515 -
1516 -       i=first;
1517 -
1518 -       while(len) {
1519 -               ret = (*frob)(map, &cfi->chips[chipnum], adr, thunk);
1520 -               
1521 -               if (ret)
1522 -                       return ret;
1523 -
1524 -               adr += regions[i].erasesize;
1525 -               len -= regions[i].erasesize;
1526 -
1527 -               if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
1528 -                       i++;
1529 -
1530 -               if (adr >> cfi->chipshift) {
1531 -                       adr = 0;
1532 -                       chipnum++;
1533 -                       
1534 -                       if (chipnum >= cfi->numchips)
1535 -                       break;
1536 -               }
1537 -       }
1538 -
1539 -       return 0;
1540 -}
1541 -
1542 -
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)
1546  {
1547         struct cfi_private *cfi = map->fldrv_priv;
1548 -       cfi_word status, status_OK;
1549 +       map_word status, status_OK;
1550         unsigned long timeo;
1551         int retries = 3;
1552         DECLARE_WAITQUEUE(wait, current);
1553 @@ -1305,17 +1370,17 @@
1554  
1555         ENABLE_VPP(map);
1556         /* Clear the status register first */
1557 -       cfi_write(map, CMD(0x50), adr);
1558 +       map_write(map, CMD(0x50), adr);
1559  
1560         /* Now erase */
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;
1567  
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);
1574  
1575         /* FIXME. Use a timer to check this, and return immediately. */
1576 @@ -1340,19 +1405,19 @@
1577                         chip->erase_suspended = 0;
1578                 }
1579  
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))
1584                         break;
1585                 
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);
1600                         DISABLE_VPP(map);
1601                         spin_unlock(chip->mutex);
1602                         return -EIO;
1603 @@ -1369,43 +1434,46 @@
1604         ret = 0;
1605  
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);
1612  
1613         /* check for lock bit */
1614 -       if (status & CMD(0x3a)) {
1615 -               unsigned char chipstatus = status;
1616 -               if (status != CMD(status & 0xff)) {
1617 -                       int i;
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))) {
1623 +                       int i, w;
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);
1627 +                               }
1628                         }
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);
1632                 }
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);
1638                 
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);
1642                         ret = -EIO;
1643                 } else if (chipstatus & 0x02) {
1644                         /* Protection bit set */
1645                         ret = -EROFS;
1646                 } else if (chipstatus & 0x8) {
1647                         /* Voltage */
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);
1650                         ret = -EIO;
1651                 } else if (chipstatus & 0x20) {
1652                         if (retries--) {
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);
1658                                 goto retry;
1659                         }
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);
1662                         ret = -EIO;
1663                 }
1664         }
1665 @@ -1423,13 +1491,12 @@
1666         ofs = instr->addr;
1667         len = instr->len;
1668  
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);
1671         if (ret)
1672                 return ret;
1673  
1674         instr->state = MTD_ERASE_DONE;
1675 -       if (instr->callback)
1676 -               instr->callback(instr);
1677 +       mtd_erase_callback(instr);
1678         
1679         return 0;
1680  }
1681 @@ -1475,7 +1542,8 @@
1682  }
1683  
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)
1688  {
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);
1696 -       
1697 +       chip->state = FL_JEDEC_QUERY;
1698         return 0;
1699  }
1700  #endif
1701 @@ -1492,10 +1559,11 @@
1702  #define DO_XXLOCK_ONEBLOCK_LOCK                ((void *) 1)
1703  #define DO_XXLOCK_ONEBLOCK_UNLOCK      ((void *) 2)
1704  
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)
1708  {
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;
1713         int ret;
1714  
1715 @@ -1512,13 +1580,13 @@
1716         }
1717  
1718         ENABLE_VPP(map);
1719 -       cfi_write(map, CMD(0x60), adr);
1720 +       map_write(map, CMD(0x60), adr);
1721  
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;
1730         } else
1731                 BUG();
1732 @@ -1533,15 +1601,16 @@
1733         timeo = jiffies + (HZ*20);
1734         for (;;) {
1735  
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))
1740                         break;
1741                 
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]);
1750                         DISABLE_VPP(map);
1751                         spin_unlock(chip->mutex);
1752                         return -EIO;
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,
1758 -                                 ofs, len, 0);
1759 +       cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
1760 +               ofs, len, 0);
1761  #endif
1762  
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);
1767         
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,
1772 -                                 ofs, len, 0);
1773 +       printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
1774 +              __FUNCTION__, ret);
1775 +       cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
1776 +               ofs, len, 0);
1777  #endif
1778  
1779         return ret;
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,
1785 -                                 ofs, len, 0);
1786 +       cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
1787 +               ofs, len, 0);
1788  #endif
1789  
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);
1793         
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, 
1797 -                                 ofs, len, 0);
1798 +       printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
1799 +              __FUNCTION__, ret);
1800 +       cfi_varsize_frob(mtd, do_printlockstatus_oneblock, 
1801 +               ofs, len, 0);
1802  #endif
1803         
1804         return ret;
1805 @@ -1679,7 +1749,7 @@
1806                 
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;
1812                         wake_up(&chip->wq);
1813                 }
1814 @@ -1694,6 +1764,7 @@
1815         struct cfi_private *cfi = map->fldrv_priv;
1816         kfree(cfi->cmdset_priv);
1817         kfree(cfi->cfiq);
1818 +       kfree(cfi->chips[0].priv);
1819         kfree(cfi);
1820         kfree(mtd->eraseregions);
1821  }
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
1826 @@ -3,15 +3,21 @@
1827   *   AMD & Fujitsu Standard Vendor Command Set (ID 0x0002)
1828   *
1829   * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
1830 + * Copyright (C) 2004 Arcom Control Systems Ltd <linux@arcom.com>
1831   *
1832   * 2_by_8 routines added by Simon Munton
1833   *
1834 + * 4_by_16 work by Carolyn J. Smith
1835 + *
1836 + * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
1837 + *
1838   * This code is GPL
1839   *
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 $
1842   *
1843   */
1844  
1845 +#include <linux/config.h>
1846  #include <linux/module.h>
1847  #include <linux/types.h>
1848  #include <linux/kernel.h>
1849 @@ -24,17 +30,24 @@
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>
1858  
1859  #define AMD_BOOTLOC_BUG
1860 +#define FORCE_WORD_WRITE 0
1861 +
1862 +#define MAX_WORD_RETRIES 3
1863 +
1864 +#define MANUFACTURER_AMD       0x0001
1865 +#define MANUFACTURER_SST       0x00BF
1866 +#define SST49LF004B            0x0060
1867  
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 *);
1877 @@ -44,8 +57,11 @@
1878  static void cfi_amdstd_destroy(struct mtd_info *);
1879  
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 *);
1883  
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"
1887  
1888  static struct mtd_chip_driver cfi_amdstd_chipdrv = {
1889         .probe          = NULL, /* Not usable directly */
1890 @@ -55,50 +71,199 @@
1891  };
1892  
1893  
1894 +/* #define DEBUG_CFI_FEATURES */
1895 +
1896 +
1897 +#ifdef DEBUG_CFI_FEATURES
1898 +static void cfi_tell_features(struct cfi_pri_amdstd *extp)
1899 +{
1900 +       const char* erase_suspend[3] = {
1901 +               "Not supported", "Read only", "Read/write"
1902 +       };
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"
1907 +       };
1908 +
1909 +       printk("  Silicon revision: %d\n", extp->SiliconRevision >> 1);
1910 +       printk("  Address sensitive unlock: %s\n", 
1911 +              (extp->SiliconRevision & 1) ? "Not required" : "Required");
1912 +
1913 +       if (extp->EraseSuspend < ARRAY_SIZE(erase_suspend))
1914 +               printk("  Erase Suspend: %s\n", erase_suspend[extp->EraseSuspend]);
1915 +       else
1916 +               printk("  Erase Suspend: Unknown value %d\n", extp->EraseSuspend);
1917 +
1918 +       if (extp->BlkProt == 0)
1919 +               printk("  Block protection: Not supported\n");
1920 +       else
1921 +               printk("  Block protection: %d sectors per group\n", extp->BlkProt);
1922 +
1923 +
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");
1932 +       else
1933 +               printk("  Page mode: %d word page\n", extp->PageMode << 2);
1934 +
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);
1939 +
1940 +       if (extp->TopBottom < ARRAY_SIZE(top_bottom))
1941 +               printk("  Top/Bottom Boot Block: %s\n", top_bottom[extp->TopBottom]);
1942 +       else
1943 +               printk("  Top/Bottom Boot Block: Unknown value %d\n", extp->TopBottom);
1944 +}
1945 +#endif
1946 +
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)
1950 +{
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;
1956 +
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 */
1962 +               } else {
1963 +                       extp->TopBottom = 2;    /* bottom boot */
1964 +               }
1965 +       }
1966 +}
1967 +#endif
1968 +
1969 +static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
1970 +{
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;
1976 +       }
1977 +}
1978 +
1979 +static void fixup_use_secsi(struct mtd_info *mtd, void *param)
1980 +{
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;
1984 +}
1985 +
1986 +static void fixup_use_erase_chip(struct mtd_info *mtd, void *param)
1987 +{
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;
1993 +       }
1994 +       
1995 +}
1996 +
1997 +static struct cfi_fixup cfi_fixup_table[] = {
1998 +#ifdef AMD_BOOTLOC_BUG
1999 +       { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
2000 +#endif
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, },
2009 +#endif
2010 +       { 0, 0, NULL, NULL }
2011 +};
2012 +static struct cfi_fixup jedec_fixup_table[] = {
2013 +       { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },
2014 +       { 0, 0, NULL, NULL }
2015 +};
2016 +
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.
2022 +        */
2023 +       { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
2024 +       { 0, 0, NULL, NULL }
2025 +};
2026 +
2027 +
2028  struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
2029  {
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;
2034         int i;
2035 -       __u8 major, minor;
2036 -       __u32 base = cfi->chips[0].start;
2037 +
2038 +       mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
2039 +       if (!mtd) {
2040 +               printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
2041 +               return NULL;
2042 +       }
2043 +       memset(mtd, 0, sizeof(*mtd));
2044 +       mtd->priv = map;
2045 +       mtd->type = MTD_NORFLASH;
2046 +
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;
2056  
2057         if (cfi->cfi_mode==CFI_MODE_CFI){
2058 +               unsigned char bootloc;
2059 +               /* 
2060 +                * It's a real CFI chip, not one for which the probe
2061 +                * routine faked a CFI structure. So we read the feature
2062 +                * table from it.
2063 +                */
2064                 __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
2065 +               struct cfi_pri_amdstd *extp;
2066  
2067 -               cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
2068 -               
2069 -               major = cfi_read_query(map, base + (adr+3)*ofs_factor);
2070 -               minor = cfi_read_query(map, base + (adr+4)*ofs_factor);
2071 -               
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);
2075 -               
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");
2083 +               if (!extp) {
2084 +                       kfree(mtd);
2085 +                       return NULL;
2086 +               }
2087 +
2088 +               /* Install our own private info structure */
2089 +               cfi->cmdset_priv = extp;        
2090 +
2091 +               /* Apply cfi device specific fixups */
2092 +               cfi_fixup(mtd, cfi_fixup_table);
2093 +
2094 +#ifdef DEBUG_CFI_FEATURES
2095 +               /* Tell the user about it in lots of lovely detail */
2096 +               cfi_tell_features(extp);
2097 +#endif 
2098 +
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);
2103 +                       bootloc = 2;
2104 +               }
2105  
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 */
2113 -                       } else {
2114 -                               bootloc = 2;    /* bottom boot */
2115 -                       }
2116 -               } else
2117 -#endif
2118 -                       {
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);
2121 -                       }
2122                 if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) {
2123                         printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name);
2124                         
2125 @@ -112,32 +277,50 @@
2126                         }
2127                 }
2128                 /*
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.
2133                  */
2134 -               switch (cfi->device_type) {
2135 -               case CFI_DEVICETYPE_X8:
2136 -                       cfi->addr_unlock1 = 0x555; 
2137 -                       cfi->addr_unlock2 = 0x2aa; 
2138 -                       break;
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;
2144 -                       } else {
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; 
2151 +                               break;
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;
2157 +                               } else {
2158 +                                       cfi->addr_unlock2 = 0x554;
2159 +                               }
2160 +                               break;
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;
2166 +                               } else {
2167 +                                       cfi->addr_unlock2 = 0xaa8; 
2168 +                               }
2169 +                               break;
2170 +                       default:
2171 +                               printk(KERN_WARNING
2172 +                                      "MTD %s(): Unsupported device type %d\n",
2173 +                                      __func__, cfi->device_type);
2174 +                               kfree(mtd);
2175 +                               kfree(extp);
2176 +                               return NULL;
2177                         }
2178 -                       break;
2179 -               case CFI_DEVICETYPE_X32:
2180 -                       cfi->addr_unlock1 = 0x1555; 
2181 -                       cfi->addr_unlock2 = 0xaaa; 
2182 -                       break;
2183 -               default:
2184 -                       printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0002 device type %d\n", cfi->device_type);
2185 -                       return NULL;
2186                 }
2187 +
2188         } /* CFI mode */
2189 +       else if (cfi->cfi_mode == CFI_MODE_JEDEC) {
2190 +               /* Apply jedec specific fixups */
2191 +               cfi_fixup(mtd, jedec_fixup_table);
2192 +       }
2193 +       /* Apply generic fixups */
2194 +       cfi_fixup(mtd, fixup_table);
2195  
2196         for (i=0; i< cfi->numchips; i++) {
2197                 cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
2198 @@ -146,135 +329,66 @@
2199         }               
2200         
2201         map->fldrv = &cfi_amdstd_chipdrv;
2202 -
2203 -       cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL);
2204 -       return cfi_amdstd_setup(map);
2205 +       
2206 +       return cfi_amdstd_setup(mtd);
2207  }
2208  
2209 -static struct mtd_info *cfi_amdstd_setup(struct map_info *map)
2210 +
2211 +static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
2212  {
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;
2218 +       int i,j;
2219  
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;
2226  
2227 -       if (!mtd) {
2228 -         printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
2229 -         goto setup_err;
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");
2235 +               goto setup_err;
2236         }
2237 -
2238 -       memset(mtd, 0, sizeof(*mtd));
2239 -       mtd->priv = map;
2240 -       mtd->type = MTD_NORFLASH;
2241 -       /* Also select the correct geometry setup too */ 
2242 -       mtd->size = devsize * cfi->numchips;
2243 -       
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;
2247 -       } else {
2248 -               unsigned long offset = 0;
2249 -               int i,j;
2250 -
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");
2255 -                       goto setup_err;
2256 -               }
2257                         
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;
2266                         
2267 -                       if (mtd->erasesize < ersize) {
2268 -                               mtd->erasesize = ersize;
2269 -                       }
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;
2274 -                       }
2275 -                       offset += (ersize * ernum);
2276 -               }
2277 -               if (offset != devsize) {
2278 -                       /* Argh */
2279 -                       printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
2280 -                       goto setup_err;
2281 +               if (mtd->erasesize < ersize) {
2282 +                       mtd->erasesize = ersize;
2283                 }
2284 -#if 0
2285 -               // debug
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);
2291 -               }
2292 -#endif
2293 -       }
2294 -
2295 -       switch (CFIDEV_BUSWIDTH)
2296 -       {
2297 -       case 1:
2298 -       case 2:
2299 -       case 4:
2300 -#if 1
2301 -               if (mtd->numeraseregions > 1)
2302 -                       mtd->erase = cfi_amdstd_erase_varsize;
2303 -               else
2304 -#endif
2305 -               if (((cfi->cfiq->EraseRegionInfo[0] & 0xffff) + 1) == 1)
2306 -                       mtd->erase = cfi_amdstd_erase_chip;
2307 -               else
2308 -                       mtd->erase = cfi_amdstd_erase_onesize;
2309 -               mtd->read = cfi_amdstd_read;
2310 -               mtd->write = cfi_amdstd_write;
2311 -               break;
2312 -
2313 -       default:
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;
2319 +               }
2320 +               offset += (ersize * ernum);
2321 +       }
2322 +       if (offset != devsize) {
2323 +               /* Argh */
2324 +               printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
2325                 goto setup_err;
2326 -               break;
2327         }
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;
2335 +#if 0
2336 +       // debug
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);
2342         }
2343 +#endif
2344  
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");
2348  
2349 -        /* does this chip have a secsi area? */
2350 -       if(cfi->mfr==1){
2351 -               
2352 -               switch(cfi->id){
2353 -               case 0x50:
2354 -               case 0x53:
2355 -               case 0x55:
2356 -               case 0x56:
2357 -               case 0x5C:
2358 -               case 0x5F:
2359 -                       /* Yes */
2360 -                       mtd->read_user_prot_reg = cfi_amdstd_secsi_read;
2361 -                       mtd->read_fact_prot_reg = cfi_amdstd_secsi_read;
2362 -               default:                       
2363 -                       ;
2364 -               }
2365 -       }
2366 -       
2367 -               
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);
2375         return mtd;
2376  
2377 @@ -289,46 +403,182 @@
2378         return NULL;
2379  }
2380  
2381 -static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
2382 +/*
2383 + * Return true if the chip is ready.
2384 + *
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.
2387 + *
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).
2392 + */
2393 +static int chip_ready(struct map_info *map, unsigned long addr)
2394 +{
2395 +       map_word d, t;
2396 +
2397 +       d = map_read(map, addr);
2398 +       t = map_read(map, addr);
2399 +
2400 +       return map_word_equal(map, d, t);
2401 +}
2402 +
2403 +static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
2404  {
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;
2410  
2411 + resettime:
2412 +       timeo = jiffies + HZ;
2413   retry:
2414 -       cfi_spin_lock(chip->mutex);
2415 +       switch (chip->state) {
2416  
2417 -       if (chip->state != FL_READY){
2418 -#if 0
2419 -               printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state);
2420 -#endif
2421 +       case FL_STATUS:
2422 +               for (;;) {
2423 +                       if (chip_ready(map, adr))
2424 +                               break;
2425 +
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);
2429 +                               return -EIO;
2430 +                       }
2431 +                       cfi_spin_unlock(chip->mutex);
2432 +                       cfi_udelay(1);
2433 +                       cfi_spin_lock(chip->mutex);
2434 +                       /* Someone else might have been playing with it. */
2435 +                       goto retry;
2436 +               }
2437 +                               
2438 +       case FL_READY:
2439 +       case FL_CFI_QUERY:
2440 +       case FL_JEDEC_QUERY:
2441 +               return 0;
2442 +
2443 +       case FL_ERASING:
2444 +               if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */
2445 +                       goto sleep;
2446 +
2447 +               if (!(mode == FL_READY || mode == FL_POINT
2448 +                     || !cfip
2449 +                     || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))
2450 +                     || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1))))
2451 +                       goto sleep;
2452 +
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. */
2456 +
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;
2464 +               for (;;) {
2465 +                       if (chip_ready(map, adr))
2466 +                               break;
2467 +
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__);
2478 +                               return -EIO;
2479 +                       }
2480 +                       
2481 +                       cfi_spin_unlock(chip->mutex);
2482 +                       cfi_udelay(1);
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. */
2486 +               }
2487 +               chip->state = FL_READY;
2488 +               return 0;
2489 +
2490 +       case FL_POINT:
2491 +               /* Only if there's no operation suspended... */
2492 +               if (mode == FL_READY && chip->oldstate == FL_READY)
2493 +                       return 0;
2494 +
2495 +       default:
2496 +       sleep:
2497                 set_current_state(TASK_UNINTERRUPTIBLE);
2498                 add_wait_queue(&chip->wq, &wait);
2499 -                
2500                 cfi_spin_unlock(chip->mutex);
2501 -
2502                 schedule();
2503                 remove_wait_queue(&chip->wq, &wait);
2504 -#if 0
2505 -               if(signal_pending(current))
2506 -                       return -EINTR;
2507 -#endif
2508 -               timeo = jiffies + HZ;
2509 +               cfi_spin_lock(chip->mutex);
2510 +               goto resettime;
2511 +       }
2512 +}
2513  
2514 -               goto retry;
2515 -       }       
2516 +
2517 +static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr)
2518 +{
2519 +       struct cfi_private *cfi = map->fldrv_priv;
2520 +
2521 +       switch(chip->oldstate) {
2522 +       case FL_ERASING:
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;
2527 +               break;
2528 +
2529 +       case FL_READY:
2530 +       case FL_STATUS:
2531 +               /* We should really make set_vpp() count, rather than doing this */
2532 +               DISABLE_VPP(map);
2533 +               break;
2534 +       default:
2535 +               printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate);
2536 +       }
2537 +       wake_up(&chip->wq);
2538 +}
2539 +
2540 +
2541 +static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
2542 +{
2543 +       unsigned long cmd_addr;
2544 +       struct cfi_private *cfi = map->fldrv_priv;
2545 +       int ret;
2546  
2547         adr += chip->start;
2548  
2549 -       chip->state = FL_READY;
2550 +       /* Ensure cmd read/writes are aligned. */ 
2551 +       cmd_addr = adr & ~(map_bankwidth(map)-1); 
2552 +
2553 +       cfi_spin_lock(chip->mutex);
2554 +       ret = get_chip(map, chip, cmd_addr, FL_READY);
2555 +       if (ret) {
2556 +               cfi_spin_unlock(chip->mutex);
2557 +               return ret;
2558 +       }
2559 +
2560 +       if (chip->state != FL_POINT && chip->state != FL_READY) {
2561 +               map_write(map, CMD(0xf0), cmd_addr);
2562 +               chip->state = FL_READY;
2563 +       }
2564  
2565         map_copy_from(map, buf, adr, len);
2566  
2567 -       wake_up(&chip->wq);
2568 -       cfi_spin_unlock(chip->mutex);
2569 +       put_chip(map, chip, cmd_addr);
2570  
2571 +       cfi_spin_unlock(chip->mutex);
2572         return 0;
2573  }
2574  
2575 +
2576  static int cfi_amdstd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
2577  {
2578         struct map_info *map = mtd->priv;
2579 @@ -370,6 +620,7 @@
2580         return ret;
2581  }
2582  
2583 +
2584  static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
2585  {
2586         DECLARE_WAITQUEUE(wait, current);
2587 @@ -381,11 +632,11 @@
2588  
2589         if (chip->state != FL_READY){
2590  #if 0
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);
2593  #endif
2594                 set_current_state(TASK_UNINTERRUPTIBLE);
2595                 add_wait_queue(&chip->wq, &wait);
2596 -                
2597 +               
2598                 cfi_spin_unlock(chip->mutex);
2599  
2600                 schedule();
2601 @@ -402,13 +653,15 @@
2602         adr += chip->start;
2603  
2604         chip->state = FL_READY;
2605 -       
2606 +
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);
2611         
2612         map_copy_from(map, buf, adr, len);
2613  
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 @@
2619         return ret;
2620  }
2621  
2622 -static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, cfi_word datum, int fast)
2623 +
2624 +static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum)
2625  {
2626 -       unsigned long timeo = jiffies + HZ;
2627 -       unsigned int oldstatus, status, prev_oldstatus, prev_status;
2628 -       unsigned int dq6;
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;
2641 +       /*
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.
2649 +        */
2650 +       unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
2651         int ret = 0;
2652 -       int ta = 0;
2653 +       map_word oldd, curd;
2654 +       int retry_cnt = 0;
2655  
2656 +       adr += chip->start;
2657 +
2658 +       cfi_spin_lock(chip->mutex);
2659 +       ret = get_chip(map, chip, adr, FL_WRITING);
2660 +       if (ret) {
2661 +               cfi_spin_unlock(chip->mutex);
2662 +               return ret;
2663 +       }
2664 +
2665 +       DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
2666 +              __func__, adr, datum.x[0] );
2667 +
2668 +       /*
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.
2673 +        */
2674 +       oldd = map_read(map, adr);
2675 +       if (map_word_equal(map, oldd, datum)) {
2676 +               DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n",
2677 +                      __func__);
2678 +               goto op_done;
2679 +       }
2680 +
2681 +       ENABLE_VPP(map);
2682   retry:
2683 +       /*
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.
2690 +        */
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;
2696 +
2697 +       cfi_spin_unlock(chip->mutex);
2698 +       cfi_udelay(chip->word_write_time);
2699         cfi_spin_lock(chip->mutex);
2700  
2701 -       if (chip->state != FL_READY) {
2702 +       /* See comment above for timeout value. */
2703 +       timeo = jiffies + uWriteTimeout; 
2704 +       for (;;) {
2705 +               if (chip->state != FL_WRITING) {
2706 +                       /* Someone's suspended the write. Sleep */
2707 +                       DECLARE_WAITQUEUE(wait, current);
2708 +
2709 +                       set_current_state(TASK_UNINTERRUPTIBLE);
2710 +                       add_wait_queue(&chip->wq, &wait);
2711 +                       cfi_spin_unlock(chip->mutex);
2712 +                       schedule();
2713 +                       remove_wait_queue(&chip->wq, &wait);
2714 +                       timeo = jiffies + (HZ / 2); /* FIXME */
2715 +                       cfi_spin_lock(chip->mutex);
2716 +                       continue;
2717 +               }
2718 +
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)) {
2725 +                               goto op_done;
2726 +                       }
2727 +                       /* Nope something has gone wrong. */
2728 +                       break;
2729 +               }
2730 +
2731 +               if (time_after(jiffies, timeo)) {
2732 +                       printk(KERN_WARNING "MTD %s(): software timeout\n",
2733 +                               __func__ );
2734 +                       break;
2735 +               }
2736 +
2737 +               /* Latency issues. Drop the lock, wait a while and retry */
2738 +               cfi_spin_unlock(chip->mutex);
2739 +               cfi_udelay(1);
2740 +               cfi_spin_lock(chip->mutex);
2741 +       }
2742 +
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) 
2747 +               goto retry;
2748 +
2749 +       ret = -EIO;
2750 + op_done:
2751 +       chip->state = FL_READY;
2752 +       put_chip(map, chip, adr);
2753 +       cfi_spin_unlock(chip->mutex);
2754 +
2755 +       return ret;
2756 +}
2757 +
2758 +
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)
2761 +{
2762 +       struct map_info *map = mtd->priv;
2763 +       struct cfi_private *cfi = map->fldrv_priv;
2764 +       int ret = 0;
2765 +       int chipnum;
2766 +       unsigned long ofs, chipstart;
2767 +       DECLARE_WAITQUEUE(wait, current);
2768 +
2769 +       *retlen = 0;
2770 +       if (!len)
2771 +               return 0;
2772 +
2773 +       chipnum = to >> cfi->chipshift;
2774 +       ofs = to  - (chipnum << cfi->chipshift);
2775 +       chipstart = cfi->chips[chipnum].start;
2776 +
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;
2781 +               int n = 0;
2782 +               map_word tmp_buf;
2783 +
2784 + retry:
2785 +               cfi_spin_lock(cfi->chips[chipnum].mutex);
2786 +
2787 +               if (cfi->chips[chipnum].state != FL_READY) {
2788  #if 0
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);
2791  #endif
2792 -               set_current_state(TASK_UNINTERRUPTIBLE);
2793 -               add_wait_queue(&chip->wq, &wait);
2794 -                
2795 -               cfi_spin_unlock(chip->mutex);
2796 +                       set_current_state(TASK_UNINTERRUPTIBLE);
2797 +                       add_wait_queue(&cfi->chips[chipnum].wq, &wait);
2798  
2799 -               schedule();
2800 -               remove_wait_queue(&chip->wq, &wait);
2801 +                       cfi_spin_unlock(cfi->chips[chipnum].mutex);
2802 +
2803 +                       schedule();
2804 +                       remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
2805  #if 0
2806 -               printk(KERN_DEBUG "Wake up to write:\n");
2807 -               if(signal_pending(current))
2808 -                       return -EINTR;
2809 +                       if(signal_pending(current))
2810 +                               return -EINTR;
2811  #endif
2812 -               timeo = jiffies + HZ;
2813 +                       goto retry;
2814 +               }
2815  
2816 -               goto retry;
2817 -       }       
2818 +               /* Load 'tmp_buf' with old contents of flash */
2819 +               tmp_buf = map_read(map, bus_ofs+chipstart);
2820  
2821 -       chip->state = FL_WRITING;
2822 +               cfi_spin_unlock(cfi->chips[chipnum].mutex);
2823 +
2824 +               /* Number of bytes to copy from buffer */
2825 +               n = min_t(int, len, map_bankwidth(map)-i);
2826 +               
2827 +               tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);
2828 +
2829 +               ret = do_write_oneword(map, &cfi->chips[chipnum], 
2830 +                                      bus_ofs, tmp_buf);
2831 +               if (ret) 
2832 +                       return ret;
2833 +               
2834 +               ofs += n;
2835 +               buf += n;
2836 +               (*retlen) += n;
2837 +               len -= n;
2838 +
2839 +               if (ofs >> cfi->chipshift) {
2840 +                       chipnum ++; 
2841 +                       ofs = 0;
2842 +                       if (chipnum == cfi->numchips)
2843 +                               return 0;
2844 +               }
2845 +       }
2846 +       
2847 +       /* We are now aligned, write as much as possible */
2848 +       while(len >= map_bankwidth(map)) {
2849 +               map_word datum;
2850 +
2851 +               datum = map_word_load(map, buf);
2852 +
2853 +               ret = do_write_oneword(map, &cfi->chips[chipnum],
2854 +                                      ofs, datum);
2855 +               if (ret)
2856 +                       return ret;
2857 +
2858 +               ofs += map_bankwidth(map);
2859 +               buf += map_bankwidth(map);
2860 +               (*retlen) += map_bankwidth(map);
2861 +               len -= map_bankwidth(map);
2862 +
2863 +               if (ofs >> cfi->chipshift) {
2864 +                       chipnum ++; 
2865 +                       ofs = 0;
2866 +                       if (chipnum == cfi->numchips)
2867 +                               return 0;
2868 +                       chipstart = cfi->chips[chipnum].start;
2869 +               }
2870 +       }
2871 +
2872 +       /* Write the trailing bytes if any */
2873 +       if (len & (map_bankwidth(map)-1)) {
2874 +               map_word tmp_buf;
2875 +
2876 + retry1:
2877 +               cfi_spin_lock(cfi->chips[chipnum].mutex);
2878 +
2879 +               if (cfi->chips[chipnum].state != FL_READY) {
2880 +#if 0
2881 +                       printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
2882 +#endif
2883 +                       set_current_state(TASK_UNINTERRUPTIBLE);
2884 +                       add_wait_queue(&cfi->chips[chipnum].wq, &wait);
2885 +
2886 +                       cfi_spin_unlock(cfi->chips[chipnum].mutex);
2887 +
2888 +                       schedule();
2889 +                       remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
2890 +#if 0
2891 +                       if(signal_pending(current))
2892 +                               return -EINTR;
2893 +#endif
2894 +                       goto retry1;
2895 +               }
2896 +
2897 +               tmp_buf = map_read(map, ofs + chipstart);
2898 +
2899 +               cfi_spin_unlock(cfi->chips[chipnum].mutex);
2900 +
2901 +               tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);
2902 +       
2903 +               ret = do_write_oneword(map, &cfi->chips[chipnum], 
2904 +                               ofs, tmp_buf);
2905 +               if (ret) 
2906 +                       return ret;
2907 +               
2908 +               (*retlen) += len;
2909 +       }
2910 +
2911 +       return 0;
2912 +}
2913 +
2914 +
2915 +/*
2916 + * FIXME: interleaved mode not tested, and probably not supported!
2917 + */
2918 +static inline int do_write_buffer(struct map_info *map, struct flchip *chip, 
2919 +                                 unsigned long adr, const u_char *buf, int len)
2920 +{
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;
2925 +       int ret = -EIO;
2926 +       unsigned long cmd_adr;
2927 +       int z, words;
2928 +       map_word datum;
2929  
2930         adr += chip->start;
2931 -       DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8x)\n",
2932 -              __func__, adr, datum );
2933 +       cmd_adr = adr;
2934  
2935 -       ENABLE_VPP(map);
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);
2940 +       if (ret) {
2941 +               cfi_spin_unlock(chip->mutex);
2942 +               return ret;
2943         }
2944 -       else {
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);
2948 +
2949 +       datum = map_word_load(map, buf);
2950 +
2951 +       DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
2952 +              __func__, adr, datum.x[0] );
2953 +
2954 +       ENABLE_VPP(map);
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);
2958 +
2959 +       /* Write Buffer Load */
2960 +       map_write(map, CMD(0x25), cmd_adr);
2961 +
2962 +       chip->state = FL_WRITING_TO_BUFFER;
2963 +
2964 +       /* Write length of data to come */
2965 +       words = len / map_bankwidth(map);
2966 +       map_write(map, CMD(words - 1), cmd_adr);
2967 +       /* Write data */
2968 +       z = 0;
2969 +       while(z < words * map_bankwidth(map)) {
2970 +               datum = map_word_load(map, buf);
2971 +               map_write(map, datum, adr + z);
2972 +
2973 +               z += map_bankwidth(map);
2974 +               buf += map_bankwidth(map);
2975         }
2976 -       cfi_write(map, datum, adr);
2977 +       z -= map_bankwidth(map);
2978 +
2979 +       adr += z;
2980 +
2981 +       /* Write Buffer Program Confirm: GO GO GO */
2982 +       map_write(map, CMD(0x29), cmd_adr);
2983 +       chip->state = FL_WRITING;
2984  
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);
2989  
2990 -       /*
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.
2994 -        *
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.
3013 -        *
3014 -        * - Thayne Harbaugh
3015 -        */
3016 -       dq6 = CMD(1<<6);
3017 -       /* See comment above for timeout value. */
3018         timeo = jiffies + uWriteTimeout; 
3019 -               
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 );
3024 -
3025 -       /*
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.
3037 -        *
3038 -        * If our timeout occurs _then_ we will check dq5 to see
3039 -        * if the device also had an internal timeout.
3040 -        */
3041 -       while( ( ( status ^ oldstatus ) & dq6 )
3042 -              && ! ( ta = time_after(jiffies, timeo) ) ) {
3043 +               
3044 +       for (;;) {
3045 +               if (chip->state != FL_WRITING) {
3046 +                       /* Someone's suspended the write. Sleep */
3047 +                       DECLARE_WAITQUEUE(wait, current);
3048  
3049 -               if (need_resched()) {
3050 +                       set_current_state(TASK_UNINTERRUPTIBLE);
3051 +                       add_wait_queue(&chip->wq, &wait);
3052                         cfi_spin_unlock(chip->mutex);
3053 -                       yield();
3054 +                       schedule();
3055 +                       remove_wait_queue(&chip->wq, &wait);
3056 +                       timeo = jiffies + (HZ / 2); /* FIXME */
3057                         cfi_spin_lock(chip->mutex);
3058 -               } else 
3059 -                       udelay(1);
3060 +                       continue;
3061 +               }
3062  
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 );
3067 -       }
3068 +               if (chip_ready(map, adr))
3069 +                       goto op_done;
3070 +                   
3071 +               if( time_after(jiffies, timeo))
3072 +                       break;
3073  
3074 -       /*
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.
3086 -        */
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 );
3093 -
3094 -       if ( oldstatus == datum && status == datum ) {
3095 -               /* success - do nothing */
3096 -               goto write_done;
3097 -       }
3098 -
3099 -       if ( ta ) {
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",
3105 -                               __func__,
3106 -                               status & dq5mask );
3107 -               } else {
3108 -                       printk( KERN_WARNING
3109 -                               "MTD %s(): Software timed out during write.\n",
3110 -                               __func__ );
3111 -               }
3112 -               goto write_failed;
3113 +               /* Latency issues. Drop the lock, wait a while and retry */
3114 +               cfi_spin_unlock(chip->mutex);
3115 +               cfi_udelay(1);
3116 +               cfi_spin_lock(chip->mutex);
3117         }
3118  
3119 -       /*
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.
3123 -        */
3124 -       printk(KERN_WARNING
3125 -              "MTD %s(): Wacky!  Unable to decode failure status\n",
3126 +       printk(KERN_WARNING "MTD %s(): software timeout\n",
3127                __func__ );
3128  
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);
3134 -
3135 - write_failed:
3136 -       ret = -EIO;
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 */
3141  
3142 - write_done:
3143 -       DISABLE_VPP(map);
3144 +       ret = -EIO;
3145 + op_done:
3146         chip->state = FL_READY;
3147 -       wake_up(&chip->wq);
3148 +       put_chip(map, chip, adr);
3149         cfi_spin_unlock(chip->mutex);
3150  
3151         return ret;
3152  }
3153  
3154 -static int cfi_amdstd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
3155 +
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)
3158  {
3159         struct map_info *map = mtd->priv;
3160         struct cfi_private *cfi = map->fldrv_priv;
3161 +       int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
3162         int ret = 0;
3163         int chipnum;
3164 -       unsigned long ofs, chipstart;
3165 +       unsigned long ofs;
3166  
3167         *retlen = 0;
3168         if (!len)
3169 @@ -679,176 +1105,94 @@
3170  
3171         chipnum = to >> cfi->chipshift;
3172         ofs = to  - (chipnum << cfi->chipshift);
3173 -       chipstart = cfi->chips[chipnum].start;
3174 -
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;
3179 -               int n = 0;
3180 -               u_char tmp_buf[8];
3181 -               cfi_word datum;
3182 -
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--;
3186 -
3187 -               if (cfi_buswidth_is_2()) {
3188 -                       datum = *(__u16*)tmp_buf;
3189 -               } else if (cfi_buswidth_is_4()) {
3190 -                       datum = *(__u32*)tmp_buf;
3191 -               } else {
3192 -                       return -EINVAL;  /* should never happen, but be safe */
3193 -               }
3194  
3195 -               ret = do_write_oneword(map, &cfi->chips[chipnum], 
3196 -                                      bus_ofs, datum, 0);
3197 -               if (ret) 
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)
3202 +                       local_len = len;
3203 +               ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<<cfi->chipshift),
3204 +                                            local_len, retlen, buf);
3205 +               if (ret)
3206                         return ret;
3207 -               
3208 -               ofs += n;
3209 -               buf += n;
3210 -               (*retlen) += n;
3211 +               ofs += local_len;
3212 +               buf += local_len;
3213 +               len -= local_len;
3214  
3215                 if (ofs >> cfi->chipshift) {
3216 -                       chipnum ++; 
3217 +                       chipnum ++;
3218                         ofs = 0;
3219                         if (chipnum == cfi->numchips)
3220                                 return 0;
3221                 }
3222         }
3223 -       
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);
3229 -       }
3230  
3231 -       /* We are now aligned, write as much as possible */
3232 -       while(len >= CFIDEV_BUSWIDTH) {
3233 -               cfi_word datum;
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));
3238 +
3239 +               if (size > len)
3240 +                       size = len;
3241 +               if (size % map_bankwidth(map))
3242 +                       size -= size % map_bankwidth(map);
3243  
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;
3250 -               } else {
3251 -                       return -EINVAL;
3252 -               }
3253 -               ret = do_write_oneword(map, &cfi->chips[chipnum],
3254 -                                      ofs, datum, cfi->fast_prog);
3255 -               if (ret) {
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);
3260 -                       }
3261 +               ret = do_write_buffer(map, &cfi->chips[chipnum], 
3262 +                                     ofs, buf, size);
3263 +               if (ret)
3264                         return ret;
3265 -               }
3266  
3267 -               ofs += CFIDEV_BUSWIDTH;
3268 -               buf += CFIDEV_BUSWIDTH;
3269 -               (*retlen) += CFIDEV_BUSWIDTH;
3270 -               len -= CFIDEV_BUSWIDTH;
3271 +               ofs += size;
3272 +               buf += size;
3273 +               (*retlen) += size;
3274 +               len -= size;
3275  
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);
3281 -                       }
3282 -
3283                         chipnum ++; 
3284                         ofs = 0;
3285                         if (chipnum == cfi->numchips)
3286                                 return 0;
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);
3293 -                       }
3294                 }
3295         }
3296  
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);
3301 -       }
3302 +       if (len) {
3303 +               size_t retlen_dregs = 0;
3304  
3305 -       /* Write the trailing bytes if any */
3306 -       if (len & (CFIDEV_BUSWIDTH-1)) {
3307 -               int i = 0, n = 0;
3308 -               u_char tmp_buf[8];
3309 -               cfi_word datum;
3310 -
3311 -               map_copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
3312 -               while (len--)
3313 -                       tmp_buf[i++] = buf[n++];
3314 -
3315 -               if (cfi_buswidth_is_2()) {
3316 -                       datum = *(__u16*)tmp_buf;
3317 -               } else if (cfi_buswidth_is_4()) {
3318 -                       datum = *(__u32*)tmp_buf;
3319 -               } else {
3320 -                       return -EINVAL;  /* should never happen, but be safe */
3321 -               }
3322 +               ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<<cfi->chipshift),
3323 +                                            len, &retlen_dregs, buf);
3324  
3325 -               ret = do_write_oneword(map, &cfi->chips[chipnum], 
3326 -                               ofs, datum, 0);
3327 -               if (ret) 
3328 -                       return ret;
3329 -               
3330 -               (*retlen) += n;
3331 +               *retlen += retlen_dregs;
3332 +               return ret;
3333         }
3334  
3335         return 0;
3336  }
3337  
3338 +
3339 +/*
3340 + * Handle devices with one erase region, that only implement
3341 + * the chip erase command.
3342 + */
3343  static inline int do_erase_chip(struct map_info *map, struct flchip *chip)
3344  {
3345 -       unsigned int oldstatus, status, prev_oldstatus, prev_status;
3346 -       unsigned int dq6;
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);
3352         int ret = 0;
3353 -       int ta = 0;
3354 -       cfi_word ones = 0;
3355  
3356 - retry:
3357 -       cfi_spin_lock(chip->mutex);
3358 +       adr = cfi->addr_unlock1;
3359  
3360 -       if (chip->state != FL_READY){
3361 -               set_current_state(TASK_UNINTERRUPTIBLE);
3362 -               add_wait_queue(&chip->wq, &wait);
3363 -                
3364 +       cfi_spin_lock(chip->mutex);
3365 +       ret = get_chip(map, chip, adr, FL_WRITING);
3366 +       if (ret) {
3367                 cfi_spin_unlock(chip->mutex);
3368 +               return ret;
3369 +       }
3370  
3371 -               schedule();
3372 -               remove_wait_queue(&chip->wq, &wait);
3373 -#if 0
3374 -               if(signal_pending(current))
3375 -                       return -EINTR;
3376 -#endif
3377 -               timeo = jiffies + HZ;
3378 -
3379 -               goto retry;
3380 -       }       
3381 -
3382 -       chip->state = FL_ERASING;
3383         DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
3384                __func__, chip->start );
3385 -       
3386 -       /* Handle devices with one erase region, that only implement
3387 -        * the chip erase command.
3388 -        */
3389 +
3390         ENABLE_VPP(map);
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;
3399  
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.
3404 -        *
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.
3408 -        */
3409 -       /* see comments in do_write_oneword */
3410 -       dq6 = CMD(1<<6);
3411 +       chip->state = FL_ERASING;
3412 +       chip->erase_suspended = 0;
3413 +       chip->in_progress_block_addr = adr;
3414  
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 );
3419 -
3420 -       while( ( ( status ^ oldstatus ) & dq6 )
3421 -              && ! ( ta = time_after(jiffies, timeo) ) ) {
3422 -               int wait_reps;
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);
3427  
3428 -               /* an initial short sleep */
3429 -               cfi_spin_unlock(chip->mutex);
3430 -               schedule_timeout(HZ/100);
3431 -               cfi_spin_lock(chip->mutex);
3432 -               
3433 +       timeo = jiffies + (HZ*20);
3434 +
3435 +       for (;;) {
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);
3440 -                       
3441                         cfi_spin_unlock(chip->mutex);
3442 -                       printk("erase suspended. Sleeping\n");
3443 -                       
3444                         schedule();
3445                         remove_wait_queue(&chip->wq, &wait);
3446 -#if 0                  
3447 -                       if (signal_pending(current))
3448 -                               return -EINTR;
3449 -#endif                 
3450 -                       timeo = jiffies + (HZ*2); /* FIXME */
3451                         cfi_spin_lock(chip->mutex);
3452                         continue;
3453                 }
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;
3459 +               }
3460  
3461 -               /* Busy wait for 1/10 of a milisecond */
3462 -               for(wait_reps = 0;
3463 -                   (wait_reps < 100)
3464 -                           && ( ( status ^ oldstatus ) & dq6 );
3465 -                   wait_reps++) {
3466 -                       
3467 -                       /* Latency issues. Drop the lock, wait a while and retry */
3468 -                       cfi_spin_unlock(chip->mutex);
3469 -
3470 -                       cfi_udelay(1);
3471 +               if (chip_ready(map, adr))
3472 +                       goto op_done;
3473  
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 );
3479 -               }
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 );
3484 -       }
3485 -
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 );
3492 -
3493 -       if ( cfi_buswidth_is_1() ) {
3494 -               ones =  (__u8)~0;
3495 -       } else if ( cfi_buswidth_is_2() ) {
3496 -               ones = (__u16)~0;
3497 -       } else if ( cfi_buswidth_is_4() ) {
3498 -               ones = (__u32)~0;
3499 -       } else {
3500 -               printk(KERN_WARNING "Unsupported buswidth\n");
3501 -               goto erase_failed;
3502 -       }
3503 -       
3504 -       if ( oldstatus == ones && status == ones ) {
3505 -               /* success - do nothing */
3506 -               goto erase_done;
3507 -       }
3508 +               if (time_after(jiffies, timeo))
3509 +                       break;
3510  
3511 -       if ( ta ) {
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",
3517 -                               __func__,
3518 -                               status & dq5mask );
3519 -               } else {
3520 -                       printk( KERN_WARNING
3521 -                               "MTD %s(): Software timed out during write.\n",
3522 -                               __func__ );
3523 -               }
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);
3530         }
3531  
3532 -       printk(KERN_WARNING
3533 -              "MTD %s(): Wacky!  Unable to decode failure status\n",
3534 +       printk(KERN_WARNING "MTD %s(): software timeout\n",
3535                __func__ );
3536  
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);
3542 -
3543 - erase_failed:
3544 -       ret = -EIO;
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 */
3549  
3550 - erase_done:
3551 -       DISABLE_VPP(map);
3552 +       ret = -EIO;
3553 + op_done:
3554         chip->state = FL_READY;
3555 -       wake_up(&chip->wq);
3556 +       put_chip(map, chip, adr);
3557         cfi_spin_unlock(chip->mutex);
3558 +
3559         return ret;
3560  }
3561  
3562  
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)
3565  {
3566 -       unsigned int oldstatus, status, prev_oldstatus, prev_status;
3567 -       unsigned int dq6;
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);
3572         int ret = 0;
3573 -       int ta = 0;
3574 -       cfi_word ones = 0;
3575  
3576 - retry:
3577 -       cfi_spin_lock(chip->mutex);
3578 +       adr += chip->start;
3579  
3580 -       if (chip->state != FL_READY){
3581 -               set_current_state(TASK_UNINTERRUPTIBLE);
3582 -               add_wait_queue(&chip->wq, &wait);
3583 -                
3584 +       cfi_spin_lock(chip->mutex);
3585 +       ret = get_chip(map, chip, adr, FL_ERASING);
3586 +       if (ret) {
3587                 cfi_spin_unlock(chip->mutex);
3588 +               return ret;
3589 +       }
3590  
3591 -               schedule();
3592 -               remove_wait_queue(&chip->wq, &wait);
3593 -#if 0
3594 -               if(signal_pending(current))
3595 -                       return -EINTR;
3596 -#endif
3597 -               timeo = jiffies + HZ;
3598 -
3599 -               goto retry;
3600 -       }       
3601 -
3602 -       chip->state = FL_ERASING;
3603 -
3604 -       adr += chip->start;
3605         DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
3606                __func__, adr );
3607  
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);
3613  
3614 -       cfi_write(map, CMD(0x30), adr);
3615 +       chip->state = FL_ERASING;
3616 +       chip->erase_suspended = 0;
3617 +       chip->in_progress_block_addr = adr;
3618         
3619 -       timeo = jiffies + (HZ*20);
3620 -
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.
3625 -        *
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.
3629 -        */
3630 -       /* see comments in do_write_oneword */
3631 -       dq6 = CMD(1<<6);
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);
3636  
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 );
3641 -
3642 -       while( ( ( status ^ oldstatus ) & dq6 )
3643 -              && ! ( ta = time_after(jiffies, timeo) ) ) {
3644 -               int wait_reps;
3645 +       timeo = jiffies + (HZ*20);
3646  
3647 -               /* an initial short sleep */
3648 -               cfi_spin_unlock(chip->mutex);
3649 -               schedule_timeout(HZ/100);
3650 -               cfi_spin_lock(chip->mutex);
3651 -               
3652 +       for (;;) {
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);
3657 -                       
3658                         cfi_spin_unlock(chip->mutex);
3659 -                       printk(KERN_DEBUG "erase suspended. Sleeping\n");
3660 -                       
3661                         schedule();
3662                         remove_wait_queue(&chip->wq, &wait);
3663 -#if 0                  
3664 -                       if (signal_pending(current))
3665 -                               return -EINTR;
3666 -#endif                 
3667 -                       timeo = jiffies + (HZ*2); /* FIXME */
3668                         cfi_spin_lock(chip->mutex);
3669                         continue;
3670                 }
3671 -
3672 -               /* Busy wait for 1/10 of a milisecond */
3673 -               for(wait_reps = 0;
3674 -                   (wait_reps < 100)
3675 -                           && ( ( status ^ oldstatus ) & dq6 );
3676 -                   wait_reps++) {
3677 -                       
3678 -                       /* Latency issues. Drop the lock, wait a while and retry */
3679 -                       cfi_spin_unlock(chip->mutex);
3680 -                       
3681 -                       cfi_udelay(1);
3682 -               
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 );
3688 -               }
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 );
3693 -       }
3694 -
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 );
3701 -
3702 -       if ( cfi_buswidth_is_1() ) {
3703 -               ones =  (__u8)~0;
3704 -       } else if ( cfi_buswidth_is_2() ) {
3705 -               ones = (__u16)~0;
3706 -       } else if ( cfi_buswidth_is_4() ) {
3707 -               ones = (__u32)~0;
3708 -       } else {
3709 -               printk(KERN_WARNING "Unsupported buswidth\n");
3710 -               goto erase_failed;
3711 -       }
3712 -
3713 -       if ( oldstatus == ones && status == ones ) {
3714 -               /* success - do nothing */
3715 -               goto erase_done;
3716 -       }
3717 -
3718 -       if ( ta ) {
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",
3724 -                               __func__,
3725 -                               status & dq5mask );
3726 -               } else {
3727 -                       printk( KERN_WARNING
3728 -                               "MTD %s(): Software timed out during write.\n",
3729 -                               __func__ );
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;
3735                 }
3736 -               goto erase_failed;
3737 -       }
3738  
3739 -       printk(KERN_WARNING
3740 -              "MTD %s(): Wacky!  Unable to decode failure status\n",
3741 -              __func__ );
3742 +               if (chip_ready(map, adr))
3743 +                       goto op_done;
3744  
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))
3751 +                       break;
3752  
3753 - erase_failed:
3754 -       ret = -EIO;
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);
3760 +       }
3761 +       
3762 +       printk(KERN_WARNING "MTD %s(): software timeout\n",
3763 +              __func__ );
3764 +       
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 */
3769  
3770 - erase_done:
3771 -       DISABLE_VPP(map);
3772 +       ret = -EIO;
3773 + op_done:
3774         chip->state = FL_READY;
3775 -       wake_up(&chip->wq);
3776 +       put_chip(map, chip, adr);
3777         cfi_spin_unlock(chip->mutex);
3778         return ret;
3779  }
3780  
3781 -static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
3782 -{
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;
3787 -       int i, first;
3788 -       struct mtd_erase_region_info *regions = mtd->eraseregions;
3789 -
3790 -       if (instr->addr > mtd->size)
3791 -               return -EINVAL;
3792 -
3793 -       if ((instr->len + instr->addr) > mtd->size)
3794 -               return -EINVAL;
3795 -
3796 -       /* Check that both start and end of the requested erase are
3797 -        * aligned with the erasesize at the appropriate addresses.
3798 -        */
3799 -
3800 -       i = 0;
3801 -
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.
3806 -       */
3807 -       
3808 -       while (i < mtd->numeraseregions && instr->addr >= regions[i].offset)
3809 -              i++;
3810 -       i--;
3811 -
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
3815 -          effect here.
3816 -       */
3817 -
3818 -       if (instr->addr & (regions[i].erasesize-1))
3819 -               return -EINVAL;
3820 -
3821 -       /* Remember the erase region we start on */
3822 -       first = i;
3823 -
3824 -       /* Next, check that the end of the requested erase is aligned
3825 -        * with the erase region at that address.
3826 -        */
3827 -
3828 -       while (i<mtd->numeraseregions && (instr->addr + instr->len) >= regions[i].offset)
3829 -               i++;
3830 -
3831 -       /* As before, drop back one to point at the region in which
3832 -          the address actually falls
3833 -       */
3834 -       i--;
3835 -       
3836 -       if ((instr->addr + instr->len) & (regions[i].erasesize-1))
3837 -               return -EINVAL;
3838 -       
3839 -       chipnum = instr->addr >> cfi->chipshift;
3840 -       adr = instr->addr - (chipnum << cfi->chipshift);
3841 -       len = instr->len;
3842 -
3843 -       i=first;
3844 -
3845 -       while(len) {
3846 -               ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
3847 -
3848 -               if (ret)
3849 -                       return ret;
3850 -
3851 -               adr += regions[i].erasesize;
3852 -               len -= regions[i].erasesize;
3853 -
3854 -               if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
3855 -                       i++;
3856 -
3857 -               if (adr >> cfi->chipshift) {
3858 -                       adr = 0;
3859 -                       chipnum++;
3860 -                       
3861 -                       if (chipnum >= cfi->numchips)
3862 -                       break;
3863 -               }
3864 -       }
3865 -
3866 -       instr->state = MTD_ERASE_DONE;
3867 -       if (instr->callback)
3868 -               instr->callback(instr);
3869 -       
3870 -       return 0;
3871 -}
3872  
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)
3875  {
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;
3880 -
3881 -       if (instr->addr & (mtd->erasesize - 1))
3882 -               return -EINVAL;
3883 -
3884 -       if (instr->len & (mtd->erasesize -1))
3885 -               return -EINVAL;
3886 -
3887 -       if ((instr->len + instr->addr) > mtd->size)
3888 -               return -EINVAL;
3889 +       unsigned long ofs, len;
3890 +       int ret;
3891  
3892 -       chipnum = instr->addr >> cfi->chipshift;
3893 -       adr = instr->addr - (chipnum << cfi->chipshift);
3894 +       ofs = instr->addr;
3895         len = instr->len;
3896  
3897 -       while(len) {
3898 -               ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
3899 -
3900 -               if (ret)
3901 -                       return ret;
3902 -
3903 -               adr += mtd->erasesize;
3904 -               len -= mtd->erasesize;
3905 +       ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
3906 +       if (ret)
3907 +               return ret;
3908  
3909 -               if (adr >> cfi->chipshift) {
3910 -                       adr = 0;
3911 -                       chipnum++;
3912 -                       
3913 -                       if (chipnum >= cfi->numchips)
3914 -                       break;
3915 -               }
3916 -       }
3917 -               
3918         instr->state = MTD_ERASE_DONE;
3919 -       if (instr->callback)
3920 -               instr->callback(instr);
3921 +       mtd_erase_callback(instr);
3922         
3923         return 0;
3924  }
3925  
3926 +
3927  static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
3928  {
3929         struct map_info *map = mtd->priv;
3930 @@ -1324,12 +1381,12 @@
3931                 return ret;
3932  
3933         instr->state = MTD_ERASE_DONE;
3934 -       if (instr->callback)
3935 -               instr->callback(instr);
3936 +       mtd_erase_callback(instr);
3937         
3938         return 0;
3939  }
3940  
3941 +
3942  static void cfi_amdstd_sync (struct mtd_info *mtd)
3943  {
3944         struct map_info *map = mtd->priv;
3945 @@ -1368,7 +1425,7 @@
3946  
3947                         schedule();
3948  
3949 -                       remove_wait_queue(&chip->wq, &wait);
3950 +                       remove_wait_queue(&chip->wq, &wait);
3951                         
3952                         goto retry;
3953                 }
3954 @@ -1427,7 +1484,7 @@
3955         /* Unlock the chips again */
3956  
3957         if (ret) {
3958 -               for (i--; i >=0; i--) {
3959 +               for (i--; i >=0; i--) {
3960                         chip = &cfi->chips[i];
3961  
3962                         cfi_spin_lock(chip->mutex);
3963 @@ -1443,6 +1500,7 @@
3964         return ret;
3965  }
3966  
3967 +
3968  static void cfi_amdstd_resume(struct mtd_info *mtd)
3969  {
3970         struct map_info *map = mtd->priv;
3971 @@ -1458,7 +1516,7 @@
3972                 
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);
3977                         wake_up(&chip->wq);
3978                 }
3979                 else
3980 @@ -1480,21 +1538,23 @@
3981  
3982  static char im_name[]="cfi_cmdset_0002";
3983  
3984 +
3985  int __init cfi_amdstd_init(void)
3986  {
3987         inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002);
3988         return 0;
3989  }
3990  
3991 +
3992  static void __exit cfi_amdstd_exit(void)
3993  {
3994         inter_module_unregister(im_name);
3995  }
3996  
3997 +
3998  module_init(cfi_amdstd_init);
3999  module_exit(cfi_amdstd_exit);
4000  
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");
4004 -
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
4009 @@ -4,6 +4,7 @@
4010   *
4011   * (C) 2000 Red Hat. GPL'd
4012   *
4013 + * $Id: cfi_cmdset_0020.c,v 1.15 2004/08/09 13:19:43 dwmw2 Exp $
4014   * 
4015   * 10/10/2000  Nicolas Pitre <nico@cam.org>
4016   *     - completely revamped method functions so they are aware and
4017 @@ -38,7 +39,7 @@
4018  
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 *);
4026 @@ -116,7 +117,6 @@
4027  {
4028         struct cfi_private *cfi = map->fldrv_priv;
4029         int i;
4030 -       __u32 base = cfi->chips[0].start;
4031  
4032         if (cfi->cfi_mode) {
4033                 /* 
4034 @@ -126,36 +126,11 @@
4035                  */
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;
4039  
4040 -                printk(" ST Microelectronics Extended Query Table at 0x%4.4X\n", adr);
4041 -               if (!adr)
4042 +               extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "ST Microelectronics");
4043 +               if (!extp)
4044                         return NULL;
4045  
4046 -               /* Switch it into Query Mode */
4047 -               cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
4048 -
4049 -               extp = kmalloc(sizeof(*extp), GFP_KERNEL);
4050 -               if (!extp) {
4051 -                       printk(KERN_ERR "Failed to allocate memory\n");
4052 -                       return NULL;
4053 -               }
4054 -               
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)));
4059 -               }
4060 -               
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);
4066 -                    kfree(extp);
4067 -                    return NULL;
4068 -               }
4069 -               
4070                 /* Do some byteswapping if necessary */
4071                 extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport);
4072                 extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask);
4073 @@ -175,8 +150,6 @@
4074                 cfi->chips[i].erase_time = 1024;
4075         }               
4076  
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);
4080  }
4081  
4082 @@ -266,7 +239,7 @@
4083  
4084  static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
4085  {
4086 -       __u32 status, status_OK;
4087 +       map_word status, status_OK;
4088         unsigned long timeo;
4089         DECLARE_WAITQUEUE(wait, current);
4090         int suspended = 0;
4091 @@ -276,7 +249,7 @@
4092         adr += chip->start;
4093  
4094         /* Ensure cmd read/writes are aligned. */ 
4095 -       cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); 
4096 +       cmd_addr = adr & ~(map_bankwidth(map)-1); 
4097  
4098         /* Let's determine this according to the interleave only once */
4099         status_OK = CMD(0x80);
4100 @@ -290,33 +263,33 @@
4101          */
4102         switch (chip->state) {
4103         case FL_ERASING:
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 */
4107                 
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
4114                  */
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);
4120                 for (;;) {
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))
4125                                 break;
4126                         
4127                         if (time_after(jiffies, timeo)) {
4128                                 /* Urgh */
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]);
4139                                 return -EIO;
4140                         }
4141                         
4142 @@ -326,7 +299,7 @@
4143                 }
4144                 
4145                 suspended = 1;
4146 -               cfi_write(map, CMD(0xff), cmd_addr);
4147 +               map_write(map, CMD(0xff), cmd_addr);
4148                 chip->state = FL_READY;
4149                 break;
4150         
4151 @@ -340,13 +313,13 @@
4152  
4153         case FL_CFI_QUERY:
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;
4158  
4159         case 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;
4167                         break;
4168                 }
4169 @@ -354,7 +327,7 @@
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]);
4175                         return -EIO;
4176                 }
4177  
4178 @@ -389,8 +362,8 @@
4179                    sending the 0x70 (Read Status) command to an erasing
4180                    chip and expecting it to be ignored, that's what we 
4181                    do. */
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);            
4186         }
4187  
4188         wake_up(&chip->wq);
4189 @@ -441,16 +414,16 @@
4190                                   unsigned long adr, const u_char *buf, int len)
4191  {
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);
4197         int wbufsize, z;
4198          
4199          /* M58LW064A requires bus alignment for buffer wriets -- saw */
4200 -        if (adr & (CFIDEV_BUSWIDTH-1))
4201 +        if (adr & (map_bankwidth(map)-1))
4202              return -EINVAL;
4203  
4204 -        wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize;
4205 +        wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
4206          adr += chip->start;
4207         cmd_adr = adr & ~(wbufsize-1);
4208         
4209 @@ -476,21 +449,21 @@
4210                 
4211         case FL_CFI_QUERY:
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));
4219  #endif
4220  
4221         case FL_STATUS:
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))
4226                         break;
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]);
4234                         return -EIO;
4235                 }
4236  
4237 @@ -512,13 +485,13 @@
4238         }
4239  
4240         ENABLE_VPP(map);
4241 -       cfi_write(map, CMD(0xe8), cmd_adr);
4242 +       map_write(map, CMD(0xe8), cmd_adr);
4243         chip->state = FL_WRITING_TO_BUFFER;
4244  
4245         z = 0;
4246         for (;;) {
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))
4251                         break;
4252  
4253                 spin_unlock_bh(chip->mutex);
4254 @@ -528,41 +501,26 @@
4255                 if (++z > 100) {
4256                         /* Argh. Not ready for write to buffer */
4257                         DISABLE_VPP(map);
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]);
4264                         return -EIO;
4265                 }
4266         }
4267  
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 );
4271          
4272         /* Write data */
4273 -       for (z = 0; z < len; z += CFIDEV_BUSWIDTH) {
4274 -               if (cfi_buswidth_is_1()) {
4275 -                       u8 *b = (u8 *)buf;
4276 -
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;
4281 -
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;
4286 -
4287 -                       map_write32 (map, *b++, adr+z);
4288 -                       buf = (const u_char *)b;
4289 -               } else {
4290 -                       DISABLE_VPP(map);
4291 -                       return -EINVAL;
4292 -               }
4293 +       for (z = 0; z < len;
4294 +            z += map_bankwidth(map), buf += map_bankwidth(map)) {
4295 +               map_word d;
4296 +               d = map_word_load(map, buf);
4297 +               map_write(map, d, adr+z);
4298         }
4299         /* GO GO GO */
4300 -       cfi_write(map, CMD(0xd0), cmd_adr);
4301 +       map_write(map, CMD(0xd0), cmd_adr);
4302         chip->state = FL_WRITING;
4303  
4304         spin_unlock_bh(chip->mutex);
4305 @@ -584,16 +542,16 @@
4306                         continue;
4307                 }
4308  
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))
4313                         break;
4314  
4315                 /* OK Still waiting */
4316                 if (time_after(jiffies, timeo)) {
4317                          /* clear status */
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;
4324                         DISABLE_VPP(map);
4325                         spin_unlock_bh(chip->mutex);
4326 @@ -620,19 +578,18 @@
4327         chip->state = FL_STATUS;
4328  
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]);
4336  #endif
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;
4344 -        }
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;
4352 +       }
4353         wake_up(&chip->wq);
4354         spin_unlock_bh(chip->mutex);
4355  
4356 @@ -644,7 +601,7 @@
4357  {
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;
4362         int ret = 0;
4363         int chipnum;
4364         unsigned long ofs;
4365 @@ -657,7 +614,7 @@
4366         ofs = to  - (chipnum << cfi->chipshift);
4367  
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);
4373  #endif
4374 @@ -700,7 +657,7 @@
4375  #define ECCBUF_DIV(x) ((x) & ~(ECCBUF_SIZE - 1))
4376  #define ECCBUF_MOD(x) ((x) &  (ECCBUF_SIZE - 1))
4377  static int
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)
4381  {
4382         unsigned long i;
4383 @@ -769,7 +726,7 @@
4384  static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
4385  {
4386         struct cfi_private *cfi = map->fldrv_priv;
4387 -       __u32 status, status_OK;
4388 +       map_word status, status_OK;
4389         unsigned long timeo;
4390         int retries = 3;
4391         DECLARE_WAITQUEUE(wait, current);
4392 @@ -789,12 +746,12 @@
4393         case FL_CFI_QUERY:
4394         case FL_JEDEC_QUERY:
4395         case FL_READY:
4396 -               cfi_write(map, CMD(0x70), adr);
4397 +               map_write(map, CMD(0x70), adr);
4398                 chip->state = FL_STATUS;
4399  
4400         case 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))
4405                         break;
4406                 
4407                 /* Urgh. Chip not yet ready to talk to us. */
4408 @@ -823,11 +780,11 @@
4409  
4410         ENABLE_VPP(map);
4411         /* Clear the status register first */
4412 -       cfi_write(map, CMD(0x50), adr);
4413 +       map_write(map, CMD(0x50), adr);
4414  
4415         /* Now erase */
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;
4421         
4422         spin_unlock_bh(chip->mutex);
4423 @@ -851,15 +808,15 @@
4424                         continue;
4425                 }
4426  
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))
4431                         break;
4432                 
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]);
4440                         DISABLE_VPP(map);
4441                         spin_unlock_bh(chip->mutex);
4442                         return -EIO;
4443 @@ -875,43 +832,46 @@
4444         ret = 0;
4445  
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);
4452  
4453         /* check for lock bit */
4454 -       if (status & CMD(0x3a)) {
4455 -               unsigned char chipstatus = status;
4456 -               if (status != CMD(status & 0xff)) {
4457 -                       int i;
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))) {
4463 +                       int i, w;
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);
4467 +                               }
4468                         }
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);
4472                 }
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);
4478                 
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);
4482                         ret = -EIO;
4483                 } else if (chipstatus & 0x02) {
4484                         /* Protection bit set */
4485                         ret = -EROFS;
4486                 } else if (chipstatus & 0x8) {
4487                         /* Voltage */
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);
4490                         ret = -EIO;
4491                 } else if (chipstatus & 0x20) {
4492                         if (retries--) {
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);
4498                                 goto retry;
4499                         }
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);
4502                         ret = -EIO;
4503                 }
4504         }
4505 @@ -1006,8 +966,7 @@
4506         }
4507                 
4508         instr->state = MTD_ERASE_DONE;
4509 -       if (instr->callback)
4510 -               instr->callback(instr);
4511 +       mtd_erase_callback(instr);
4512         
4513         return 0;
4514  }
4515 @@ -1072,7 +1031,7 @@
4516  static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
4517  {
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);
4523  
4524 @@ -1090,12 +1049,12 @@
4525         case FL_CFI_QUERY:
4526         case FL_JEDEC_QUERY:
4527         case FL_READY:
4528 -               cfi_write(map, CMD(0x70), adr);
4529 +               map_write(map, CMD(0x70), adr);
4530                 chip->state = FL_STATUS;
4531  
4532         case 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)) 
4537                         break;
4538                 
4539                 /* Urgh. Chip not yet ready to talk to us. */
4540 @@ -1123,8 +1082,8 @@
4541         }
4542  
4543         ENABLE_VPP(map);
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;
4549         
4550         spin_unlock_bh(chip->mutex);
4551 @@ -1137,15 +1096,15 @@
4552         timeo = jiffies + (HZ*2);
4553         for (;;) {
4554  
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))
4559                         break;
4560                 
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]);
4568                         DISABLE_VPP(map);
4569                         spin_unlock_bh(chip->mutex);
4570                         return -EIO;
4571 @@ -1221,7 +1180,7 @@
4572  static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
4573  {
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);
4579  
4580 @@ -1239,12 +1198,12 @@
4581         case FL_CFI_QUERY:
4582         case FL_JEDEC_QUERY:
4583         case FL_READY:
4584 -               cfi_write(map, CMD(0x70), adr);
4585 +               map_write(map, CMD(0x70), adr);
4586                 chip->state = FL_STATUS;
4587  
4588         case 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))
4593                         break;
4594                 
4595                 /* Urgh. Chip not yet ready to talk to us. */
4596 @@ -1272,8 +1231,8 @@
4597         }
4598  
4599         ENABLE_VPP(map);
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;
4605         
4606         spin_unlock_bh(chip->mutex);
4607 @@ -1286,15 +1245,15 @@
4608         timeo = jiffies + (HZ*2);
4609         for (;;) {
4610  
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))
4615                         break;
4616                 
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]);
4624                         DISABLE_VPP(map);
4625                         spin_unlock_bh(chip->mutex);
4626                         return -EIO;
4627 @@ -1423,7 +1382,7 @@
4628                 
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;
4634                         wake_up(&chip->wq);
4635                 }
4636 @@ -1440,11 +1399,6 @@
4637         kfree(cfi);
4638  }
4639  
4640 -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
4641 -#define cfi_staa_init init_module
4642 -#define cfi_staa_exit cleanup_module
4643 -#endif
4644 -
4645  static char im_name[]="cfi_cmdset_0020";
4646  
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
4652 @@ -1,7 +1,7 @@
4653  /* 
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 $
4658  */
4659  
4660  #include <linux/config.h>
4661 @@ -26,7 +26,7 @@
4662  #endif
4663  
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);
4668  
4669  struct mtd_info *cfi_probe(struct map_info *map);
4670 @@ -35,21 +35,36 @@
4671     in: interleave,type,mode
4672     ret: table index, <0 for error
4673   */
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)
4677  {
4678         int osf = cfi->interleave * cfi->device_type;   // scale factor
4679 +       map_word val;
4680 +       map_word qry;
4681  
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))
4685 -               return 1;       // ok !
4686 +       qry =  cfi_build_cmd('Q', map, cfi);
4687 +       val = map_read(map, base + osf*0x10);
4688  
4689 -       return 0;       // nothing found
4690 +       if (!map_word_equal(map, qry, val))
4691 +               return 0;
4692 +
4693 +       qry =  cfi_build_cmd('R', map, cfi);
4694 +       val = map_read(map, base + osf*0x11);
4695 +
4696 +       if (!map_word_equal(map, qry, val))
4697 +               return 0;
4698 +
4699 +       qry =  cfi_build_cmd('Y', map, cfi);
4700 +       val = map_read(map, base + osf*0x12);
4701 +
4702 +       if (!map_word_equal(map, qry, val))
4703 +               return 0;
4704 +
4705 +       return 1;       // nothing found
4706  }
4707  
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)
4711  {
4712         int i;
4713         
4714 @@ -66,6 +81,7 @@
4715                 return 0;
4716         }
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);
4720  
4721         if (!qry_present(map,base,cfi))
4722 @@ -78,18 +94,25 @@
4723         }
4724  
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 */
4731 +                       continue; 
4732 +               }
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);
4743  
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);
4750                                 return 0;
4751                         }
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);
4758                         
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);
4763                                 return 0;
4764                         }
4765                 }
4766 @@ -108,21 +132,16 @@
4767         
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 */
4773 -               return -1;
4774 -       }
4775 -       chips[cfi->numchips].start = base;
4776 -       chips[cfi->numchips].state = FL_READY;
4777 +       set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
4778         cfi->numchips++;
4779         
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);
4783  
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,
4787 -              map->buswidth*8);
4788 +              map->bankwidth*8);
4789         
4790         return 1;
4791  }
4792 @@ -150,7 +169,6 @@
4793         memset(cfi->cfiq,0,sizeof(struct cfi_ident));   
4794         
4795         cfi->cfi_mode = CFI_MODE_CFI;
4796 -       cfi->fast_prog=1;               /* CFI supports fast programming */
4797         
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);
4802  #endif
4803         }
4804 +
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).
4811 +        */
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);    
4818 +
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);
4823 +
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);
4827  
4828         return 1;
4829  }
4830 @@ -241,11 +280,11 @@
4831                 printk("No Alternate Algorithm Table\n");
4832                 
4833                 
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);
4838         if (cfip->VppMin) {
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);
4843         }
4844         else
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
4850 @@ -0,0 +1,188 @@
4851 +/*
4852 + * Common Flash Interface support:
4853 + *   Generic utility functions not dependant on command set
4854 + *
4855 + * Copyright (C) 2002 Red Hat
4856 + * Copyright (C) 2003 STMicroelectronics Limited
4857 + *
4858 + * This code is covered by the GPL.
4859 + *
4860 + * $Id: cfi_util.c,v 1.5 2004/08/12 06:40:23 eric Exp $
4861 + *
4862 + */
4863 +
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>
4870 +
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>
4879 +
4880 +struct cfi_extquery *
4881 +cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name)
4882 +{
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;
4886 +       int i;
4887 +       struct cfi_extquery *extp = NULL;
4888 +
4889 +       printk(" %s Extended Query Table at 0x%4.4X\n", name, adr);
4890 +       if (!adr)
4891 +               goto out;
4892 +
4893 +       /* Switch it into Query Mode */
4894 +       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
4895 +
4896 +       extp = kmalloc(size, GFP_KERNEL);
4897 +       if (!extp) {
4898 +               printk(KERN_ERR "Failed to allocate memory\n");
4899 +               goto out;
4900 +       }
4901 +               
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));
4906 +       }
4907 +
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);
4913 +               kfree(extp);
4914 +               extp = NULL;
4915 +               goto out;
4916 +       }
4917 +
4918 +out:
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);
4922 +
4923 +       return extp;
4924 +}
4925 +
4926 +EXPORT_SYMBOL(cfi_read_pri);
4927 +
4928 +void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup *fixups)
4929 +{
4930 +       struct map_info *map = mtd->priv;
4931 +       struct cfi_private *cfi = map->fldrv_priv;
4932 +       struct cfi_fixup *f;
4933 +
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);
4938 +               }
4939 +       }
4940 +}
4941 +
4942 +EXPORT_SYMBOL(cfi_fixup);
4943 +
4944 +int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
4945 +                                    loff_t ofs, size_t len, void *thunk)
4946 +{
4947 +       struct map_info *map = mtd->priv;
4948 +       struct cfi_private *cfi = map->fldrv_priv;
4949 +       unsigned long adr;
4950 +       int chipnum, ret = 0;
4951 +       int i, first;
4952 +       struct mtd_erase_region_info *regions = mtd->eraseregions;
4953 +
4954 +       if (ofs > mtd->size)
4955 +               return -EINVAL;
4956 +
4957 +       if ((len + ofs) > mtd->size)
4958 +               return -EINVAL;
4959 +
4960 +       /* Check that both start and end of the requested erase are
4961 +        * aligned with the erasesize at the appropriate addresses.
4962 +        */
4963 +
4964 +       i = 0;
4965 +
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.
4970 +       */
4971 +       
4972 +       while (i < mtd->numeraseregions && ofs >= regions[i].offset)
4973 +              i++;
4974 +       i--;
4975 +
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
4979 +          effect here.
4980 +       */
4981 +
4982 +       if (ofs & (regions[i].erasesize-1))
4983 +               return -EINVAL;
4984 +
4985 +       /* Remember the erase region we start on */
4986 +       first = i;
4987 +
4988 +       /* Next, check that the end of the requested erase is aligned
4989 +        * with the erase region at that address.
4990 +        */
4991 +
4992 +       while (i<mtd->numeraseregions && (ofs + len) >= regions[i].offset)
4993 +               i++;
4994 +
4995 +       /* As before, drop back one to point at the region in which
4996 +          the address actually falls
4997 +       */
4998 +       i--;
4999 +       
5000 +       if ((ofs + len) & (regions[i].erasesize-1))
5001 +               return -EINVAL;
5002 +
5003 +       chipnum = ofs >> cfi->chipshift;
5004 +       adr = ofs - (chipnum << cfi->chipshift);
5005 +
5006 +       i=first;
5007 +
5008 +       while(len) {
5009 +               unsigned long chipmask;
5010 +               int size = regions[i].erasesize;
5011 +
5012 +               ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk);
5013 +               
5014 +               if (ret)
5015 +                       return ret;
5016 +
5017 +               adr += size;
5018 +               len -= size;
5019 +
5020 +               chipmask = (1 << cfi->chipshift) - 1;
5021 +               if ((adr & chipmask) == ((regions[i].offset + size * regions[i].numblocks) & chipmask))
5022 +                       i++;
5023 +
5024 +               if (adr >> cfi->chipshift) {
5025 +                       adr = 0;
5026 +                       chipnum++;
5027 +                       
5028 +                       if (chipnum >= cfi->numchips)
5029 +                       break;
5030 +               }
5031 +       }
5032 +
5033 +       return 0;
5034 +}
5035 +
5036 +EXPORT_SYMBOL(cfi_varsize_frob);
5037 +
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
5043 @@ -1,5 +1,5 @@
5044  /*
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 $
5047   *
5048   * Registration for chip drivers
5049   *
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
5054 @@ -0,0 +1,107 @@
5055 +#ifndef FWH_LOCK_H
5056 +#define FWH_LOCK_H
5057 +
5058 +
5059 +enum fwh_lock_state {
5060 +        FWH_UNLOCKED   = 0,
5061 +       FWH_DENY_WRITE = 1,
5062 +       FWH_IMMUTABLE  = 2,
5063 +       FWH_DENY_READ  = 4,
5064 +};
5065 +
5066 +struct fwh_xxlock_thunk {
5067 +       enum fwh_lock_state val;
5068 +       flstate_t state;
5069 +};
5070 +
5071 +
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})
5074 +
5075 +/*
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.
5081 + */
5082 +static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip, 
5083 +       unsigned long adr, int len, void *thunk)
5084 +{
5085 +       struct cfi_private *cfi = map->fldrv_priv;
5086 +       struct fwh_xxlock_thunk *xxlt = (struct fwh_xxlock_thunk *)thunk;
5087 +       int ret;
5088 +
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 );
5094 +               return -EIO;
5095 +       }
5096 +       /*
5097 +        * lock block registers:
5098 +        * - on 64k boundariesand
5099 +        * - bit 1 set high
5100 +        * - block lock registers are 4MiB lower - overflow subtract (danger)
5101 +        * 
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.
5106 +        */
5107 +       adr = (adr & ~0xffffUL) | 0x2;
5108 +       adr += chip->start - 0x400000;
5109 +
5110 +       /*
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
5113 +        * and timeout.
5114 +        */
5115 +       cfi_spin_lock(chip->mutex);
5116 +       ret = get_chip(map, chip, adr, FL_LOCKING);
5117 +       if (ret) {
5118 +               cfi_spin_unlock(chip->mutex);
5119 +               return ret;
5120 +       }
5121 +
5122 +       chip->state = xxlt->state;
5123 +       map_write(map, CMD(xxlt->val), adr);
5124 +
5125 +       /* Done and happy. */
5126 +       chip->state = FL_READY;
5127 +       put_chip(map, chip, adr);
5128 +       cfi_spin_unlock(chip->mutex);
5129 +       return 0;
5130 +}
5131 +
5132 +
5133 +static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
5134 +{
5135 +       int ret;
5136 +
5137 +       ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
5138 +               (void *)&FWH_XXLOCK_ONEBLOCK_LOCK);
5139 +
5140 +       return ret;
5141 +}
5142 +
5143 +
5144 +static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
5145 +{
5146 +       int ret;
5147 +
5148 +       ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
5149 +               (void *)&FWH_XXLOCK_ONEBLOCK_UNLOCK);
5150 +       
5151 +       return ret;
5152 +}
5153 +
5154 +static void fixup_use_fwh_lock(struct mtd_info *mtd, void *param)
5155 +{
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;
5160 +}
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
5166 @@ -2,7 +2,7 @@
5167   * Routines common to all CFI-type probes.
5168   * (C) 2001-2003 Red Hat, Inc.
5169   * GPL'd
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 $
5172   */
5173  
5174  #include <linux/kernel.h>
5175 @@ -50,24 +50,22 @@
5176  EXPORT_SYMBOL(mtd_do_chip_probe);
5177  
5178  
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)
5181  {
5182 -       unsigned long base=0;
5183         struct cfi_private cfi;
5184         struct cfi_private *retcfi;
5185 -       struct flchip chip[MAX_CFI_CHIPS];
5186 -       int i;
5187 +       unsigned long *chip_map;
5188 +       int i, j, mapsize;
5189 +       int max_chips;
5190  
5191         memset(&cfi, 0, sizeof(cfi));
5192 -       memset(&chip[0], 0, sizeof(chip));
5193  
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);
5203                 return NULL;
5204         }               
5205  
5206 @@ -81,46 +79,47 @@
5207                 return NULL;
5208         }
5209  #endif
5210 -       chip[0].start = 0;
5211 -       chip[0].state = FL_READY;
5212         cfi.chipshift = cfi.cfiq->DevSize;
5213  
5214 -       switch(cfi.interleave) {
5215 -#ifdef CFIDEV_INTERLEAVE_1
5216 -       case 1:
5217 -               break;
5218 -#endif
5219 -#ifdef CFIDEV_INTERLEAVE_2
5220 -       case 2:
5221 +       if (cfi_interleave_is_1(&cfi)) {
5222 +               ;
5223 +       } else if (cfi_interleave_is_2(&cfi)) {
5224                 cfi.chipshift++;
5225 -               break;
5226 -#endif
5227 -#ifdef CFIDEV_INTERLEAVE_4
5228 -       case 4:
5229 -               cfi.chipshift+=2;
5230 -               break;
5231 -#endif
5232 -       default:
5233 +       } else if (cfi_interleave_is_4((&cfi))) {
5234 +               cfi.chipshift += 2;
5235 +       } else if (cfi_interleave_is_8(&cfi)) {
5236 +               cfi.chipshift += 3;
5237 +       } else {
5238                 BUG();
5239         }
5240                 
5241         cfi.numchips = 1;
5242  
5243 +       /* 
5244 +        * Allocate memory for bitmap of valid chips. 
5245 +        * Align bitmap storage size to full byte. 
5246 +        */ 
5247 +       max_chips = map->size >> cfi.chipshift;
5248 +       mapsize = (max_chips / 8) + ((max_chips % 8) ? 1 : 0);
5249 +       chip_map = kmalloc(mapsize, GFP_KERNEL);
5250 +       if (!chip_map) {
5251 +               printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
5252 +               kfree(cfi.cfiq);
5253 +               return NULL;
5254 +       }
5255 +       memset (chip_map, 0, mapsize);
5256 +
5257 +       set_bit(0, chip_map); /* Mark first chip valid */
5258 +
5259         /*
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.
5263 -        *
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.
5269          */
5270  
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);
5276 +       }
5277  
5278         /*
5279          * Now allocate the space for the structures we need to return to 
5280 @@ -132,19 +131,26 @@
5281         if (!retcfi) {
5282                 printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name);
5283                 kfree(cfi.cfiq);
5284 +               kfree(chip_map);
5285                 return NULL;
5286         }
5287  
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);
5291 +
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++];
5295  
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;
5306 +               }
5307         }
5308  
5309 +       kfree(chip_map);
5310         return retcfi;
5311  }
5312  
5313 @@ -152,131 +158,31 @@
5314  static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
5315                              struct cfi_private *cfi)
5316  {
5317 -       switch (map->buswidth) {
5318 -#ifdef CFIDEV_BUSWIDTH_1               
5319 -       case CFIDEV_BUSWIDTH_1:
5320 -               cfi->interleave = CFIDEV_INTERLEAVE_1;
5321 -
5322 -               cfi->device_type = CFI_DEVICETYPE_X8;
5323 -               if (cp->probe_chip(map, 0, NULL, cfi))
5324 -                       return 1;
5325 -
5326 -               cfi->device_type = CFI_DEVICETYPE_X16;
5327 -               if (cp->probe_chip(map, 0, NULL, cfi))
5328 -                       return 1;
5329 -               break;                  
5330 -#endif /* CFIDEV_BUSWITDH_1 */
5331 -
5332 -#ifdef CFIDEV_BUSWIDTH_2               
5333 -       case CFIDEV_BUSWIDTH_2:
5334 -#ifdef CFIDEV_INTERLEAVE_1
5335 -               cfi->interleave = CFIDEV_INTERLEAVE_1;
5336 -
5337 -               cfi->device_type = CFI_DEVICETYPE_X16;
5338 -               if (cp->probe_chip(map, 0, NULL, cfi))
5339 -                       return 1;
5340 -#endif /* CFIDEV_INTERLEAVE_1 */
5341 -#ifdef CFIDEV_INTERLEAVE_2
5342 -               cfi->interleave = CFIDEV_INTERLEAVE_2;
5343 -
5344 -               cfi->device_type = CFI_DEVICETYPE_X8;
5345 -               if (cp->probe_chip(map, 0, NULL, cfi))
5346 -                       return 1;
5347 -
5348 -               cfi->device_type = CFI_DEVICETYPE_X16;
5349 -               if (cp->probe_chip(map, 0, NULL, cfi))
5350 -                       return 1;
5351 -#endif /* CFIDEV_INTERLEAVE_2 */
5352 -               break;                  
5353 -#endif /* CFIDEV_BUSWIDTH_2 */
5354 -
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;
5359 -
5360 -                cfi->device_type = CFI_DEVICETYPE_X32;
5361 -               if (cp->probe_chip(map, 0, NULL, cfi))
5362 -                       return 1;
5363 -#endif /* CFIDEV_INTERLEAVE_1 */
5364 -#ifdef CFIDEV_INTERLEAVE_2
5365 -               cfi->interleave = CFIDEV_INTERLEAVE_2;
5366 -
5367 -#ifdef SOMEONE_ACTUALLY_MAKES_THESE
5368 -               cfi->device_type = CFI_DEVICETYPE_X32;
5369 -               if (cp->probe_chip(map, 0, NULL, cfi))
5370 -                       return 1;
5371 -#endif
5372 -               cfi->device_type = CFI_DEVICETYPE_X16;
5373 -               if (cp->probe_chip(map, 0, NULL, cfi))
5374 -                       return 1;
5375 -
5376 -               cfi->device_type = CFI_DEVICETYPE_X8;
5377 -               if (cp->probe_chip(map, 0, NULL, cfi))
5378 -                       return 1;
5379 -#endif /* CFIDEV_INTERLEAVE_2 */
5380 -#ifdef CFIDEV_INTERLEAVE_4
5381 -               cfi->interleave = CFIDEV_INTERLEAVE_4;
5382 -
5383 -#ifdef SOMEONE_ACTUALLY_MAKES_THESE
5384 -               cfi->device_type = CFI_DEVICETYPE_X32;
5385 -               if (cp->probe_chip(map, 0, NULL, cfi))
5386 -                       return 1;
5387 -#endif
5388 -               cfi->device_type = CFI_DEVICETYPE_X16;
5389 -               if (cp->probe_chip(map, 0, NULL, cfi))
5390 -                       return 1;
5391 -
5392 -               cfi->device_type = CFI_DEVICETYPE_X8;
5393 -               if (cp->probe_chip(map, 0, NULL, cfi))
5394 -                       return 1;
5395 -#endif /* CFIDEV_INTERLEAVE_4 */
5396 -               break;
5397 -#endif /* CFIDEV_BUSWIDTH_4 */
5398 -
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;
5403 -
5404 -                cfi->device_type = CFI_DEVICETYPE_X32;
5405 -               if (cp->probe_chip(map, 0, NULL, cfi))
5406 -                       return 1;
5407 -#endif /* CFIDEV_INTERLEAVE_2 */
5408 -#ifdef CFIDEV_INTERLEAVE_4
5409 -               cfi->interleave = CFIDEV_INTERLEAVE_4;
5410 -
5411 -#ifdef SOMEONE_ACTUALLY_MAKES_THESE
5412 -               cfi->device_type = CFI_DEVICETYPE_X32;
5413 -               if (cp->probe_chip(map, 0, NULL, cfi))
5414 -                       return 1;
5415 -#endif
5416 -               cfi->device_type = CFI_DEVICETYPE_X16;
5417 -               if (cp->probe_chip(map, 0, NULL, cfi))
5418 -                       return 1;
5419 -#endif /* CFIDEV_INTERLEAVE_4 */
5420 -#ifdef CFIDEV_INTERLEAVE_8
5421 -               cfi->interleave = CFIDEV_INTERLEAVE_8;
5422 -
5423 -               cfi->device_type = CFI_DEVICETYPE_X16;
5424 -               if (cp->probe_chip(map, 0, NULL, cfi))
5425 -                       return 1;
5426 -
5427 -               cfi->device_type = CFI_DEVICETYPE_X8;
5428 -               if (cp->probe_chip(map, 0, NULL, cfi))
5429 -                       return 1;
5430 -#endif /* CFIDEV_INTERLEAVE_8 */
5431 -               break;
5432 -#endif /* CFIDEV_BUSWIDTH_8 */
5433 -
5434 -       default:
5435 -               printk(KERN_WARNING "genprobe_new_chip called with unsupported buswidth %d\n", map->buswidth);
5436 -               return 0;
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;
5440 +
5441 +       for (nr_chips = min_chips; nr_chips <= max_chips; nr_chips <<= 1) {
5442 +
5443 +               if (!cfi_interleave_supported(nr_chips))
5444 +                   continue;
5445 +
5446 +               cfi->interleave = nr_chips;
5447 +
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;
5451 +
5452 +               for (; type <= CFI_DEVICETYPE_X32; type<<=1) {
5453 +                       cfi->device_type = type;
5454 +
5455 +                       if (cp->probe_chip(map, 0, NULL, cfi))
5456 +                               return 1;
5457 +               }
5458         }
5459         return 0;
5460  }
5461  
5462 -
5463  typedef struct mtd_info *cfi_cmdset_fn_t(struct map_info *, int);
5464  
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
5470 @@ -11,7 +11,7 @@
5471   * not going to guess how to send commands to them, plus I expect they will
5472   * all speak CFI..
5473   *
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 $
5476   */
5477  
5478  #include <linux/init.h>
5479 @@ -128,7 +128,7 @@
5480     {
5481        printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n");
5482        kfree(MTD);
5483 -      return 0;
5484 +      return NULL;
5485     }
5486     
5487     for (Base = 0; Base < map->size; Base += my_bank_size)
5488 @@ -141,7 +141,7 @@
5489          if (jedec_probe8(map,Base,priv) == 0) {
5490                  printk("did recognize jedec chip\n");
5491                  kfree(MTD);
5492 -                return 0;
5493 +                return NULL;
5494          }
5495        }
5496        if (map->buswidth == 2)
5497 @@ -167,7 +167,7 @@
5498        {
5499          printk("mtd: Failed. Device has incompatible mixed sector sizes\n");
5500          kfree(MTD);
5501 -        return 0;
5502 +        return NULL;
5503        }      
5504     }
5505     
5506 @@ -193,7 +193,7 @@
5507        {
5508          printk("mtd: Internal Error, JEDEC not set\n");
5509          kfree(MTD);
5510 -        return 0;
5511 +        return NULL;
5512        }
5513        
5514        if (Uniq != 0)
5515 @@ -221,7 +221,7 @@
5516     if (!priv->size) {
5517            printk("priv->size is zero\n");
5518            kfree(MTD);
5519 -          return 0;
5520 +          return NULL;
5521     }
5522     if (priv->size/my_bank_size) {
5523            if (priv->size/my_bank_size == 1) {
5524 @@ -240,7 +240,7 @@
5525                       {
5526                          printk("mtd: Failed. Cannot handle unsymmetric banking\n");
5527                          kfree(MTD);
5528 -                        return 0;
5529 +                        return NULL;
5530                       }      
5531                    }
5532            }
5533 @@ -385,7 +385,7 @@
5534     for (I = 0; JEDEC_table[I].jedec != 0; I++)
5535        if (JEDEC_table[I].jedec == Id)
5536          return JEDEC_table + I;
5537 -   return 0;
5538 +   return NULL;
5539  }
5540  
5541  // Look for flash using an 8 bit bus interface
5542 @@ -780,8 +780,7 @@
5543                     
5544     //printk("done\n");
5545     instr->state = MTD_ERASE_DONE;
5546 -   if (instr->callback)
5547 -       instr->callback(instr);
5548 +   mtd_erase_callback(instr);
5549     return 0;
5550     
5551     #undef flread
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
5556 @@ -1,9 +1,11 @@
5557  /* 
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.
5564 +
5565 +   Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
5566  */
5567  
5568  #include <linux/config.h>
5569 @@ -27,6 +29,7 @@
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
5577 @@ -37,8 +40,13 @@
5578  
5579  
5580  /* AMD */
5581 +#define AM29DL800BB    0x22C8
5582 +#define AM29DL800BT    0x224A
5583 +
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
5591 @@ -49,6 +57,7 @@
5592  #define AM29F040       0x00A4
5593  #define AM29LV040B     0x004F
5594  #define AM29F032B      0x0041
5595 +#define AM29F002T      0x00B0
5596  
5597  /* Atmel */
5598  #define AT49BV512      0x0003
5599 @@ -59,6 +68,7 @@
5600  #define AT49BV32XT     0x00C9
5601  
5602  /* Fujitsu */
5603 +#define MBM29F040C     0x00A4
5604  #define MBM29LV650UE   0x22D7
5605  #define MBM29LV320TE   0x22F6
5606  #define MBM29LV320BE   0x22F9
5607 @@ -66,6 +76,11 @@
5608  #define MBM29LV160BE   0x2249
5609  #define MBM29LV800BA   0x225B
5610  #define MBM29LV800TA   0x22DA
5611 +#define MBM29LV400TC   0x22B9
5612 +#define MBM29LV400BC   0x22BA
5613 +
5614 +/* Hyundai */
5615 +#define HY29F002T      0x00B0
5616  
5617  /* Intel */
5618  #define I28F004B3T     0x00d4
5619 @@ -92,9 +107,11 @@
5620  #define I82802AC       0x00ac
5621  
5622  /* Macronix */
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
5630  
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
5639  
5640  /* SST */
5641 +#define SST29EE020     0x0010
5642 +#define SST29LE020     0x0012
5643  #define SST29EE512     0x005d
5644  #define SST29LE512     0x003d
5645  #define SST39LF800     0x2781
5646 @@ -121,6 +144,8 @@
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
5655 @@ -158,8 +183,8 @@
5656  
5657  
5658  struct unlock_addr {
5659 -       int addr1;
5660 -       int addr2;
5661 +       u32 addr1;
5662 +       u32 addr2;
5663  };
5664  
5665  
5666 @@ -211,11 +236,10 @@
5667         const __u16 dev_id;
5668         const char *name;
5669         const int DevSize;
5670 -       const int InterfaceDesc;
5671         const int NumEraseRegions;
5672         const int CmdSet;
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];
5677  };
5678  
5679  #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
5680 @@ -285,6 +309,40 @@
5681                 }
5682         }, {
5683                 .mfr_id         = MANUFACTURER_AMD,
5684 +               .dev_id         = AM29LV400BB,
5685 +               .name           = "AMD AM29LV400BB",
5686 +               .uaddr          = {
5687 +                       [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
5688 +                       [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
5689 +               },
5690 +               .DevSize        = SIZE_512KiB,
5691 +               .CmdSet         = P_ID_AMD_STD,
5692 +               .NumEraseRegions= 4,
5693 +               .regions        = {
5694 +                       ERASEINFO(0x04000,1),
5695 +                       ERASEINFO(0x02000,2),
5696 +                       ERASEINFO(0x08000,1),
5697 +                       ERASEINFO(0x10000,7)
5698 +               }
5699 +       }, {
5700 +               .mfr_id         = MANUFACTURER_AMD,
5701 +               .dev_id         = AM29LV400BT,
5702 +               .name           = "AMD AM29LV400BT",
5703 +               .uaddr          = {
5704 +                       [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
5705 +                       [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
5706 +               },
5707 +               .DevSize        = SIZE_512KiB,
5708 +               .CmdSet         = P_ID_AMD_STD,
5709 +               .NumEraseRegions= 4,
5710 +               .regions        = {
5711 +                       ERASEINFO(0x10000,7),
5712 +                       ERASEINFO(0x08000,1),
5713 +                       ERASEINFO(0x02000,2),
5714 +                       ERASEINFO(0x04000,1)
5715 +               }
5716 +       }, {
5717 +               .mfr_id         = MANUFACTURER_AMD,
5718                 .dev_id         = AM29LV800BB,
5719                 .name           = "AMD AM29LV800BB",
5720                 .uaddr          = {
5721 @@ -301,6 +359,45 @@
5722                         ERASEINFO(0x10000,15),
5723                 }
5724         }, {
5725 +/* add DL */
5726 +               .mfr_id         = MANUFACTURER_AMD,
5727 +               .dev_id         = AM29DL800BB,
5728 +               .name           = "AMD AM29DL800BB",
5729 +               .uaddr          = {
5730 +                       [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
5731 +                       [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
5732 +               },
5733 +               .DevSize        = SIZE_1MiB,
5734 +               .CmdSet         = P_ID_AMD_STD,
5735 +               .NumEraseRegions= 6,
5736 +               .regions        = {
5737 +                       ERASEINFO(0x04000,1),
5738 +                       ERASEINFO(0x08000,1),
5739 +                       ERASEINFO(0x02000,4),
5740 +                       ERASEINFO(0x08000,1),
5741 +                       ERASEINFO(0x04000,1),
5742 +                       ERASEINFO(0x10000,14)
5743 +               }
5744 +       }, {
5745 +               .mfr_id         = MANUFACTURER_AMD,
5746 +               .dev_id         = AM29DL800BT,
5747 +               .name           = "AMD AM29DL800BT",
5748 +               .uaddr          = {
5749 +                       [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
5750 +                       [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
5751 +               },
5752 +               .DevSize        = SIZE_1MiB,
5753 +               .CmdSet         = P_ID_AMD_STD,
5754 +               .NumEraseRegions= 6,
5755 +               .regions        = {
5756 +                       ERASEINFO(0x10000,14),
5757 +                       ERASEINFO(0x04000,1),
5758 +                       ERASEINFO(0x08000,1),
5759 +                       ERASEINFO(0x02000,4),
5760 +                       ERASEINFO(0x08000,1),
5761 +                       ERASEINFO(0x04000,1)
5762 +               }
5763 +       }, {
5764                 .mfr_id         = MANUFACTURER_AMD,
5765                 .dev_id         = AM29F800BB,
5766                 .name           = "AMD AM29F800BB",
5767 @@ -417,6 +514,17 @@
5768                         ERASEINFO(0x10000,8),
5769                 }
5770         }, {
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)
5780 +               }
5781 +       }, {
5782                 .mfr_id         = MANUFACTURER_ATMEL,
5783                 .dev_id         = AT49BV512,
5784                 .name           = "Atmel AT49BV512",
5785 @@ -505,6 +613,19 @@
5786                 }
5787         }, {
5788                 .mfr_id         = MANUFACTURER_FUJITSU,
5789 +               .dev_id         = MBM29F040C,
5790 +               .name           = "Fujitsu MBM29F040C",
5791 +               .uaddr          = {
5792 +                       [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
5793 +               },
5794 +               .DevSize        = SIZE_512KiB,
5795 +               .CmdSet         = P_ID_AMD_STD,
5796 +               .NumEraseRegions= 1,
5797 +               .regions        = {
5798 +                       ERASEINFO(0x10000,8)
5799 +               }
5800 +       }, {
5801 +               .mfr_id         = MANUFACTURER_FUJITSU,
5802                 .dev_id         = MBM29LV650UE,
5803                 .name           = "Fujitsu MBM29LV650UE",
5804                 .uaddr          = {
5805 @@ -615,6 +736,51 @@
5806                         ERASEINFO(0x04000,1)
5807                 }
5808         }, {
5809 +               .mfr_id         = MANUFACTURER_FUJITSU,
5810 +               .dev_id         = MBM29LV400BC,
5811 +               .name           = "Fujitsu MBM29LV400BC",
5812 +               .uaddr          = {
5813 +                       [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
5814 +                       [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
5815 +               },
5816 +               .DevSize        = SIZE_512KiB,
5817 +               .CmdSet         = P_ID_AMD_STD,
5818 +               .NumEraseRegions= 4,
5819 +               .regions        = {
5820 +                       ERASEINFO(0x04000,1),
5821 +                       ERASEINFO(0x02000,2),
5822 +                       ERASEINFO(0x08000,1),
5823 +                       ERASEINFO(0x10000,7)
5824 +               }
5825 +       }, {
5826 +               .mfr_id         = MANUFACTURER_FUJITSU,
5827 +               .dev_id         = MBM29LV400TC,
5828 +               .name           = "Fujitsu MBM29LV400TC",
5829 +               .uaddr          = {
5830 +                       [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
5831 +                       [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
5832 +               },
5833 +               .DevSize        = SIZE_512KiB,
5834 +               .CmdSet         = P_ID_AMD_STD,
5835 +               .NumEraseRegions= 4,
5836 +               .regions        = {
5837 +                       ERASEINFO(0x10000,7),
5838 +                       ERASEINFO(0x08000,1),
5839 +                       ERASEINFO(0x02000,2),
5840 +                       ERASEINFO(0x04000,1)
5841 +               }
5842 +       }, {
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)
5852 +               }
5853 +       }, {
5854                 .mfr_id         = MANUFACTURER_INTEL,
5855                 .dev_id         = I28F004B3B,
5856                 .name           = "Intel 28F004B3B",
5857 @@ -920,6 +1086,19 @@
5858                 }
5859         }, {
5860                 .mfr_id         = MANUFACTURER_MACRONIX,
5861 +               .dev_id         = MX29LV040C,
5862 +               .name           = "Macronix MX29LV040C",
5863 +               .uaddr          = {
5864 +                       [0] = MTD_UADDR_0x0555_0x02AA,  /* x8 */
5865 +               },
5866 +               .DevSize        = SIZE_512KiB,
5867 +               .CmdSet         = P_ID_AMD_STD,
5868 +               .NumEraseRegions= 1,
5869 +               .regions        = {
5870 +                       ERASEINFO(0x10000,8),
5871 +               }
5872 +       }, {
5873 +               .mfr_id         = MANUFACTURER_MACRONIX,
5874                 .dev_id         = MX29LV160T,
5875                 .name           = "MXIC MX29LV160T",
5876                 .uaddr          = {
5877 @@ -998,6 +1177,17 @@
5878                         ERASEINFO(0x10000,7),
5879                 }
5880         }, {
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)
5890 +               }
5891 +       }, {
5892                 .mfr_id         = MANUFACTURER_PMC,
5893                 .dev_id         = PM49FL002,
5894                 .name           = "PMC Pm49FL002",
5895 @@ -1064,6 +1254,30 @@
5896                 }
5897          }, {
5898                 .mfr_id         = MANUFACTURER_SST,
5899 +               .dev_id         = SST29EE020,
5900 +               .name           = "SST 29EE020",
5901 +               .uaddr          = {
5902 +                       [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
5903 +               },
5904 +               .DevSize        = SIZE_256KiB,
5905 +               .CmdSet         = P_ID_SST_PAGE,
5906 +               .NumEraseRegions= 1,
5907 +               regions: {ERASEINFO(0x01000,64),
5908 +               }
5909 +         }, {
5910 +               .mfr_id         = MANUFACTURER_SST,
5911 +               .dev_id         = SST29LE020,
5912 +               .name           = "SST 29LE020",
5913 +               .uaddr          = {
5914 +                       [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
5915 +               },
5916 +               .DevSize        = SIZE_256KiB,
5917 +               .CmdSet         = P_ID_SST_PAGE,
5918 +               .NumEraseRegions= 1,
5919 +               regions: {ERASEINFO(0x01000,64),
5920 +               }
5921 +       }, {
5922 +               .mfr_id         = MANUFACTURER_SST,
5923                 .dev_id         = SST39LF020,
5924                 .name           = "SST 39LF020",
5925                 .uaddr          = {
5926 @@ -1116,6 +1330,32 @@
5927                 }
5928         }, {
5929                 .mfr_id         = MANUFACTURER_SST,
5930 +               .dev_id         = SST49LF004B,
5931 +               .name           = "SST 49LF004B",
5932 +               .uaddr          = {
5933 +                       [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
5934 +               },
5935 +               .DevSize        = SIZE_512KiB,
5936 +               .CmdSet         = P_ID_AMD_STD,
5937 +               .NumEraseRegions= 1,
5938 +               .regions        = {
5939 +                       ERASEINFO(0x01000,128),
5940 +               }
5941 +       }, {
5942 +               .mfr_id         = MANUFACTURER_SST,
5943 +               .dev_id         = SST49LF008A,
5944 +               .name           = "SST 49LF008A",
5945 +               .uaddr          = {
5946 +                       [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
5947 +               },
5948 +               .DevSize        = SIZE_1MiB,
5949 +               .CmdSet         = P_ID_AMD_STD,
5950 +               .NumEraseRegions= 1,
5951 +               .regions        = {
5952 +                       ERASEINFO(0x01000,256),
5953 +               }
5954 +       }, {
5955 +               .mfr_id         = MANUFACTURER_SST,
5956                 .dev_id         = SST49LF030A,
5957                 .name           = "SST 49LF030A",
5958                 .uaddr          = {
5959 @@ -1154,6 +1394,22 @@
5960                         ERASEINFO(0x01000,256),
5961                 }
5962         }, {
5963 +               .mfr_id         = MANUFACTURER_SST,     /* should be CFI */
5964 +               .dev_id         = SST39LF160,
5965 +               .name           = "SST 39LF160",
5966 +               .uaddr          = {
5967 +                       [0] = MTD_UADDR_0x5555_0x2AAA,  /* x8 */
5968 +                       [1] = MTD_UADDR_0x5555_0x2AAA   /* x16 */
5969 +               },
5970 +               .DevSize        = SIZE_2MiB,
5971 +               .CmdSet         = P_ID_AMD_STD,
5972 +               .NumEraseRegions= 2,
5973 +               .regions        = {
5974 +                       ERASEINFO(0x1000,256),
5975 +                       ERASEINFO(0x1000,256)
5976 +               }
5977 +
5978 +       }, {
5979                 .mfr_id         = MANUFACTURER_ST,      /* FIXME - CFI device? */
5980                 .dev_id         = M29W800DT,
5981                 .name           = "ST M29W800DT",
5982 @@ -1234,6 +1490,58 @@
5983                 .regions        = {
5984                         ERASEINFO(0x10000,8),
5985                 }
5986 +        }, {
5987 +               .mfr_id         = MANUFACTURER_ST,
5988 +               .dev_id         = M50FW040,
5989 +               .name           = "ST M50FW040",
5990 +               .uaddr          = {
5991 +                       [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
5992 +               },
5993 +               .DevSize        = SIZE_512KiB,
5994 +               .CmdSet         = P_ID_INTEL_EXT,
5995 +               .NumEraseRegions= 1,
5996 +               .regions        = {
5997 +                       ERASEINFO(0x10000,8),
5998 +               }
5999 +        }, {
6000 +               .mfr_id         = MANUFACTURER_ST,
6001 +               .dev_id         = M50FW080,
6002 +               .name           = "ST M50FW080",
6003 +               .uaddr          = {
6004 +                       [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
6005 +               },
6006 +               .DevSize        = SIZE_1MiB,
6007 +               .CmdSet         = P_ID_INTEL_EXT,
6008 +               .NumEraseRegions= 1,
6009 +               .regions        = {
6010 +                       ERASEINFO(0x10000,16),
6011 +               }
6012 +        }, {
6013 +               .mfr_id         = MANUFACTURER_ST,
6014 +               .dev_id         = M50FW016,
6015 +               .name           = "ST M50FW016",
6016 +               .uaddr          = {
6017 +                       [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
6018 +               },
6019 +               .DevSize        = SIZE_2MiB,
6020 +               .CmdSet         = P_ID_INTEL_EXT,
6021 +               .NumEraseRegions= 1,
6022 +               .regions        = {
6023 +                       ERASEINFO(0x10000,32),
6024 +               }
6025 +       }, {
6026 +               .mfr_id         = MANUFACTURER_ST,
6027 +               .dev_id         = M50LPW080,
6028 +               .name           = "ST M50LPW080",
6029 +               .uaddr          = {
6030 +                       [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
6031 +               },
6032 +               .DevSize        = SIZE_1MiB,
6033 +               .CmdSet         = P_ID_INTEL_EXT,
6034 +               .NumEraseRegions= 1,
6035 +               .regions        = {
6036 +                       ERASEINFO(0x10000,16),
6037 +               }
6038         }, {
6039                 .mfr_id         = MANUFACTURER_TOSHIBA,
6040                 .dev_id         = TC58FVT160,
6041 @@ -1344,44 +1652,59 @@
6042                         ERASEINFO(0x02000, 2),
6043                         ERASEINFO(0x04000, 1),
6044                 }
6045 -       } 
6046 +       }
6047  };
6048  
6049  
6050  static int cfi_jedec_setup(struct cfi_private *p_cfi, int index);
6051  
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);
6055  
6056  struct mtd_info *jedec_probe(struct map_info *map);
6057  
6058  static inline u32 jedec_read_mfr(struct map_info *map, __u32 base, 
6059         struct cfi_private *cfi)
6060  {
6061 -       u32 result, mask;
6062 +       map_word result;
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);
6067 -       result &= mask;
6068 -       return result;
6069 +       result = map_read(map, base + ofs);
6070 +       return result.x[0] & mask;
6071  }
6072  
6073  static inline u32 jedec_read_id(struct map_info *map, __u32 base, 
6074         struct cfi_private *cfi)
6075  {
6076 -       int osf;
6077 -       u32 result, mask;
6078 -       osf = cfi->interleave *cfi->device_type;
6079 +       map_word result;
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);
6084 -       result &= mask;
6085 -       return result;
6086 +       result = map_read(map, base + ofs);
6087 +       return result.x[0] & mask;
6088  }
6089  
6090  static inline void jedec_reset(u32 base, struct map_info *map, 
6091         struct cfi_private *cfi)
6092  {
6093         /* Reset */
6094 -       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
6095 +
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);
6108 +       }
6109 +
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 @@
6115  
6116         uaddr = finfo->uaddr[uaddr_idx];
6117  
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];
6122 +       }
6123 +
6124   uaddr_done:
6125         return uaddr;
6126  }
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];
6130         }
6131 -       p_cfi->cmdset_priv = 0;
6132 +       p_cfi->cmdset_priv = NULL;
6133  
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;
6137  
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 );
6142                 return 0;
6143         }
6144 +
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;
6148  
6149 @@ -1473,8 +1804,35 @@
6150         u32 mfr, id;
6151         __u8 uaddr;
6152  
6153 -       /* The ID's must match */
6154 -       if ( cfi->mfr != finfo->mfr_id || cfi->id != finfo->dev_id ) {
6155 +       /*
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.
6163 +        */
6164 +       switch (cfi->device_type) {
6165 +       case CFI_DEVICETYPE_X8:
6166 +               mfr = (__u8)finfo->mfr_id;
6167 +               id = (__u8)finfo->dev_id;
6168 +               break;
6169 +       case CFI_DEVICETYPE_X16:
6170 +               mfr = (__u16)finfo->mfr_id;
6171 +               id = (__u16)finfo->dev_id;
6172 +               break;
6173 +       case CFI_DEVICETYPE_X32:
6174 +               mfr = (__u16)finfo->mfr_id;
6175 +               id = (__u32)finfo->dev_id;
6176 +               break;
6177 +       default:
6178 +               printk(KERN_WARNING
6179 +                      "MTD %s(): Unsupported device type %d\n",
6180 +                      __func__, cfi->device_type);
6181 +               goto match_done;
6182 +       }
6183 +       if ( cfi->mfr != mfr || cfi->id != id ) {
6184                 goto match_done;
6185         }
6186  
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 @@
6197         }
6198  
6199         uaddr = finfo_uaddr(finfo, cfi->device_type);
6200 -       if ( MTD_UADDR_NOT_SUPPORTED ) {
6201 +       if ( uaddr == MTD_UADDR_NOT_SUPPORTED ) {
6202                 goto match_done;
6203         }
6204  
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",
6214 -                      __func__,
6215 -                      unlock_addrs[uaddr].addr1,
6216 -                      unlock_addrs[uaddr].addr2 );
6217 +                       "MTD %s(): 0x%.4x 0x%.4x did not match\n",
6218 +                       __func__,
6219 +                       unlock_addrs[uaddr].addr1,
6220 +                       unlock_addrs[uaddr].addr2);
6221                 goto match_done;
6222         }
6223  
6224 @@ -1540,10 +1898,10 @@
6225          */
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);
6232         }
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 */
6236  
6237   match_done:   
6238 @@ -1552,41 +1910,24 @@
6239  
6240  
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)
6244  {
6245         int i;
6246 -       int unlockpass = 0;
6247 +       enum uaddr uaddr_idx = MTD_UADDR_NOT_SUPPORTED;
6248 +       u32 probe_offset1, probe_offset2;
6249  
6250 -       /*
6251 -        * FIXME - eventually replace these unlock address seeds with
6252 -        * information from unlock_addrs[].
6253 -        */
6254 + retry:
6255         if (!cfi->numchips) {
6256 -               switch (cfi->device_type) {
6257 -               case CFI_DEVICETYPE_X8:
6258 -                       cfi->addr_unlock1 = 0x555;
6259 -                       cfi->addr_unlock2 = 0x2aa;
6260 -                       break;
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;
6266 -                       } else {
6267 -                               cfi->addr_unlock2 = 0x554;
6268 -                       }
6269 -                       break;
6270 -               case CFI_DEVICETYPE_X32:
6271 -                       cfi->addr_unlock1 = 0x1555; 
6272 -                       cfi->addr_unlock2 = 0xaaa; 
6273 -                       break;
6274 -               default:
6275 -                       printk(KERN_NOTICE "Eep. Unknown jedec_probe device type %d\n", cfi->device_type);
6276 -               return 0;
6277 -               }
6278 +               uaddr_idx++;
6279 +
6280 +               if (MTD_UADDR_UNNECESSARY == uaddr_idx)
6281 +                       return 0;
6282 +
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;
6286         }
6287  
6288 - retry:
6289         /* Make certain we aren't probing past the end of map */
6290         if (base >= map->size) {
6291                 printk(KERN_NOTICE
6292 @@ -1595,30 +1936,30 @@
6293                 return 0;
6294                 
6295         }
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);
6300 -
6301 -               return 0;
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))
6313 +       {
6314 +               goto retry;
6315         }
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);
6320 -               return 0;
6321                 
6322 -       }
6323 -
6324         /* Reset */
6325         jedec_reset(base, map, cfi);
6326  
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);
6333         }
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 */
6337  
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 @@
6352                                 goto ok_out;
6353                         }
6354                 }
6355 -               switch(unlockpass++) {
6356 -               case 0:
6357 -                       cfi->addr_unlock1 |= cfi->addr_unlock1 << 4;
6358 -                       cfi->addr_unlock2 |= cfi->addr_unlock2 << 4;
6359 -                       goto retry;
6360 -               case 1:
6361 -                       cfi->addr_unlock1 = cfi->addr_unlock2 = 0;
6362 -                       goto retry;
6363 -               }
6364 -               return 0;
6365 +               goto retry;
6366         } else {
6367                 __u16 mfr;
6368                 __u16 id;
6369 @@ -1668,21 +1999,24 @@
6370                 }
6371         }
6372         
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 */
6384 +               }
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);
6392  
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);
6399                                 return 0;
6400                         }
6401                         
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);
6408                                 return 0;
6409                         }
6410                 }
6411 @@ -1702,22 +2036,16 @@
6412                 
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 */
6418 -               return -1;
6419 -       }
6420 -       chips[cfi->numchips].start = base;
6421 -       chips[cfi->numchips].state = FL_READY;
6422 +       set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
6423         cfi->numchips++;
6424                 
6425  ok_out:
6426         /* Put it back into Read Mode */
6427         jedec_reset(base, map, cfi);
6428  
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, 
6431 -              map->buswidth*8);
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);
6435         
6436         return 1;
6437  }
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
6442 @@ -1,7 +1,7 @@
6443  /*
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 $
6448   */
6449  
6450  #include <linux/module.h>
6451 @@ -104,13 +104,17 @@
6452         /* Yeah, it's inefficient. Who cares? It's faster than a _real_
6453            flash erase. */
6454         struct map_info *map = (struct map_info *)mtd->priv;
6455 +       map_word allff;
6456         unsigned long i;
6457  
6458 -       for (i=0; i<instr->len; i++)
6459 -               map_write8(map, 0xFF, instr->addr + i);
6460 +       allff = map_word_ff(map);
6461  
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);
6466 +
6467 +       instr->state = MTD_ERASE_DONE;
6468 +
6469 +       mtd_erase_callback(instr);
6470  
6471         return 0;
6472  }
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
6477 @@ -1,7 +1,7 @@
6478  /*
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 $
6483   */
6484  
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
6490 @@ -4,7 +4,7 @@
6491   * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
6492   *           2000,2001 Lineo, Inc.
6493   *
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 $
6496   *
6497   * Devices supported:
6498   *   LH28F016SCT Symmetrical block flash memory, 2Mx8
6499 @@ -30,6 +30,7 @@
6500  #include <linux/mtd/mtd.h>
6501  #include <linux/mtd/cfi.h>
6502  #include <linux/delay.h>
6503 +#include <linux/init.h>
6504  
6505  #define CMD_RESET              0xffffffff
6506  #define CMD_READ_ID            0x90909090
6507 @@ -154,7 +155,7 @@
6508         map->fldrv = &sharp_chipdrv;
6509         map->fldrv_priv = sharp;
6510  
6511 -       MOD_INC_USE_COUNT;
6512 +       __module_get(THIS_MODULE);
6513         return mtd;
6514  }
6515  
6516 @@ -424,8 +425,7 @@
6517         }
6518  
6519         instr->state = MTD_ERASE_DONE;
6520 -       if(instr->callback)
6521 -               instr->callback(instr);
6522 +       mtd_erase_callback(instr);
6523  
6524         return 0;
6525  }
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
6530 @@ -1,5 +1,5 @@
6531  /*
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 $
6534   *
6535   * Read flash partition table from command line
6536   *
6537 @@ -10,7 +10,7 @@
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 ')'
6545   * 
6546 @@ -94,7 +94,7 @@
6547                 if (size < PAGE_SIZE)
6548                 {
6549                         printk(KERN_ERR ERRP "partition size too small (%lx)\n", size);
6550 -                       return 0;
6551 +                       return NULL;
6552                 }
6553         }
6554  
6555 @@ -121,7 +121,7 @@
6556                 if ((p = strchr(name, delim)) == 0)
6557                 {
6558                         printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
6559 -                       return 0;
6560 +                       return NULL;
6561                 }
6562                 name_len = p - name;
6563                 s = p + 1;
6564 @@ -148,12 +148,12 @@
6565                 if (size == SIZE_REMAINING)
6566                 {
6567                         printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n");
6568 -                       return 0;
6569 +                       return NULL;
6570                 }
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)
6574 -                 return 0;
6575 +                 return NULL;
6576         }
6577         else
6578         {       /* this is the last partition: allocate space for all */
6579 @@ -166,7 +166,7 @@
6580                 if (!parts)
6581                 {
6582                         printk(KERN_ERR ERRP "out of memory\n");
6583 -                       return 0;
6584 +                       return NULL;
6585                 }
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);
6590  }
6591  
6592 -static void __exit cmdline_parser_exit(void)
6593 -{
6594 -       deregister_mtd_parser(&cmdline_parser);
6595 -}
6596 -
6597  module_init(cmdline_parser_init);
6598 -module_exit(cmdline_parser_exit);
6599 -
6600  
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
6607 @@ -1,5 +1,5 @@
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 $
6611  
6612  menu "Self-contained MTD device drivers"
6613         depends on MTD!=n
6614 @@ -40,9 +40,12 @@
6615  
6616  config MTD_MS02NV
6617         tristate "DEC MS02-NV NVRAM module support"
6618 -       depends on CONFIG_DECSTATION
6619 +       depends on MTD && MACH_DECSTATION
6620         help
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.
6626  
6627  config MTD_SLRAM
6628         tristate "Uncached system RAM"
6629 @@ -52,6 +55,16 @@
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.
6632  
6633 +config MTD_PHRAM
6634 +       tristate "Physical system RAM"
6635 +       depends on MTD
6636 +       help
6637 +         This is a re-implementation of the slram driver above.
6638 +
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...
6642 +
6643  config MTD_LART
6644         tristate "28F160xx flash driver for LART"
6645         depends on SA1100_LART && MTD
6646 @@ -115,7 +128,7 @@
6647  comment "Disk-On-Chip Device Drivers"
6648  
6649  config MTD_DOC2000
6650 -       tristate "M-Systems Disk-On-Chip 2000 and Millennium"
6651 +       tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)"
6652         depends on MTD
6653         ---help---
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
6657           chips.
6658  
6659 +         NOTE: This driver is deprecated and will probably be removed soon.
6660 +         Please try the new DiskOnChip driver under "NAND Flash Device
6661 +         Drivers".
6662 +
6663  config MTD_DOC2001
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)"
6666         depends on MTD
6667         ---help---
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
6671           chips.
6672  
6673 +         NOTE: This driver is deprecated and will probably be removed soon.
6674 +         Please try the new DiskOnChip driver under "NAND Flash Device
6675 +         Drivers".
6676 +
6677  config MTD_DOC2001PLUS
6678         tristate "M-Systems Disk-On-Chip Millennium Plus"
6679         depends on MTD
6680 @@ -159,12 +180,23 @@
6681           to emulate a block device by using a kind of file system on the 
6682           flash chips.
6683  
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).
6687 +
6688  config MTD_DOCPROBE
6689         tristate
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
6693         help
6694 -         This isn't a real config option, it's derived.
6695 +         This isn't a real config option; it's derived.
6696 +
6697 +config MTD_DOCECC
6698 +       tristate
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
6701 +       help
6702 +         This isn't a real config option; it's derived.
6703  
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
6710 @@ -1,7 +1,7 @@
6711  #
6712  # linux/drivers/devices/Makefile
6713  #
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 $
6716  
6717  #                       *** BIG UGLY NOTE ***
6718  #
6719 @@ -13,8 +13,10 @@
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
6735 @@ -0,0 +1,1056 @@
6736 +/*
6737 + * $Id: blkmtd-24.c,v 1.23 2004/08/09 18:49:42 dmarlin Exp $
6738 + *
6739 + * blkmtd.c - use a block device as a fake MTD
6740 + *
6741 + * Author: Simon Evans <spse@secret.org.uk>
6742 + *
6743 + * Copyright (C) 2001,2002 Simon Evans
6744 + *
6745 + * Licence: GPL
6746 + *
6747 + * How it works:
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
6754 + *     write cache.
6755 + *
6756 + *     It can be loaded Read-Only to prevent erases and writes to the
6757 + *     medium.
6758 + *
6759 + */
6760 +
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>
6770 +
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;
6776 +#endif
6777 +#endif
6778 +
6779 +
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)
6784 +
6785 +
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"
6789 +
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;
6796 +       long iobuf_locks;
6797 +       struct semaphore wrbuf_mutex;
6798 +};
6799 +
6800 +
6801 +/* Static info about the MTD, used in cleanup_module */
6802 +static LIST_HEAD(blkmtd_device_list);
6803 +
6804 +
6805 +static void blkmtd_sync(struct mtd_info *mtd);
6806 +
6807 +#define MAX_DEVICES 4
6808 +
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 */
6813 +int sync;
6814 +
6815 +
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");
6827 +
6828 +
6829 +/**
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
6835 + *
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.
6839 + */
6840 +static int read_pages(struct blkmtd_dev *dev, int pagenrs[], struct page **pagelst, int pages)
6841 +{
6842 +       kdev_t kdev;
6843 +       struct page *page;
6844 +       int cnt = 0;
6845 +       struct kiobuf *iobuf;
6846 +       int err = 0;
6847 +
6848 +       if(!dev) {
6849 +               err("read_pages: PANIC dev == NULL");
6850 +               return -EIO;
6851 +       }
6852 +       kdev = to_kdev_t(dev->binding->bd_dev);
6853 +
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);
6857 +               if (err) {
6858 +                       crit("cant allocate kiobuf");
6859 +                       return -ENOMEM;
6860 +               }
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);
6866 +                       return -ENOMEM;
6867 +               }
6868 +#endif
6869 +       } else {
6870 +               iobuf = dev->rd_buf;
6871 +       }
6872 +
6873 +       iobuf->nr_pages = 0;
6874 +       iobuf->length = 0;
6875 +       iobuf->offset = 0;
6876 +       iobuf->locked = 1;
6877 +       
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;
6884 +               }
6885 +       }
6886 +
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);
6891 +               if(err < 0) {
6892 +                       while(pages--) {
6893 +                               ClearPageUptodate(pagelst[pages]);
6894 +                               unlock_page(pagelst[pages]);
6895 +                               page_cache_release(pagelst[pages]);
6896 +                       }
6897 +               } else {
6898 +                       while(iobuf->nr_pages--) {
6899 +                               SetPageUptodate(iobuf->maplist[iobuf->nr_pages]);
6900 +                       }
6901 +                       err = 0;
6902 +               }
6903 +       }
6904 +
6905 +
6906 +       if(iobuf != dev->rd_buf) {
6907 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
6908 +               kfree(iobuf->blocks);
6909 +#endif
6910 +               free_kiovec(1, &iobuf);
6911 +       } else {
6912 +               clear_bit(0, &dev->iobuf_locks);
6913 +       }
6914 +       DEBUG(2, "read_pages: done, err = %d\n", err);
6915 +       return err;
6916 +}
6917 +
6918 +
6919 +/**
6920 + * commit_pages - commit pages in the writeout kiobuf to disk
6921 + * @dev: device to write to
6922 + *
6923 + * If the current dev has pages in the dev->wr_buf kiobuf,
6924 + * they are written to disk using brw_kiovec()
6925 + */
6926 +static int commit_pages(struct blkmtd_dev *dev)
6927 +{
6928 +       struct kiobuf *iobuf = dev->wr_buf;
6929 +       kdev_t kdev = to_kdev_t(dev->binding->bd_dev);
6930 +       int err = 0;
6931 +
6932 +       iobuf->length = iobuf->nr_pages << PAGE_SHIFT;
6933 +       iobuf->locked = 1;
6934 +       if(iobuf->length) {
6935 +               int i;
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));
6941 +                       lock_page(page);
6942 +               }
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);
6951 +               }
6952 +       }
6953 +
6954 +       DEBUG(2, "blkmtd: sync: end, err = %d\n", err);
6955 +       iobuf->offset = 0;
6956 +       iobuf->nr_pages = 0;
6957 +       iobuf->length = 0;
6958 +       return err;
6959 +}
6960 +
6961 +
6962 +/**
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
6969 + *
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.
6975 + */
6976 +static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to,
6977 +                   size_t len, int *retlen)
6978 +{
6979 +       int pagenr, offset;
6980 +       size_t start_len = 0, end_len;
6981 +       int pagecnt = 0;
6982 +       struct kiobuf *iobuf = dev->wr_buf;
6983 +       int err = 0;
6984 +       struct page *pagelst[2];
6985 +       int pagenrs[2];
6986 +       int readpages = 0;
6987 +       int ignorepage = -1;
6988 +
6989 +       pagenr = to >> PAGE_SHIFT;
6990 +       offset = to & ~PAGE_MASK;
6991 +
6992 +       DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %zd pagenr = %d offset = %d\n",
6993 +             buf, (long)to, len, pagenr, offset);
6994 +
6995 +       *retlen = 0;
6996 +       /* see if we have to do a partial write at the start */
6997 +       if(offset) {
6998 +               start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len;
6999 +               len -= start_len;
7000 +       }
7001 +
7002 +       /* calculate the length of the other two regions */
7003 +       end_len = len & ~PAGE_MASK;
7004 +       len -= end_len;
7005 +
7006 +       if(start_len) {
7007 +               pagenrs[0] = pagenr;
7008 +               readpages++;
7009 +               pagecnt++;
7010 +       }
7011 +       if(len)
7012 +               pagecnt += len >> PAGE_SHIFT;
7013 +       if(end_len) {
7014 +               pagenrs[readpages] = pagenr + pagecnt;
7015 +               readpages++;
7016 +               pagecnt++;
7017 +       }
7018 +
7019 +       DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n",
7020 +             start_len, len, end_len, pagecnt);
7021 +
7022 +       down(&dev->wrbuf_mutex);
7023 +
7024 +       if(iobuf->nr_pages && ((pagenr <= iobuf->blocks[iobuf->nr_pages-1])
7025 +                              || (iobuf->nr_pages + pagecnt) >= KIO_STATIC_PAGES)) {
7026 +
7027 +               if((pagenr == iobuf->blocks[iobuf->nr_pages-1])
7028 +                  && ((iobuf->nr_pages + pagecnt) < KIO_STATIC_PAGES)) {
7029 +                       iobuf->nr_pages--;
7030 +                       ignorepage = pagenr;
7031 +               } else {
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);
7036 +               }
7037 +       }
7038 +       
7039 +       if(readpages) {
7040 +               err = read_pages(dev, pagenrs, pagelst, readpages);
7041 +               if(err < 0)
7042 +                       goto readin_err;
7043 +       }
7044 +
7045 +       if(start_len) {
7046 +               /* do partial start region */
7047 +               struct page *page;
7048 +
7049 +               DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %zd offset = %d\n",
7050 +                     pagenr, start_len, offset);
7051 +               page = pagelst[0];
7052 +               BUG_ON(!buf);
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);
7056 +                       BUG();
7057 +               }
7058 +               memcpy(page_address(page)+offset, buf, start_len);
7059 +               SetPageDirty(page);
7060 +               SetPageUptodate(page);
7061 +               unlock_page(page);
7062 +               buf += start_len;
7063 +               *retlen = start_len;
7064 +               err = 0;
7065 +               iobuf->blocks[iobuf->nr_pages] = pagenr++;
7066 +               iobuf->maplist[iobuf->nr_pages] = page;
7067 +               iobuf->nr_pages++;
7068 +       }
7069 +
7070 +       /* Now do the main loop to a page aligned, n page sized output */
7071 +       if(len) {
7072 +               int pagesc = len >> PAGE_SHIFT;
7073 +               DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n",
7074 +                     pagenr, pagesc);
7075 +               while(pagesc) {
7076 +                       struct page *page;
7077 +
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) {
7082 +                               BUG();
7083 +                       }
7084 +                       if(!page) {
7085 +                               warn("write: cant grab cache page %d", pagenr);
7086 +                               err = -ENOMEM;
7087 +                               goto write_err;
7088 +                       }
7089 +                       if(!buf) {
7090 +                               memset(page_address(page), 0xff, PAGE_SIZE);
7091 +                       } else {
7092 +                               memcpy(page_address(page), buf, PAGE_SIZE);
7093 +                               buf += PAGE_SIZE;
7094 +                       }
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);
7101 +                       pagesc--;
7102 +                       *retlen += PAGE_SIZE;
7103 +               }
7104 +       }
7105 +
7106 +       if(end_len) {
7107 +               /* do the third region */
7108 +               struct page *page;
7109 +               DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %zd\n",
7110 +                     pagenr, end_len);
7111 +               page = pagelst[readpages-1];
7112 +               BUG_ON(!buf);
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);
7116 +                       BUG();
7117 +               }
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;
7124 +               err = 0;
7125 +               iobuf->blocks[iobuf->nr_pages] = pagenr;
7126 +               iobuf->maplist[iobuf->nr_pages] = page;
7127 +               iobuf->nr_pages++;
7128 +       }
7129 +
7130 +       DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err);
7131 +
7132 +       if(sync) {
7133 +write_err:
7134 +               commit_pages(dev);
7135 +       }
7136 +
7137 +readin_err:
7138 +       up(&dev->wrbuf_mutex);
7139 +       return err;
7140 +}
7141 +
7142 +
7143 +/* erase a specified part of the device */
7144 +static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr)
7145 +{
7146 +       struct blkmtd_dev *dev = mtd->priv;
7147 +       struct mtd_erase_region_info *einfo = mtd->eraseregions;
7148 +       int numregions = mtd->numeraseregions;
7149 +       size_t from;
7150 +       u_long len;
7151 +       int err = -EIO;
7152 +       size_t retlen;
7153 +
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;
7160 +       }
7161 +
7162 +       instr->state = MTD_ERASING;
7163 +       from = instr->addr;
7164 +       len = instr->len;
7165 +
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))
7176 +                               break;
7177 +               }
7178 +               numregions--;
7179 +               einfo++;
7180 +       }
7181 +
7182 +       if(!numregions) {
7183 +               /* Not a valid erase block */
7184 +               err("erase: invalid erase request 0x%lX @ 0x%08zX", len, from);
7185 +               instr->state = MTD_ERASE_FAILED;
7186 +               err = -EIO;
7187 +       }
7188 +
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);
7193 +               if(err < 0) {
7194 +                       err("erase failed err = %d", err);
7195 +                       instr->state = MTD_ERASE_FAILED;
7196 +               } else {
7197 +                       instr->state = MTD_ERASE_DONE;
7198 +                       err = 0;
7199 +               }
7200 +       }
7201 +
7202 +       DEBUG(3, "blkmtd: erase: checking callback\n");
7203 + erase_callback:
7204 +       mtd_erase_callback(instr);
7205 +       DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
7206 +       return err;
7207 +}
7208 +
7209 +
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)
7213 +{
7214 +       struct blkmtd_dev *dev = mtd->priv;
7215 +       int err = 0;
7216 +       int offset;
7217 +       int pagenr, pages;
7218 +       struct page **pagelst;
7219 +       int *pagenrs;
7220 +       int i;
7221 +
7222 +       *retlen = 0;
7223 +
7224 +       DEBUG(2, "blkmtd: read: dev = `%s' from = %lld len = %zd buf = %p\n",
7225 +             bdevname(dev->binding->bd_dev), from, len, buf);
7226 +
7227 +       pagenr = from >> PAGE_SHIFT;
7228 +       offset = from - (pagenr << PAGE_SHIFT);
7229 +
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);
7233 +
7234 +       pagelst = kmalloc(sizeof(struct page *) * pages, GFP_KERNEL);
7235 +       if(!pagelst)
7236 +               return -ENOMEM;
7237 +       pagenrs = kmalloc(sizeof(int) * pages, GFP_KERNEL);
7238 +       if(!pagenrs) {
7239 +               kfree(pagelst);
7240 +               return -ENOMEM;
7241 +       }
7242 +       for(i = 0; i < pages; i++)
7243 +               pagenrs[i] = pagenr+i;
7244 +
7245 +       err = read_pages(dev, pagenrs, pagelst, pages);
7246 +       if(err)
7247 +               goto readerr;
7248 +
7249 +       pagenr = 0;
7250 +       while(pages) {
7251 +               struct page *page;
7252 +               int cpylen;
7253 +
7254 +               DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr);
7255 +               page = pagelst[pagenr];
7256 +
7257 +               cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE;
7258 +               if(offset+cpylen > PAGE_SIZE)
7259 +                       cpylen = PAGE_SIZE-offset;
7260 +
7261 +               memcpy(buf + *retlen, page_address(page) + offset, cpylen);
7262 +               offset = 0;
7263 +               len -= cpylen;
7264 +               *retlen += cpylen;
7265 +               pagenr++;
7266 +               pages--;
7267 +               unlock_page(page);
7268 +               if(!PageDirty(page))
7269 +                       page_cache_release(page);
7270 +       }
7271 +
7272 + readerr:
7273 +       kfree(pagelst);
7274 +       kfree(pagenrs);
7275 +       DEBUG(2, "blkmtd: end read: retlen = %zd, err = %d\n", *retlen, err);
7276 +       return err;
7277 +}
7278 +
7279 +
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)
7283 +{
7284 +       struct blkmtd_dev *dev = mtd->priv;
7285 +       int err;
7286 +
7287 +       *retlen = 0;
7288 +       if(!len)
7289 +               return 0;
7290 +
7291 +       DEBUG(2, "blkmtd: write: dev = `%s' to = %lld len = %zd buf = %p\n",
7292 +             bdevname(dev->binding->bd_dev), to, len, buf);
7293 +
7294 +       /* handle readonly and out of range numbers */
7295 +
7296 +       if(!dev->wr_buf) {
7297 +               err("error: trying to write to a readonly device %s", mtd->name);
7298 +               return -EROFS;
7299 +       }
7300 +
7301 +       if(to >= mtd->size) {
7302 +               return -ENOSPC;
7303 +       }
7304 +
7305 +       if(to + len > mtd->size) {
7306 +               len = (mtd->size - to);
7307 +       }
7308 +
7309 +       err = write_pages(dev, buf, to, len, retlen);
7310 +       if(err < 0)
7311 +               *retlen = 0;
7312 +       else
7313 +               err = 0;
7314 +       DEBUG(2, "blkmtd: write: end, err = %d\n", err);
7315 +       return err;
7316 +}
7317 +
7318 +
7319 +/* sync the device - wait until the write queue is empty */
7320 +static void blkmtd_sync(struct mtd_info *mtd)
7321 +{
7322 +       struct blkmtd_dev *dev = mtd->priv;
7323 +       struct kiobuf *iobuf = dev->wr_buf;
7324 +
7325 +       DEBUG(2, "blkmtd: sync: called\n");
7326 +       if(iobuf == NULL)
7327 +               return;
7328 +
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);
7335 +}
7336 +
7337 +
7338 +#ifdef BLKMTD_PROC_DEBUG
7339 +/* procfs stuff */
7340 +static int blkmtd_proc_read(char *page, char **start, off_t off,
7341 +                           int count, int *eof, void *data)
7342 +{
7343 +       int len;
7344 +       struct list_head *temp1, *temp2;
7345 +
7346 +       MOD_INC_USE_COUNT;
7347 +
7348 +       /* Count the size of the page lists */
7349 +
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,
7353 +                                                   list);
7354 +               struct list_head *temp;
7355 +               struct page *pagei;
7356 +
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);
7361 +                       clean++;
7362 +                       if(PageLocked(pagei))
7363 +                               locked++;
7364 +                       if(PageDirty(pagei))
7365 +                               dirty++;
7366 +                       if(PageLRU(pagei))
7367 +                               lru++;
7368 +               }
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))
7372 +                               locked++;
7373 +                       if(PageDirty(pagei))
7374 +                               dirty++;
7375 +                       if(PageLRU(pagei))
7376 +                               lru++;
7377 +               }
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))
7381 +                               locked++;
7382 +                       if(PageDirty(pagei))
7383 +                               dirty++;
7384 +                       if(PageLRU(pagei))
7385 +                               lru++;
7386 +               }
7387 +
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);
7395 +       }
7396 +
7397 +       if(len <= count)
7398 +               *eof = 1;
7399 +
7400 +       MOD_DEC_USE_COUNT;
7401 +       return len;
7402 +}
7403 +#endif
7404 +
7405 +
7406 +static void free_device(struct blkmtd_dev *dev)
7407 +{
7408 +       DEBUG(2, "blkmtd: free_device() dev = %p\n", dev);
7409 +       if(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);
7417 +
7418 +               if(dev->rd_buf) {
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);
7423 +#endif
7424 +                       free_kiovec(1, &dev->rd_buf);
7425 +               }
7426 +               if(dev->wr_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);
7431 +#endif
7432 +                       free_kiovec(1, &dev->wr_buf);
7433 +               }
7434 +
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);
7440 +               }
7441 +               kfree(dev);
7442 +       }
7443 +}
7444 +
7445 +
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.
7450 + */
7451 +static struct mtd_erase_region_info *calc_erase_regions(
7452 +       size_t erase_size, size_t total_size, int *regions)
7453 +{
7454 +       struct mtd_erase_region_info *info = NULL;
7455 +
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 */
7460 +       if(erase_size) {
7461 +               int es = erase_size;
7462 +               erase_size = 1;
7463 +               while(es != 1) {
7464 +                       es >>= 1;
7465 +                       erase_size <<= 1;
7466 +               }
7467 +               if(erase_size < PAGE_SIZE)
7468 +                       erase_size = PAGE_SIZE;
7469 +       } else {
7470 +               erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
7471 +       }
7472 +
7473 +       *regions = 0;
7474 +
7475 +       do {
7476 +               int tot_size = total_size;
7477 +               int er_size = erase_size;
7478 +               int count = 0, offset = 0, regcnt = 0;
7479 +
7480 +               while(tot_size) {
7481 +                       count = tot_size / er_size;
7482 +                       if(count) {
7483 +                               tot_size = tot_size % er_size;
7484 +                               if(info) {
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;
7490 +                                       (*regions)++;
7491 +                               }
7492 +                               regcnt++;
7493 +                               offset += (count * er_size);
7494 +                       }
7495 +                       while(er_size > tot_size)
7496 +                               er_size >>= 1;
7497 +               }
7498 +               if(info == NULL) {
7499 +                       info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL);
7500 +                       if(!info)
7501 +                               break;
7502 +               }
7503 +       } while(!(*regions));
7504 +       DEBUG(2, "calc_erase_regions done, es = %zd size = %zd regions = %d\n",
7505 +             erase_size, total_size, *regions);
7506 +       return info;
7507 +}
7508 +
7509 +
7510 +extern kdev_t name_to_kdev_t(char *line) __init;
7511 +
7512 +
7513 +static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size)
7514 +{
7515 +       int maj, min;
7516 +       kdev_t kdev;
7517 +       int mode;
7518 +       struct blkmtd_dev *dev;
7519 +
7520 +#ifdef MODULE
7521 +       struct file *file = NULL;
7522 +       struct inode *inode;
7523 +#endif
7524 +
7525 +       if(!devname)
7526 +               return NULL;
7527 +
7528 +       /* Get a handle on the device */
7529 +       mode = (readonly) ? O_RDONLY : O_RDWR;
7530 +
7531 +#ifdef MODULE
7532 +
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));
7537 +               return NULL;
7538 +       }
7539 +
7540 +       /* determine is this is a block device and
7541 +        * if so get its major and minor numbers
7542 +        */
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);
7547 +               return NULL;
7548 +       }
7549 +       kdev = inode->i_rdev;
7550 +       filp_close(file, NULL);
7551 +#else
7552 +       kdev = name_to_kdev_t(devname);
7553 +#endif /* MODULE */
7554 +
7555 +       if(!kdev) {
7556 +               err("bad block device: `%s'", devname);
7557 +               return NULL;
7558 +       }
7559 +
7560 +       maj = MAJOR(kdev);
7561 +       min = MINOR(kdev);
7562 +       DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n",
7563 +             maj, min);
7564 +
7565 +       if(maj == MTD_BLOCK_MAJOR) {
7566 +               err("attempting to use an MTD device as a block device");
7567 +               return NULL;
7568 +       }
7569 +
7570 +       DEBUG(1, "blkmtd: devname = %s\n", bdevname(kdev));
7571 +
7572 +       dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL);
7573 +       if(dev == NULL)
7574 +               return NULL;
7575 +
7576 +       memset(dev, 0, sizeof(struct blkmtd_dev));
7577 +       if(alloc_kiovec(1, &dev->rd_buf)) {
7578 +               err("cant allocate read iobuf");
7579 +               goto devinit_err;
7580 +       }
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");
7585 +               goto devinit_err;
7586 +       }
7587 +#endif
7588 +       
7589 +       if(!readonly) {
7590 +               if(alloc_kiovec(1, &dev->wr_buf)) {
7591 +                       err("cant allocate kiobuf - readonly enabled");
7592 +
7593 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
7594 +               } else {
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);
7599 +                       }
7600 +#endif
7601 +               }
7602 +               if(dev->wr_buf)
7603 +                       init_MUTEX(&dev->wrbuf_mutex);
7604 +       }
7605 +
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))
7609 +               goto devinit_err;
7610 +
7611 +       if(set_blocksize(kdev, PAGE_SIZE)) {
7612 +               err("cant set block size to PAGE_SIZE on %s", bdevname(kdev));
7613 +               goto devinit_err;
7614 +       }
7615 +
7616 +       dev->mtd_info.size = dev->binding->bd_inode->i_size & PAGE_MASK;
7617 +
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)
7622 +               goto devinit_err;
7623 +
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)
7628 +               goto devinit_err;
7629 +
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);
7633 +
7634 +       if(readonly) {
7635 +               dev->mtd_info.type = MTD_ROM;
7636 +               dev->mtd_info.flags = MTD_CAP_ROM;
7637 +       } else {
7638 +               dev->mtd_info.type = MTD_RAM;
7639 +               dev->mtd_info.flags = MTD_CAP_RAM;
7640 +       }
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;
7649 +
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);
7654 +               free_device(dev);
7655 +               return NULL;
7656 +       } else {
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)");
7661 +       }
7662 +       
7663 +       return dev;
7664 +
7665 + devinit_err:
7666 +       free_device(dev);
7667 +       return NULL;
7668 +}
7669 +
7670 +
7671 +/* Cleanup and exit - sync the device and kill of the kernel thread */
7672 +static void __devexit cleanup_blkmtd(void)
7673 +{
7674 +       struct list_head *temp1, *temp2;
7675 +#ifdef BLKMTD_PROC_DEBUG
7676 +       if(blkmtd_proc) {
7677 +               remove_proc_entry("blkmtd_debug", NULL);
7678 +       }
7679 +#endif
7680 +
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,
7684 +                                                   list);
7685 +               blkmtd_sync(&dev->mtd_info);
7686 +               free_device(dev);
7687 +       }
7688 +}
7689 +
7690 +#ifndef MODULE
7691 +
7692 +/* Handle kernel boot params */
7693 +
7694 +
7695 +static int __init param_blkmtd_device(char *str)
7696 +{
7697 +       int i;
7698 +
7699 +       for(i = 0; i < MAX_DEVICES; i++) {
7700 +               device[i] = str;
7701 +               DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]);
7702 +               strsep(&str, ",");
7703 +       }
7704 +       return 1;
7705 +}
7706 +
7707 +
7708 +static int __init param_blkmtd_erasesz(char *str)
7709 +{
7710 +       int i;
7711 +       for(i = 0; i < MAX_DEVICES; i++) {
7712 +               char *val = strsep(&str, ",");
7713 +               if(val)
7714 +                       erasesz[i] = simple_strtoul(val, NULL, 0);
7715 +               DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]);
7716 +       }
7717 +
7718 +       return 1;
7719 +}
7720 +
7721 +
7722 +static int __init param_blkmtd_ro(char *str)
7723 +{
7724 +       int i;
7725 +       for(i = 0; i < MAX_DEVICES; i++) {
7726 +               char *val = strsep(&str, ",");
7727 +               if(val)
7728 +                       ro[i] = simple_strtoul(val, NULL, 0);
7729 +               DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]);
7730 +       }
7731 +
7732 +       return 1;
7733 +}
7734 +
7735 +
7736 +static int __init param_blkmtd_sync(char *str)
7737 +{
7738 +       if(str[0] == '1')
7739 +               sync = 1;
7740 +       return 1;
7741 +}
7742 +
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);
7747 +
7748 +#endif
7749 +
7750 +
7751 +/* Startup */
7752 +static int __init init_blkmtd(void)
7753 +{
7754 +       int i;
7755 +
7756 +       /* Check args - device[0] is the bare minimum*/
7757 +       if(!device[0]) {
7758 +               err("error: missing `device' name\n");
7759 +               return -EINVAL;
7760 +       }
7761 +
7762 +       for(i = 0; i < MAX_DEVICES; i++)
7763 +               add_device(device[i], ro[i], erasesz[i] << 10);
7764 +
7765 +       if(list_empty(&blkmtd_device_list))
7766 +               goto init_err;
7767 +
7768 +       info("version " VERSION);
7769 +
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");
7777 +       } else {
7778 +               blkmtd_proc->owner = THIS_MODULE;
7779 +       }
7780 +#endif
7781 +
7782 +       if(!list_empty(&blkmtd_device_list))
7783 +               /* Everything is ok if we got here */
7784 +               return 0;
7785 +
7786 + init_err:
7787 +       return -EINVAL;
7788 +}
7789 +
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
7796 @@ -1,5 +1,5 @@
7797  /*
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 $
7800   *
7801   * blkmtd.c - use a block device as a fake MTD
7802   *
7803 @@ -39,7 +39,7 @@
7804  
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 $"
7809  
7810  /* Info for the block device */
7811  struct blkmtd_dev {
7812 @@ -246,7 +246,7 @@
7813         pagenr = to >> PAGE_SHIFT;
7814         offset = to & ~PAGE_MASK;
7815  
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);
7819  
7820         /* see if we have to do a partial write at the start */
7821 @@ -270,21 +270,21 @@
7822  
7823         down(&dev->wrbuf_mutex);
7824  
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);
7828  
7829         if(start_len) {
7830                 /* do partial start region */
7831                 struct page *page;
7832  
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);
7836  
7837                 BUG_ON(!buf);
7838                 page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
7839                 lock_page(page);
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);
7844                         BUG();
7845                 }
7846 @@ -346,13 +346,13 @@
7847         if(end_len) {
7848                 /* do the third region */
7849                 struct page *page;
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",
7852                       pagenr, end_len);
7853                 BUG_ON(!buf);
7854                 page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
7855                 lock_page(page);
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);
7860                         BUG();
7861                 }
7862 @@ -375,7 +375,7 @@
7863         if(bio)
7864                 blkmtd_write_out(bio);
7865  
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);
7869  
7870         if(retlen)
7871 @@ -393,14 +393,14 @@
7872         size_t from;
7873         u_long len;
7874         int err = -EIO;
7875 -       int retlen;
7876 +       size_t retlen;
7877  
7878         instr->state = MTD_ERASING;
7879         from = instr->addr;
7880         len = instr->len;
7881  
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);
7886         while(numregions) {
7887                 DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n",
7888 @@ -417,14 +417,14 @@
7889  
7890         if(!numregions) {
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;
7895                 err = -EIO;
7896         }
7897  
7898         if(instr->state != MTD_ERASE_FAILED) {
7899                 /* do the erase */
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);
7905 @@ -435,9 +435,7 @@
7906         }
7907  
7908         DEBUG(3, "blkmtd: erase: checking callback\n");
7909 -       if (instr->callback) {
7910 -               (*(instr->callback))(instr);
7911 -       }
7912 +       mtd_erase_callback(instr);
7913         DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
7914         return err;
7915  }
7916 @@ -453,8 +451,8 @@
7917         int pagenr, pages;
7918         size_t thislen = 0;
7919  
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);
7924  
7925         if(from > mtd->size)
7926                 return -EINVAL;
7927 @@ -496,7 +494,7 @@
7928   readerr:
7929         if(retlen)
7930                 *retlen = thislen;
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);
7933         return err;
7934  }
7935  
7936 @@ -511,8 +509,8 @@
7937         if(!len)
7938                 return 0;
7939  
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);
7944  
7945         if(to >= mtd->size) {
7946                 return -ENOSPC;
7947 @@ -565,7 +563,7 @@
7948  {
7949         struct mtd_erase_region_info *info = NULL;
7950  
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 */
7956 @@ -613,7 +611,7 @@
7957                                 break;
7958                 }
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);
7963         return info;
7964  }
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
7969 @@ -4,7 +4,7 @@
7970   * (c) 1999 Machine Vision Holdings, Inc.
7971   * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
7972   *
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 $
7975   */
7976  
7977  #include <linux/kernel.h>
7978 @@ -19,12 +19,14 @@
7979  #include <linux/sched.h>
7980  #include <linux/init.h>
7981  #include <linux/types.h>
7982 +#include <linux/bitops.h>
7983  
7984  #include <linux/mtd/mtd.h>
7985  #include <linux/mtd/nand.h>
7986  #include <linux/mtd/doc2000.h>
7987  
7988  #define DOC_SUPPORT_2000
7989 +#define DOC_SUPPORT_2000TSOP
7990  #define DOC_SUPPORT_MILLENNIUM
7991  
7992  #ifdef DOC_SUPPORT_2000
7993 @@ -33,7 +35,7 @@
7994  #define DoC_is_2000(doc) (0)
7995  #endif
7996  
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)
8000  #else
8001  #define DoC_is_Millennium(doc) (0)
8002 @@ -53,9 +55,12 @@
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,
8017 @@ -84,7 +89,7 @@
8018  /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
8019  static int _DoC_WaitReady(struct DiskOnChip *doc)
8020  {
8021 -       unsigned long docptr = doc->virtadr;
8022 +       void __iomem *docptr = doc->virtadr;
8023         unsigned long timeo = jiffies + (HZ * 10);
8024  
8025         DEBUG(MTD_DEBUG_LEVEL3,
8026 @@ -92,6 +97,10 @@
8027  
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);
8033 +
8034                 if (time_after(jiffies, timeo)) {
8035                         DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
8036                         return -EIO;
8037 @@ -105,7 +114,8 @@
8038  
8039  static inline int DoC_WaitReady(struct DiskOnChip *doc)
8040  {
8041 -       unsigned long docptr = doc->virtadr;
8042 +       void __iomem *docptr = doc->virtadr;
8043 +
8044         /* This is inline, to optimise the common case, where it's ready instantly */
8045         int ret = 0;
8046  
8047 @@ -131,7 +141,7 @@
8048  static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command,
8049                               unsigned char xtraflags)
8050  {
8051 -       unsigned long docptr = doc->virtadr;
8052 +       void __iomem *docptr = doc->virtadr;
8053  
8054         if (DoC_is_2000(doc))
8055                 xtraflags |= CDSN_CTRL_FLASH_IO;
8056 @@ -145,6 +155,8 @@
8057  
8058         /* Send the command */
8059         WriteDOC_(command, docptr, doc->ioreg);
8060 +       if (DoC_is_Millennium(doc))
8061 +               WriteDOC(command, docptr, WritePipeTerm);
8062  
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)
8068  {
8069 -       unsigned long docptr;
8070         int i;
8071 -
8072 -       docptr = doc->virtadr;
8073 +       void __iomem *docptr = doc->virtadr;
8074  
8075         if (DoC_is_2000(doc))
8076                 xtraflags1 |= CDSN_CTRL_FLASH_IO;
8077 @@ -206,6 +216,9 @@
8078                 }
8079         }
8080  
8081 +       if (DoC_is_Millennium(doc))
8082 +               WriteDOC(ofs & 0xff, docptr, WritePipeTerm);
8083 +
8084         DoC_Delay(doc, 2);      /* Needed for some slow flash chips. mf. */
8085         
8086         /* FIXME: The SlowIO's for millennium could be replaced by 
8087 @@ -226,11 +239,9 @@
8088  {
8089         volatile int dummy;
8090         int modulus = 0xffff;
8091 -       unsigned long docptr;
8092 +       void __iomem *docptr = doc->virtadr;
8093         int i;
8094  
8095 -       docptr = doc->virtadr;
8096 -
8097         if (len <= 0)
8098                 return;
8099  
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)
8103  {
8104 -       unsigned long docptr;
8105 +       void __iomem *docptr = doc->virtadr;
8106         int i;
8107  
8108 -       docptr = doc->virtadr;
8109 -
8110         if (len <= 0)
8111                 return;
8112  
8113 @@ -278,7 +287,7 @@
8114  
8115  static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip)
8116  {
8117 -       unsigned long docptr = doc->virtadr;
8118 +       void __iomem *docptr = doc->virtadr;
8119  
8120         /* Software requirement 11.4.4 before writing DeviceSelect */
8121         /* Deassert the CE line to eliminate glitches on the FCE# outputs */
8122 @@ -302,7 +311,7 @@
8123  
8124  static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor)
8125  {
8126 -       unsigned long docptr = doc->virtadr;
8127 +       void __iomem *docptr = doc->virtadr;
8128  
8129         /* Select the floor (bank) of chips required */
8130         WriteDOC(floor, docptr, FloorSelect);
8131 @@ -344,15 +353,25 @@
8132  
8133         /* Read the manufacturer and device id codes from the device */
8134  
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);
8139 -
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);
8148 +
8149 +               DoC_Delay(doc, 2);
8150 +               dummy = ReadDOC(doc->virtadr, ReadPipeInit);
8151 +               id = ReadDOC(doc->virtadr, LastDataRead);
8152 +       } else {
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);
8157 +
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);
8162 +       }
8163  
8164         /* No response - return failure */
8165         if (mfr == 0xff || mfr == 0)
8166 @@ -386,11 +405,10 @@
8167                         if (!doc->mfr) {
8168                                 doc->mfr = mfr;
8169                                 doc->id = id;
8170 -                               doc->chipshift =
8171 -                                   nand_flash_ids[i].chipshift;
8172 -                               doc->page256 = nand_flash_ids[i].page256;
8173 -                               doc->pageadrlen =
8174 -                                   nand_flash_ids[i].chipshift > 25 ? 3 : 2;
8175 +                               doc->chipshift = 
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;
8179                                 doc->erasesize =
8180                                     nand_flash_ids[i].erasesize;
8181                                 return 1;
8182 @@ -410,20 +428,16 @@
8183  
8184  /* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
8185  
8186 -static void DoC_ScanChips(struct DiskOnChip *this)
8187 +static void DoC_ScanChips(struct DiskOnChip *this, int maxchips)
8188  {
8189         int floor, chip;
8190         int numchips[MAX_FLOORS];
8191 -       int maxchips = MAX_CHIPS;
8192         int ret = 1;
8193  
8194         this->numchips = 0;
8195         this->mfr = 0;
8196         this->id = 0;
8197  
8198 -       if (DoC_is_Millennium(this))
8199 -               maxchips = MAX_CHIPS_MIL;
8200 -
8201         /* For each floor, find the number of valid chips it contains */
8202         for (floor = 0; floor < MAX_FLOORS; floor++) {
8203                 ret = 1;
8204 @@ -515,6 +529,7 @@
8205  {
8206         struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
8207         struct DiskOnChip *old = NULL;
8208 +       int maxchips;
8209  
8210         /* We must avoid being called twice for the same device. */
8211  
8212 @@ -538,14 +553,28 @@
8213  
8214  
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;
8222 +               break;
8223         case DOC_ChipID_Doc2k:
8224                 mtd->name = "DiskOnChip 2000";
8225                 this->ioreg = DoC_2k_CDSN_IO;
8226 +               maxchips = MAX_CHIPS;
8227                 break;
8228         case DOC_ChipID_DocMil:
8229                 mtd->name = "DiskOnChip Millennium";
8230                 this->ioreg = DoC_Mil_CDSN_IO;
8231 +               maxchips = MAX_CHIPS_MIL;
8232                 break;
8233 +       default:
8234 +               printk("Unknown ChipID 0x%02x\n", this->ChipID);
8235 +               kfree(mtd);
8236 +               iounmap((void *) this->virtadr);
8237 +               return;
8238         }
8239  
8240         printk(KERN_NOTICE "%s found at address 0x%lX\n", mtd->name,
8241 @@ -566,6 +595,7 @@
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;
8248         mtd->sync = NULL;
8249 @@ -578,7 +608,7 @@
8250         init_MUTEX(&this->lock);
8251  
8252         /* Ident all the chips present. */
8253 -       DoC_ScanChips(this);
8254 +       DoC_ScanChips(this, maxchips);
8255  
8256         if (!this->totlen) {
8257                 kfree(mtd);
8258 @@ -597,20 +627,19 @@
8259                     size_t * retlen, u_char * buf)
8260  {
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);
8264  }
8265  
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)
8269  {
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;
8277 -
8278 -       docptr = this->virtadr;
8279 +       size_t left = len;
8280  
8281         /* Don't allow read past end of device */
8282         if (from >= this->totlen)
8283 @@ -618,122 +647,131 @@
8284  
8285         down(&this->lock);
8286  
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;
8290 -
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);
8296 +       *retlen = 0;
8297 +       while (left) {
8298 +               len = left;
8299 +
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;
8303  
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);
8310  
8311 +               /* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */
8312  
8313 -       /* Find the chip which is to be used and select it */
8314 -       mychip = &this->chips[from >> (this->chipshift)];
8315  
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);
8321 -       }
8322 +               /* Find the chip which is to be used and select it */
8323 +               mychip = &this->chips[from >> (this->chipshift)];
8324  
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);
8332 +               }
8333  
8334 -       DoC_Command(this,
8335 -                   (!this->page256
8336 -                    && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
8337 -                   CDSN_CTRL_WP);
8338 -       DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
8339 -                   CDSN_CTRL_ECC_IO);
8340 -
8341 -       if (eccbuf) {
8342 -               /* Prime the ECC engine */
8343 -               WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8344 -               WriteDOC(DOC_ECC_EN, docptr, ECCConf);
8345 -       } else {
8346 -               /* disable the ECC engine */
8347 -               WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8348 -               WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8349 -       }
8350 +               this->curfloor = mychip->floor;
8351 +               this->curchip = mychip->chip;
8352  
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);
8357 +               DoC_Command(this,
8358 +                           (!this->page256
8359 +                            && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
8360 +                           CDSN_CTRL_WP);
8361 +               DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
8362 +                           CDSN_CTRL_ECC_IO);
8363  
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);
8367 -       }
8368 +               if (eccbuf) {
8369 +                       /* Prime the ECC engine */
8370 +                       WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8371 +                       WriteDOC(DOC_ECC_EN, docptr, ECCConf);
8372 +               } else {
8373 +                       /* disable the ECC engine */
8374 +                       WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8375 +                       WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8376 +               }
8377  
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);
8383 +
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);
8387 +               }
8388  
8389 -       /* Let the caller know we completed it */
8390 -       *retlen = len;
8391 +               DoC_ReadBuf(this, &buf[len256], len - len256);
8392  
8393 -       if (eccbuf) {
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 */
8399 +               *retlen += len;
8400  
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);
8406 -               } else {
8407 -                       dummy = ReadDOC(docptr, 2k_ECCStatus);
8408 -                       dummy = ReadDOC(docptr, 2k_ECCStatus);
8409 -                       i = ReadDOC(docptr, 2k_ECCStatus);
8410 -               }
8411 +               if (eccbuf) {
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);
8416 +
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);
8422 +                       } else {
8423 +                               dummy = ReadDOC(docptr, 2k_ECCStatus);
8424 +                               dummy = ReadDOC(docptr, 2k_ECCStatus);
8425 +                               i = ReadDOC(docptr, 2k_ECCStatus);
8426 +                       }
8427  
8428 -               /* Check the ECC Status */
8429 -               if (i & 0x80) {
8430 -                       int nb_errors;
8431 -                       /* There was an ECC error */
8432 +                       /* Check the ECC Status */
8433 +                       if (i & 0x80) {
8434 +                               int nb_errors;
8435 +                               /* There was an ECC error */
8436  #ifdef ECC_DEBUG
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);
8439  #endif
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++) {
8443 -                               syndrome[i] =
8444 -                                   ReadDOC(docptr, ECCSyndrome0 + i);
8445 -                       }
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++) {
8450 +                                       syndrome[i] =
8451 +                                           ReadDOC(docptr, ECCSyndrome0 + i);
8452 +                               }
8453 +                               nb_errors = doc_decode_ecc(buf, syndrome);
8454  
8455  #ifdef ECC_DEBUG
8456 -                       printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
8457 +                               printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
8458  #endif
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 */
8463 -                               ret = -EIO;
8464 -                        }
8465 -               }
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 */
8470 +                                       ret = -EIO;
8471 +                               }
8472 +                       }
8473  
8474  #ifdef PSYCHO_DEBUG
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]);
8481  #endif
8482                 
8483 -               /* disable the ECC engine */
8484 -               WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
8485 -       }
8486 +                       /* disable the ECC engine */
8487 +                       WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
8488 +               }
8489  
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))
8493 -       {
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))
8498 +               {
8499 +                   DoC_WaitReady(this);
8500 +               }
8501 +
8502 +               from += len;
8503 +               left -= len;
8504 +               buf += len;
8505         }
8506  
8507         up(&this->lock);
8508 @@ -745,21 +783,21 @@
8509                      size_t * retlen, const u_char * buf)
8510  {
8511         char eccbuf[6];
8512 -       return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, 0);
8513 +       return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
8514  }
8515  
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)
8520  {
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;
8526         int len256 = 0;
8527         struct Nand *mychip;
8528 -
8529 -       docptr = this->virtadr;
8530 +       size_t left = len;
8531 +       int status;
8532  
8533         /* Don't allow write past end of device */
8534         if (to >= this->totlen)
8535 @@ -767,65 +805,133 @@
8536  
8537         down(&this->lock);
8538  
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;
8542 -
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);
8548 +       *retlen = 0;
8549 +       while (left) {
8550 +               len = left;
8551 +
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;
8555 +
8556 +               /* The ECC will not be calculated correctly if less than 512 is written */
8557 +/* DBB-
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);
8562 +   -DBB */
8563  
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); */
8566  
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)];
8571  
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);
8577 -       }
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);
8583 +               }
8584  
8585 -       this->curfloor = mychip->floor;
8586 -       this->curchip = mychip->chip;
8587 +               this->curfloor = mychip->floor;
8588 +               this->curchip = mychip->chip;
8589  
8590 -       /* Set device to main plane of flash */
8591 -       DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
8592 -       DoC_Command(this,
8593 -                   (!this->page256
8594 -                    && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
8595 -                   CDSN_CTRL_WP);
8596 +               /* Set device to main plane of flash */
8597 +               DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
8598 +               DoC_Command(this,
8599 +                           (!this->page256
8600 +                            && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
8601 +                           CDSN_CTRL_WP);
8602  
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);
8607  
8608 -       if (eccbuf) {
8609 -               /* Prime the ECC engine */
8610 -               WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8611 -               WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
8612 -       } else {
8613 -               /* disable the ECC engine */
8614 -               WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8615 -               WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8616 -       }
8617 +               if (eccbuf) {
8618 +                       /* Prime the ECC engine */
8619 +                       WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8620 +                       WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
8621 +               } else {
8622 +                       /* disable the ECC engine */
8623 +                       WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
8624 +                       WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8625 +               }
8626  
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);
8635 +
8636 +                       DoC_Command(this, NAND_CMD_PAGEPROG, 0);
8637 +
8638 +                       DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
8639 +                       /* There's an implicit DoC_WaitReady() in DoC_Command */
8640 +
8641 +                       dummy = ReadDOC(docptr, CDSNSlowIO);
8642 +                       DoC_Delay(this, 2);
8643 +
8644 +                       if (ReadDOC_(docptr, this->ioreg) & 1) {
8645 +                               printk(KERN_ERR "Error programming flash\n");
8646 +                               /* Error in programming */
8647 +                               *retlen = 0;
8648 +                               up(&this->lock);
8649 +                               return -EIO;
8650 +                       }
8651 +
8652 +                       DoC_Command(this, NAND_CMD_SEQIN, 0);
8653 +                       DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0,
8654 +                                   CDSN_CTRL_ECC_IO);
8655 +               }
8656 +
8657 +               DoC_WriteBuf(this, &buf[len256], len - len256);
8658 +
8659 +               if (eccbuf) {
8660 +                       WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
8661 +                                CDSNControl);
8662 +
8663 +                       if (DoC_is_Millennium(this)) {
8664 +                               WriteDOC(0, docptr, NOP);
8665 +                               WriteDOC(0, docptr, NOP);
8666 +                               WriteDOC(0, docptr, NOP);
8667 +                       } else {
8668 +                               WriteDOC_(0, docptr, this->ioreg);
8669 +                               WriteDOC_(0, docptr, this->ioreg);
8670 +                               WriteDOC_(0, docptr, this->ioreg);
8671 +                       }
8672 +
8673 +                       WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr,
8674 +                                CDSNControl);
8675 +
8676 +                       /* Read the ECC data through the DiskOnChip ECC logic */
8677 +                       for (di = 0; di < 6; di++) {
8678 +                               eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
8679 +                       }
8680 +
8681 +                       /* Reset the ECC engine */
8682 +                       WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8683 +
8684 +#ifdef PSYCHO_DEBUG
8685 +                       printk
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]);
8689 +#endif
8690 +               }
8691  
8692                 DoC_Command(this, NAND_CMD_PAGEPROG, 0);
8693  
8694                 DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
8695                 /* There's an implicit DoC_WaitReady() in DoC_Command */
8696  
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);
8702 +               } else {
8703 +                       dummy = ReadDOC(docptr, CDSNSlowIO);
8704 +                       DoC_Delay(this, 2);
8705 +                       status = ReadDOC_(docptr, this->ioreg);
8706 +               }
8707  
8708 -               if (ReadDOC_(docptr, this->ioreg) & 1) {
8709 +               if (status & 1) {
8710                         printk(KERN_ERR "Error programming flash\n");
8711                         /* Error in programming */
8712                         *retlen = 0;
8713 @@ -833,94 +939,106 @@
8714                         return -EIO;
8715                 }
8716  
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 */
8721 +               *retlen += len;
8722 +               
8723 +               if (eccbuf) {
8724 +                       unsigned char x[8];
8725 +                       size_t dummy;
8726 +                       int ret;
8727 +
8728 +                       /* Write the ECC data to flash */
8729 +                       for (di=0; di<6; di++)
8730 +                               x[di] = eccbuf[di];
8731 +               
8732 +                       x[6]=0x55;
8733 +                       x[7]=0x55;
8734 +               
8735 +                       ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x);
8736 +                       if (ret) {
8737 +                               up(&this->lock);
8738 +                               return ret;
8739 +                       }
8740 +               }
8741 +
8742 +               to += len;
8743 +               left -= len;
8744 +               buf += len;
8745         }
8746  
8747 -       DoC_WriteBuf(this, &buf[len256], len - len256);
8748 +       up(&this->lock);
8749 +       return 0;
8750 +}
8751  
8752 -       if (eccbuf) {
8753 -               WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
8754 -                        CDSNControl);
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)
8758 +{
8759 +       static char static_buf[512];
8760 +       static DECLARE_MUTEX(writev_buf_sem);
8761  
8762 -               if (DoC_is_Millennium(this)) {
8763 -                       WriteDOC(0, docptr, NOP);
8764 -                       WriteDOC(0, docptr, NOP);
8765 -                       WriteDOC(0, docptr, NOP);
8766 -               } else {
8767 -                       WriteDOC_(0, docptr, this->ioreg);
8768 -                       WriteDOC_(0, docptr, this->ioreg);
8769 -                       WriteDOC_(0, docptr, this->ioreg);
8770 -               }
8771 +       size_t totretlen = 0;
8772 +       size_t thisvecofs = 0;
8773 +       int ret= 0;
8774  
8775 -               /* Read the ECC data through the DiskOnChip ECC logic */
8776 -               for (di = 0; di < 6; di++) {
8777 -                       eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
8778 -               }
8779 +       down(&writev_buf_sem);
8780  
8781 -               /* Reset the ECC engine */
8782 -               WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
8783 +       while(count) {
8784 +               size_t thislen, thisretlen;
8785 +               unsigned char *buf;
8786  
8787 -#ifdef PSYCHO_DEBUG
8788 -               printk
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]);
8792 -#endif
8793 -       }
8794 +               buf = vecs->iov_base + thisvecofs;
8795 +               thislen = vecs->iov_len - thisvecofs;
8796  
8797 -       DoC_Command(this, NAND_CMD_PAGEPROG, 0);
8798  
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;
8804 +               } else {
8805 +                       /* Not enough to fill a page. Copy into buf */
8806 +                       memcpy(static_buf, buf, thislen);
8807 +                       buf = &static_buf[thislen];
8808 +
8809 +                       while(count && thislen < 512) {
8810 +                               vecs++;
8811 +                               count--;
8812 +                               thisvecofs = min((512-thislen), vecs->iov_len);
8813 +                               memcpy(buf, vecs->iov_base, thisvecofs);
8814 +                               thislen += thisvecofs;
8815 +                               buf += thisvecofs;
8816 +                       }
8817 +                       buf = static_buf;
8818 +               }
8819 +               if (count && thisvecofs == vecs->iov_len) {
8820 +                       thisvecofs = 0;
8821 +                       vecs++;
8822 +                       count--;
8823 +               }
8824 +               ret = doc_write_ecc(mtd, to, thislen, &thisretlen, buf, eccbuf, oobsel);
8825  
8826 -       dummy = ReadDOC(docptr, CDSNSlowIO);
8827 -       DoC_Delay(this, 2);
8828 +               totretlen += thisretlen;
8829  
8830 -       if (ReadDOC_(docptr, this->ioreg) & 1) {
8831 -               printk(KERN_ERR "Error programming flash\n");
8832 -               /* Error in programming */
8833 -               *retlen = 0;
8834 -               up(&this->lock);
8835 -               return -EIO;
8836 -       }
8837 +               if (ret || thisretlen != thislen)
8838 +                       break;
8839  
8840 -       /* Let the caller know we completed it */
8841 -       *retlen = len;
8842 -               
8843 -       if (eccbuf) {
8844 -               unsigned char x[8];
8845 -               size_t dummy;
8846 -               int ret;
8847 -
8848 -               /* Write the ECC data to flash */
8849 -               for (di=0; di<6; di++)
8850 -                       x[di] = eccbuf[di];
8851 -               
8852 -               x[6]=0x55;
8853 -               x[7]=0x55;
8854 -               
8855 -               ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x);
8856 -               up(&this->lock);
8857 -               return ret;
8858 -       }
8859 -       up(&this->lock);
8860 -       return 0;
8861 +               to += thislen;
8862 +       }               
8863 +
8864 +       up(&writev_buf_sem);
8865 +       *retlen = totretlen;
8866 +       return ret;
8867  }
8868  
8869 +
8870  static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
8871                         size_t * retlen, u_char * buf)
8872  {
8873         struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
8874         int len256 = 0, ret;
8875 -       unsigned long docptr;
8876         struct Nand *mychip;
8877  
8878         down(&this->lock);
8879  
8880 -       docptr = this->virtadr;
8881 -
8882         mychip = &this->chips[ofs >> this->chipshift];
8883  
8884         if (this->curfloor != mychip->floor) {
8885 @@ -975,9 +1093,10 @@
8886  {
8887         struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
8888         int len256 = 0;
8889 -       unsigned long docptr = this->virtadr;
8890 +       void __iomem *docptr = this->virtadr;
8891         struct Nand *mychip = &this->chips[ofs >> this->chipshift];
8892         volatile int dummy;
8893 +       int status;
8894  
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 */
8900  
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);
8906 +               } else {
8907 +                       dummy = ReadDOC(docptr, CDSNSlowIO);
8908 +                       DoC_Delay(this, 2);
8909 +                       status = ReadDOC_(docptr, this->ioreg);
8910 +               }
8911  
8912 -               if (ReadDOC_(docptr, this->ioreg) & 1) {
8913 +               if (status & 1) {
8914                         printk(KERN_ERR "Error programming oob data\n");
8915                         /* There was an error */
8916                         *retlen = 0;
8917 @@ -1045,10 +1170,16 @@
8918         DoC_Command(this, NAND_CMD_STATUS, 0);
8919         /* DoC_WaitReady() is implicit in DoC_Command */
8920  
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);
8926 +       } else {
8927 +               dummy = ReadDOC(docptr, CDSNSlowIO);
8928 +               DoC_Delay(this, 2);
8929 +               status = ReadDOC_(docptr, this->ioreg);
8930 +       }
8931  
8932 -       if (ReadDOC_(docptr, this->ioreg) & 1) {
8933 +       if (status & 1) {
8934                 printk(KERN_ERR "Error programming oob data\n");
8935                 /* There was an error */
8936                 *retlen = 0;
8937 @@ -1079,8 +1210,9 @@
8938         __u32 ofs = instr->addr;
8939         __u32 len = instr->len;
8940         volatile int dummy;
8941 -       unsigned long docptr;
8942 +       void __iomem *docptr = this->virtadr;
8943         struct Nand *mychip;
8944 +       int status;
8945  
8946         down(&this->lock);
8947  
8948 @@ -1091,8 +1223,6 @@
8949  
8950         instr->state = MTD_ERASING;
8951                 
8952 -       docptr = this->virtadr;
8953 -
8954         /* FIXME: Do this in the background. Use timers or schedule_task() */
8955         while(len) {
8956                 mychip = &this->chips[ofs >> this->chipshift];
8957 @@ -1112,10 +1242,16 @@
8958  
8959                 DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
8960  
8961 -               dummy = ReadDOC(docptr, CDSNSlowIO);
8962 -               DoC_Delay(this, 2);
8963 -               
8964 -               if (ReadDOC_(docptr, this->ioreg) & 1) {
8965 +               if (DoC_is_Millennium(this)) {
8966 +                       ReadDOC(docptr, ReadPipeInit);
8967 +                       status = ReadDOC(docptr, LastDataRead);
8968 +               } else {
8969 +                       dummy = ReadDOC(docptr, CDSNSlowIO);
8970 +                       DoC_Delay(this, 2);
8971 +                       status = ReadDOC_(docptr, this->ioreg);
8972 +               }
8973 +
8974 +               if (status & 1) {
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;
8980  
8981   callback:
8982 -       if (instr->callback)
8983 -               instr->callback(instr);
8984 +       mtd_erase_callback(instr);
8985  
8986         up(&this->lock);
8987         return 0;
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
8992 @@ -4,7 +4,7 @@
8993   * (c) 1999 Machine Vision Holdings, Inc.
8994   * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
8995   *
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 $
8998   */
8999  
9000  #include <linux/kernel.h>
9001 @@ -19,6 +19,7 @@
9002  #include <linux/sched.h>
9003  #include <linux/init.h>
9004  #include <linux/types.h>
9005 +#include <linux/bitops.h>
9006  
9007  #include <linux/mtd/mtd.h>
9008  #include <linux/mtd/nand.h>
9009 @@ -37,9 +38,11 @@
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,
9023 @@ -49,7 +52,7 @@
9024  static struct mtd_info *docmillist = NULL;
9025  
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)
9029  {
9030         volatile char dummy;
9031         int i;
9032 @@ -59,7 +62,7 @@
9033  }
9034  
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)
9038  {
9039         unsigned short c = 0xffff;
9040  
9041 @@ -76,7 +79,7 @@
9042         return (c == 0);
9043  }
9044  
9045 -static inline int DoC_WaitReady(unsigned long docptr)
9046 +static inline int DoC_WaitReady(void __iomem * docptr)
9047  {
9048         /* This is inline, to optimise the common case, where it's ready instantly */
9049         int ret = 0;
9050 @@ -100,7 +103,7 @@
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. */
9053  
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)
9057  {
9058         /* Assert the CLE (Command Latch Enable) line to the flash chip */
9059 @@ -120,7 +123,7 @@
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. */
9062  
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)
9066  {
9067         /* Assert the ALE (Address Latch Enable) line to the flash chip */
9068 @@ -158,7 +161,7 @@
9069  }
9070  
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)
9074  {
9075         /* Select the individual flash chip requested */
9076         WriteDOC(chip, docptr, CDSNDeviceSelect);
9077 @@ -169,7 +172,7 @@
9078  }
9079  
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)
9083  {
9084         /* Select the floor (bank) of chips required */
9085         WriteDOC(floor, docptr, FloorSelect);
9086 @@ -226,7 +229,7 @@
9087                                mfr, id, nand_manuf_ids[j].name, nand_flash_ids[i].name);
9088                         doc->mfr = mfr;
9089                         doc->id = id;
9090 -                       doc->chipshift = nand_flash_ids[i].chipshift;
9091 +                       doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1;
9092                         break;
9093                 }
9094         }
9095 @@ -403,17 +406,18 @@
9096                      size_t *retlen, u_char *buf)
9097  {
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);
9101  }
9102  
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)
9107  {
9108         int i, ret;
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)];
9115  
9116         /* Don't allow read past end of device */
9117 @@ -529,16 +533,17 @@
9118                       size_t *retlen, const u_char *buf)
9119  {
9120         char eccbuf[6];
9121 -       return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, 0);
9122 +       return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
9123  }
9124  
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)
9129  {
9130         int i,ret = 0;
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)];
9136  
9137         /* Don't allow write past end of device */
9138 @@ -673,7 +678,7 @@
9139  #endif
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];
9145  
9146         /* Find the chip which is to be used and select it */
9147 @@ -725,7 +730,7 @@
9148         volatile char dummy;
9149         int ret = 0;
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];
9154  
9155         /* Find the chip which is to be used and select it */
9156 @@ -794,7 +799,7 @@
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];
9163  
9164         if (len != mtd->erasesize) 
9165 @@ -840,8 +845,7 @@
9166                 instr->state = MTD_ERASE_DONE;
9167         dummy = ReadDOC(docptr, LastDataRead);
9168  
9169 -       if (instr->callback) 
9170 -               instr->callback(instr);
9171 +       mtd_erase_callback(instr);
9172  
9173         return 0;
9174  }
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
9179 @@ -6,7 +6,9 @@
9180   * (c) 1999 Machine Vision Holdings, Inc.
9181   * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
9182   *
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 $
9185 + *
9186 + * Released under GPL
9187   */
9188  
9189  #include <linux/kernel.h>
9190 @@ -21,6 +23,7 @@
9191  #include <linux/sched.h>
9192  #include <linux/init.h>
9193  #include <linux/types.h>
9194 +#include <linux/bitops.h>
9195  
9196  #include <linux/mtd/mtd.h>
9197  #include <linux/mtd/nand.h>
9198 @@ -54,7 +57,7 @@
9199  
9200  
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)
9204  {
9205         int i;
9206  
9207 @@ -65,7 +68,7 @@
9208  #define        CDSN_CTRL_FR_B_MASK     (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)
9209  
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)
9213  {
9214         unsigned int c = 0xffff;
9215  
9216 @@ -82,7 +85,7 @@
9217         return (c == 0);
9218  }
9219  
9220 -static inline int DoC_WaitReady(unsigned long docptr)
9221 +static inline int DoC_WaitReady(void __iomem * docptr)
9222  {
9223         /* This is inline, to optimise the common case, where it's ready instantly */
9224         int ret = 0;
9225 @@ -103,7 +106,7 @@
9226   * can detect. M-systems suggest always check this on any block level
9227   * operation and setting to normal mode if in reset mode.
9228   */
9229 -static inline void DoC_CheckASIC(unsigned long docptr)
9230 +static inline void DoC_CheckASIC(void __iomem * docptr)
9231  {
9232         /* Make sure the DoC is in normal mode */
9233         if ((ReadDOC(docptr, Mplus_DOCControl) & DOC_MODE_NORMAL) == 0) {
9234 @@ -115,7 +118,7 @@
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.
9237   */
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)
9241  {
9242         WriteDOC(command, docptr, Mplus_FlashCmd);
9243 @@ -130,7 +133,7 @@
9244                                unsigned long ofs, unsigned char xtraflags1,
9245                                unsigned char xtraflags2)
9246  {
9247 -       unsigned long docptr = doc->virtadr;
9248 +       void __iomem * docptr = doc->virtadr;
9249  
9250         /* Allow for possible Mill Plus internal flash interleaving */
9251         ofs >>= doc->interleave;
9252 @@ -160,14 +163,14 @@
9253  }
9254  
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)
9258  {
9259         /* No choice for flash chip on Millennium Plus */
9260         return 0;
9261  }
9262  
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)
9266  {
9267         WriteDOC((floor & 0x3), docptr, Mplus_DeviceSelect);
9268         return 0;
9269 @@ -183,24 +186,35 @@
9270   *  | Data 0    | ECC 0 |Flags0 |Flags1 | Data 1       |ECC 1    | OOB 1 + 2 |
9271   *  +-----------+-------+-------+-------+--------------+---------+-----------+
9272   */
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)
9276  {
9277 -       unsigned int ofs = *from & 0x3ff;
9278 -       unsigned int cmd;
9279 +       struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
9280  
9281 -       if (ofs < 512) {
9282 -               cmd = NAND_CMD_READ0;
9283 -               ofs &= 0x1ff;
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;
9289 +               unsigned int cmd;
9290 +
9291 +               if (ofs < 512) {
9292 +                       cmd = NAND_CMD_READ0;
9293 +                       ofs &= 0x1ff;
9294 +               } else if (ofs < 1014) {
9295 +                       cmd = NAND_CMD_READ1;
9296 +                       ofs = (ofs & 0x1ff) + 10;
9297 +               } else {
9298 +                       cmd = NAND_CMD_READOOB;
9299 +                       ofs = ofs - 1014;
9300 +               }
9301 +
9302 +               *from = (*from & ~0x3ff) | ofs;
9303 +               return cmd;
9304         } else {
9305 -               cmd = NAND_CMD_READOOB;
9306 -               ofs = ofs - 1014;
9307 +               /* No interleave */
9308 +               if ((*from) & 0x100)
9309 +                       return NAND_CMD_READ1;
9310 +               return NAND_CMD_READ0;
9311         }
9312 -
9313 -       *from = (*from & ~0x3ff) | ofs;
9314 -       return cmd;
9315  }
9316  
9317  static unsigned int DoC_GetECCOffset(struct mtd_info *mtd, loff_t *from)
9318 @@ -239,7 +253,7 @@
9319         return cmd;
9320  }
9321  
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)
9324  {
9325  #ifndef USE_MEMCPY
9326         int i;
9327 @@ -250,7 +264,7 @@
9328  #endif
9329  }
9330  
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)
9333  {
9334  #ifndef USE_MEMCPY
9335         int i;
9336 @@ -266,7 +280,7 @@
9337  {
9338         int mfr, id, i, j;
9339         volatile char dummy;
9340 -       unsigned long docptr = doc->virtadr;
9341 +       void __iomem * docptr = doc->virtadr;
9342  
9343         /* Page in the required floor/chip */
9344         DoC_SelectFloor(docptr, floor);
9345 @@ -294,10 +308,12 @@
9346         dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
9347  
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 */
9352  
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 */
9357  
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);
9362                         doc->mfr = mfr;
9363                         doc->id = id;
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;
9370                         break;
9371                 }
9372 @@ -346,6 +359,21 @@
9373         this->mfr = 0;
9374         this->id = 0;
9375  
9376 +       /* Work out the intended interleave setting */
9377 +       this->interleave = 0;
9378 +       if (this->ChipID == DOC_ChipID_DocMilPlus32)
9379 +               this->interleave = 1;
9380 +
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)");
9387 +               conf ^= 4;
9388 +               WriteDOC(conf, this->virtadr, Mplus_Configuration);
9389 +       }
9390 +
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;
9394 @@ -503,7 +531,7 @@
9395         int i;
9396         loff_t fofs;
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];
9402         char c[32];
9403 @@ -588,7 +616,7 @@
9404         loff_t fofs;
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)];
9410  
9411         /* Don't allow read past end of device */
9412 @@ -727,7 +755,7 @@
9413         loff_t fto;
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)];
9419  
9420         /* Don't allow write past end of device */
9421 @@ -739,7 +767,7 @@
9422                 return -EINVAL;
9423  
9424         /* Determine position of OOB flags, before or after data */
9425 -       before = to & 0x200;
9426 +       before = (this->interleave && (to & 0x200));
9427  
9428         DoC_CheckASIC(docptr);
9429  
9430 @@ -853,7 +881,7 @@
9431  {
9432         loff_t fofs, base;
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;
9438  
9439 @@ -886,7 +914,10 @@
9440                 /* Figure out which region we are accessing... */
9441                 fofs = ofs;
9442                 base = ofs & 0xf;
9443 -               if (base < 6) {
9444 +               if (!this->interleave) {
9445 +                       DoC_Command(docptr, NAND_CMD_READOOB, 0);
9446 +                       size = 16 - base;
9447 +               } else if (base < 6) {
9448                         DoC_Command(docptr, DoC_GetECCOffset(mtd, &fofs), 0);
9449                         size = 6 - base;
9450                 } else if (base < 8) {
9451 @@ -928,7 +959,7 @@
9452         volatile char dummy;
9453         loff_t fofs, base;
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;
9459         int ret = 0;
9460 @@ -963,7 +994,10 @@
9461                 /* Figure out which region we are accessing... */
9462                 fofs = ofs;
9463                 base = ofs & 0x0f;
9464 -               if (base < 6) {
9465 +               if (!this->interleave) {
9466 +                       WriteDOC(NAND_CMD_READOOB, docptr, Mplus_FlashCmd);
9467 +                       size = 16 - base;
9468 +               } else if (base < 6) {
9469                         WriteDOC(DoC_GetECCOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
9470                         size = 6 - base;
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];
9479  
9480         DoC_CheckASIC(docptr);
9481 @@ -1077,8 +1111,7 @@
9482         /* Disable flash internally */
9483         WriteDOC(0, docptr, Mplus_FlashSelect);
9484  
9485 -       if (instr->callback) 
9486 -               instr->callback(instr);
9487 +       mtd_erase_callback(instr);
9488  
9489         return 0;
9490  }
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
9495 @@ -4,7 +4,7 @@
9496  /* (C) 1999 Machine Vision Holdings, Inc.                      */
9497  /* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>         */
9498  
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 $   */
9501  
9502  
9503  
9504 @@ -135,6 +135,9 @@
9505                  window, DOCControl);
9506  #endif /* !DOC_PASSIVE_PROBE */        
9507  
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);
9512    
9513         switch (ChipID) {
9514 @@ -148,6 +151,12 @@
9515                 break;
9516                 
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;
9523 +
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;
9527 @@ -191,7 +200,6 @@
9528                         tmpc = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
9529                         if (tmp != tmpb && tmp == tmpc)
9530                                         return ChipID;
9531 -                       break;
9532                 default:
9533                         break;
9534                 }
9535 @@ -199,8 +207,8 @@
9536  
9537         default:
9538  
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",
9543                        ChipID, physadr);
9544  #endif
9545  #ifndef DOC_PASSIVE_PROBE
9546 @@ -241,6 +249,12 @@
9547                 return;
9548         
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);
9554 +                       return;
9555 +               }
9556                 docfound = 1;
9557                 mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL);
9558  
9559 @@ -256,12 +270,18 @@
9560                 memset((char *)this, 0, sizeof(struct DiskOnChip));
9561  
9562                 mtd->priv = this;
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);
9568  
9569                 switch(ChipID) {
9570 +               case DOC_ChipID_Doc2kTSOP:
9571 +                       name="2000 TSOP";
9572 +                       im_funcname = "DoC2k_init";
9573 +                       im_modname = "doc2000";
9574 +                       break;
9575 +                       
9576                 case DOC_ChipID_Doc2k:
9577                         name="2000";
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
9583 @@ -2,7 +2,7 @@
9584  /*
9585   * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART.
9586   *
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 $
9589   *
9590   * Author: Abraham vd Merwe <abraham@2d3d.co.za>
9591   *
9592 @@ -433,7 +433,7 @@
9593          }
9594  
9595     instr->state = MTD_ERASE_DONE;
9596 -   if (instr->callback) instr->callback (instr);
9597 +   mtd_erase_callback(instr);
9598  
9599     return (0);
9600  }
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
9605 @@ -1,12 +1,12 @@
9606  /*
9607 - *      Copyright (c) 2001 Maciej W. Rozycki
9608 + *     Copyright (c) 2001 Maciej W. Rozycki
9609   *
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.
9618   *
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 $
9621   */
9622  
9623  #include <linux/init.h>
9624 @@ -29,18 +29,18 @@
9625  
9626  
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";
9630  
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");
9635  
9636  
9637  /*
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
9641 - * at 0MB, though.
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.
9645   */
9646  static ulong ms02nv_addrs[] __initdata = {
9647         0x07000000, 0x06800000, 0x06000000, 0x05800000, 0x05000000,
9648 @@ -130,7 +130,7 @@
9649  
9650         int ret = -ENODEV;
9651  
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);
9655         if (!mod_res)
9656                 return -ENOMEM;
9657 @@ -233,7 +233,7 @@
9658                 goto err_out_csr_res;
9659         }
9660  
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);
9664  
9665         mp->next = root_ms02nv_mtd;
9666 @@ -293,12 +293,12 @@
9667  
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)
9673                         stride = 2;
9674                 break;
9675         case MACH_DS5000_2X0:
9676 -       case MACH_DS5000:
9677 +       case MACH_DS5900:
9678                 csr = (volatile u32 *)KN03_MCR_BASE;
9679                 if (*csr & KN03_MCR_BNK32M)
9680                         stride = 2;
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
9685 @@ -1,34 +1,96 @@
9686  /*
9687 - *      Copyright (c) 2001 Maciej W. Rozycki
9688 + *     Copyright (c) 2001, 2003  Maciej W. Rozycki
9689   *
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
9696 + *     systems.
9697   *
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.
9703 + *
9704 + *     $Id: ms02-nv.h,v 1.3 2003/08/19 09:25:36 dwmw2 Exp $
9705   */
9706  
9707  #include <linux/ioport.h>
9708  #include <linux/mtd/mtd.h>
9709  
9710 +/*
9711 + * Addresses are decoded as follows:
9712 + *
9713 + * 0x000000 - 0x3fffff SRAM
9714 + * 0x400000 - 0x7fffff CSR
9715 + *
9716 + * Within the SRAM area the following ranges are forced by the system
9717 + * firmware:
9718 + *
9719 + * 0x000000 - 0x0003ff diagnostic area, destroyed upon a reboot
9720 + * 0x000400 - ENDofRAM storage area, available to operating systems
9721 + *
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.
9731 + *
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
9737 + * existed).
9738 + *
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.
9745 + *
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):
9751 + *
9752 + * left LED            battery disable status: lit = enabled
9753 + * right LED           battery condition status: lit = OK
9754 + */
9755 +
9756  /* MS02-NV iomem register offsets. */
9757  #define MS02NV_CSR             0x400000        /* control & status register */
9758  
9759 +/* MS02-NV CSR status bits. */
9760 +#define MS02NV_CSR_BATT_OK     0x01            /* battery OK */
9761 +#define MS02NV_CSR_BATT_OFF    0x02            /* battery disabled */
9762 +
9763 +
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 */
9770  
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) */
9781  
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 */
9787  
9788 +
9789  typedef volatile u32 ms02nv_uint;
9790  
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
9796 @@ -1,6 +1,6 @@
9797  /*
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>
9802   *
9803   * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
9804 @@ -57,9 +57,8 @@
9805    memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
9806         
9807    instr->state = MTD_ERASE_DONE;
9808 +  mtd_erase_callback(instr);
9809  
9810 -  if (instr->callback)
9811 -    (*(instr->callback))(instr);
9812    return 0;
9813  }
9814  
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
9819 @@ -0,0 +1,359 @@
9820 +/**
9821 + *
9822 + * $Id: phram.c,v 1.2 2004/08/09 13:19:44 dwmw2 Exp $
9823 + *
9824 + * Copyright (c) Jochen Schaeuble <psionic@psionic.de>
9825 + * 07/2003     rewritten by Joern Engel <joern@wh.fh-wedel.de>
9826 + *
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!
9830 + *
9831 + * Usage:
9832 + *
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
9838 + * gigabytes.
9839 + *
9840 + */
9841 +
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>
9849 +
9850 +#define ERROR(fmt, args...) printk(KERN_ERR "phram: " fmt , ## args)
9851 +
9852 +struct phram_mtd_list {
9853 +       struct list_head list;
9854 +       struct mtd_info *mtdinfo;
9855 +};
9856 +
9857 +static LIST_HEAD(phram_list);
9858 +
9859 +
9860 +
9861 +int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
9862 +{
9863 +       u_char *start = (u_char *)mtd->priv;
9864 +
9865 +       if (instr->addr + instr->len > mtd->size)
9866 +               return -EINVAL;
9867 +       
9868 +       memset(start + instr->addr, 0xff, instr->len);
9869 +
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.
9873 +        */
9874 +
9875 +       instr->state = MTD_ERASE_DONE;
9876 +
9877 +       mtd_erase_callback(instr);
9878 +
9879 +       return 0;
9880 +}
9881 +
9882 +int phram_point(struct mtd_info *mtd, loff_t from, size_t len,
9883 +               size_t *retlen, u_char **mtdbuf)
9884 +{
9885 +       u_char *start = (u_char *)mtd->priv;
9886 +
9887 +       if (from + len > mtd->size)
9888 +               return -EINVAL;
9889 +       
9890 +       *mtdbuf = start + from;
9891 +       *retlen = len;
9892 +       return 0;
9893 +}
9894 +
9895 +void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
9896 +{
9897 +}
9898 +
9899 +int phram_read(struct mtd_info *mtd, loff_t from, size_t len,
9900 +               size_t *retlen, u_char *buf)
9901 +{
9902 +       u_char *start = (u_char *)mtd->priv;
9903 +
9904 +       if (from + len > mtd->size)
9905 +               return -EINVAL;
9906 +       
9907 +       memcpy(buf, start + from, len);
9908 +
9909 +       *retlen = len;
9910 +       return 0;
9911 +}
9912 +
9913 +int phram_write(struct mtd_info *mtd, loff_t to, size_t len,
9914 +               size_t *retlen, const u_char *buf)
9915 +{
9916 +       u_char *start = (u_char *)mtd->priv;
9917 +
9918 +       if (to + len > mtd->size)
9919 +               return -EINVAL;
9920 +       
9921 +       memcpy(start + to, buf, len);
9922 +
9923 +       *retlen = len;
9924 +       return 0;
9925 +}
9926 +
9927 +
9928 +
9929 +static void unregister_devices(void)
9930 +{
9931 +       struct phram_mtd_list *this;
9932 +
9933 +       list_for_each_entry(this, &phram_list, list) {
9934 +               del_mtd_device(this->mtdinfo);
9935 +               iounmap(this->mtdinfo->priv);
9936 +               kfree(this->mtdinfo);
9937 +               kfree(this);
9938 +       }
9939 +}
9940 +
9941 +static int register_device(char *name, unsigned long start, unsigned long len)
9942 +{
9943 +       struct phram_mtd_list *new;
9944 +       int ret = -ENOMEM;
9945 +
9946 +       new = kmalloc(sizeof(*new), GFP_KERNEL);
9947 +       if (!new)
9948 +               goto out0;
9949 +
9950 +       new->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
9951 +       if (!new->mtdinfo)
9952 +               goto out1;
9953 +       
9954 +       memset(new->mtdinfo, 0, sizeof(struct mtd_info));
9955 +
9956 +       ret = -EIO;
9957 +       new->mtdinfo->priv = ioremap(start, len);
9958 +       if (!new->mtdinfo->priv) {
9959 +               ERROR("ioremap failed\n");
9960 +               goto out2;
9961 +       }
9962 +
9963 +
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;
9975 +
9976 +       ret = -EAGAIN;
9977 +       if (add_mtd_device(new->mtdinfo)) {
9978 +               ERROR("Failed to register new device\n");
9979 +               goto out3;
9980 +       }
9981 +
9982 +       list_add_tail(&new->list, &phram_list);
9983 +       return 0;       
9984 +
9985 +out3:
9986 +       iounmap(new->mtdinfo->priv);
9987 +out2:
9988 +       kfree(new->mtdinfo);
9989 +out1:
9990 +       kfree(new);
9991 +out0:
9992 +       return ret;
9993 +}
9994 +
9995 +static int ustrtoul(const char *cp, char **endp, unsigned int base)
9996 +{
9997 +       unsigned long result = simple_strtoul(cp, endp, base);
9998 +
9999 +       switch (**endp) {
10000 +       case 'G':
10001 +               result *= 1024;
10002 +       case 'M':
10003 +               result *= 1024;
10004 +       case 'k':
10005 +               result *= 1024;
10006 +               endp++;
10007 +       }
10008 +       return result;
10009 +}
10010 +
10011 +static int parse_num32(uint32_t *num32, const char *token)
10012 +{
10013 +       char *endp;
10014 +       unsigned long n;
10015 +
10016 +       n = ustrtoul(token, &endp, 0);
10017 +       if (*endp)
10018 +               return -EINVAL;
10019 +
10020 +       *num32 = n;
10021 +       return 0;
10022 +}
10023 +
10024 +static int parse_name(char **pname, const char *token)
10025 +{
10026 +       size_t len;
10027 +       char *name;
10028 +
10029 +       len = strlen(token) + 1;
10030 +       if (len > 64)
10031 +               return -ENOSPC;
10032 +
10033 +       name = kmalloc(len, GFP_KERNEL);
10034 +       if (!name)
10035 +               return -ENOMEM;
10036 +
10037 +       strcpy(name, token);
10038 +
10039 +       *pname = name;
10040 +       return 0;
10041 +}
10042 +
10043 +#define parse_err(fmt, args...) do {   \
10044 +       ERROR(fmt , ## args);   \
10045 +       return 0;               \
10046 +} while (0)
10047 +
10048 +static int phram_setup(const char *val, struct kernel_param *kp)
10049 +{
10050 +       char buf[64+12+12], *str = buf;
10051 +       char *token[3];
10052 +       char *name;
10053 +       uint32_t start;
10054 +       uint32_t len;
10055 +       int i, ret;
10056 +
10057 +       if (strnlen(val, sizeof(str)) >= sizeof(str))
10058 +               parse_err("parameter too long\n");
10059 +
10060 +       strcpy(str, val);
10061 +
10062 +       for (i=0; i<3; i++)
10063 +               token[i] = strsep(&str, ",");
10064 +
10065 +       if (str)
10066 +               parse_err("too many arguments\n");
10067 +
10068 +       if (!token[2])
10069 +               parse_err("not enough arguments\n");
10070 +
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");
10076 +       if (ret)
10077 +               return 0;
10078 +
10079 +       ret = parse_num32(&start, token[1]);
10080 +       if (ret)
10081 +               parse_err("illegal start address\n");
10082 +
10083 +       ret = parse_num32(&len, token[2]);
10084 +       if (ret)
10085 +               parse_err("illegal device length\n");
10086 +
10087 +       register_device(name, start, len);
10088 +
10089 +       return 0;
10090 +}
10091 +
10092 +module_param_call(phram, phram_setup, NULL, NULL, 000);
10093 +MODULE_PARM_DESC(phram, "Memory region to map. \"map=<name>,<start><length>\"");
10094 +
10095 +/*
10096 + * Just for compatibility with slram, this is horrible and should go someday.
10097 + */
10098 +static int __init slram_setup(const char *val, struct kernel_param *kp)
10099 +{
10100 +       char buf[256], *str = buf;
10101 +
10102 +       if (!val || !val[0])
10103 +               parse_err("no arguments to \"slram=\"\n");
10104 +
10105 +       if (strnlen(val, sizeof(str)) >= sizeof(str))
10106 +               parse_err("parameter too long\n");
10107 +
10108 +       strcpy(str, val);
10109 +
10110 +       while (str) {
10111 +               char *token[3];
10112 +               char *name;
10113 +               uint32_t start;
10114 +               uint32_t len;
10115 +               int i, ret;
10116 +
10117 +               for (i=0; i<3; i++) {
10118 +                       token[i] = strsep(&str, ",");
10119 +                       if (token[i])
10120 +                               continue;
10121 +                       parse_err("wrong number of arguments to \"slram=\"\n");
10122 +               }
10123 +
10124 +               /* name */
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");
10130 +               if (ret)
10131 +                       return 1;
10132 +
10133 +               /* start */
10134 +               ret = parse_num32(&start, token[1]);
10135 +               if (ret)
10136 +                       parse_err("illegal start address\n");
10137 +
10138 +               /* len */
10139 +               if (token[2][0] == '+')
10140 +                       ret = parse_num32(&len, token[2] + 1);
10141 +               else
10142 +                       ret = parse_num32(&len, token[2]);
10143 +
10144 +               if (ret)
10145 +                       parse_err("illegal device length\n");
10146 +
10147 +               if (token[2][0] != '+') {
10148 +                       if (len < start)
10149 +                               parse_err("end < start\n");
10150 +                       len -= start;
10151 +               }
10152 +
10153 +               register_device(name, start, len);
10154 +       }
10155 +       return 1;
10156 +}
10157 +
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>\"");
10160 +
10161 +
10162 +int __init init_phram(void)
10163 +{
10164 +       printk(KERN_ERR "phram loaded\n");
10165 +       return 0;
10166 +}
10167 +
10168 +static void __exit cleanup_phram(void)
10169 +{
10170 +       unregister_devices();
10171 +}
10172 +
10173 +module_init(init_phram);
10174 +module_exit(cleanup_phram);
10175 +
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
10183 @@ -1,5 +1,5 @@
10184  /*
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 $
10187   *
10188   * PMC551 PCI Mezzanine Ram Device
10189   *
10190 @@ -109,12 +109,6 @@
10191  #include <linux/mtd/pmc551.h>
10192  #include <linux/mtd/compatmac.h>
10193  
10194 -#if LINUX_VERSION_CODE > 0x20300
10195 -#define PCI_BASE_ADDRESS(dev) (dev->resource[0].start)
10196 -#else
10197 -#define PCI_BASE_ADDRESS(dev) (dev->base_address[0])
10198 -#endif
10199 -
10200  static struct mtd_info *pmc551list;
10201  
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");
10205  #endif
10206  
10207 -        if (instr->callback) {
10208 -                (*(instr->callback))(instr);
10209 -       }
10210 +        mtd_erase_callback(instr);
10211          return 0;
10212  }
10213  
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 );
10220  
10221          /*
10222           * Check to see the state of the memory
10223 @@ -694,7 +686,7 @@
10224                  }
10225  
10226                  printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%lX\n",
10227 -                                   PCI_BASE_ADDRESS(PCI_Device));
10228 +                                   PCI_Device->resource[0].start);
10229  
10230                  /*
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;
10235                 }
10236 -                priv->start = ioremap((PCI_BASE_ADDRESS(PCI_Device)
10237 +                priv->start = ioremap(((PCI_Device->resource[0].start)
10238                                         & PCI_BASE_ADDRESS_MEM_MASK),
10239                                        priv->asize);
10240                 
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
10245 @@ -1,6 +1,6 @@
10246  /*======================================================================
10247  
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 $
10250  
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
10253 @@ -98,12 +98,7 @@
10254  
10255         instr->state = MTD_ERASE_DONE;
10256  
10257 -       if (instr->callback) {
10258 -               (*(instr->callback))(instr);
10259 -       }
10260 -       else {
10261 -               kfree(instr);
10262 -       }
10263 +       mtd_erase_callback(instr);
10264  
10265         return(0);
10266  }
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
10271 @@ -1,5 +1,5 @@
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 $
10275   *
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 @@
10279  {
10280      erase_unit_header_t header;
10281      loff_t offset, max_offset;
10282 -    int ret;
10283 +    size_t ret;
10284 +    int err;
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) {
10291  
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);
10295         
10296 -       if (ret) 
10297 -           return ret;
10298 +       if (err) 
10299 +           return err;
10300  
10301         if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;
10302      }
10303 @@ -958,7 +959,7 @@
10304         if (ret) {
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,
10309                    offset);
10310             return -EIO;
10311         }
10312 @@ -1093,7 +1094,7 @@
10313  
10314  int init_ftl(void)
10315  {
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");
10318  
10319         return register_mtd_blktrans(&ftl_tr);
10320  }
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
10325 @@ -7,7 +7,7 @@
10326   * (c) 1999 Machine Vision Holdings, Inc.
10327   * Author: David Woodhouse <dwmw2@infradead.org>
10328   *
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 $
10331   *
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
10334 @@ -55,9 +55,19 @@
10335         struct INFTLrecord *inftl;
10336         unsigned long temp;
10337  
10338 -       if (mtd->ecctype != MTD_ECC_RS_DiskOnChip)
10339 +       if (mtd->type != MTD_NANDFLASH)
10340 +               return;
10341 +       /* OK, this is moderately ugly.  But probably safe.  Alternatives? */
10342 +       if (memcmp(mtd->name, "DiskOnChip", 10))
10343                 return;
10344  
10345 +       if (!mtd->block_isbad) {
10346 +               printk(KERN_ERR
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");
10349 +               return;
10350 +       }
10351 +
10352         DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name);
10353  
10354         inftl = kmalloc(sizeof(*inftl), GFP_KERNEL);
10355 @@ -72,6 +82,8 @@
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;
10361  
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;
10367  
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);
10372  
10373         /*
10374          * Normally, we force a fold to happen before we run out of free
10375 @@ -198,8 +210,8 @@
10376         struct inftl_oob oob;
10377          size_t retlen;
10378  
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);
10383  
10384         memset(BlockMap, 0xff, sizeof(BlockMap));
10385         memset(BlockDeleted, 0, sizeof(BlockDeleted));
10386 @@ -284,21 +296,22 @@
10387                  if (BlockMap[block] == BLOCK_NIL)
10388                          continue;
10389                  
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); 
10395                  if (ret < 0) {
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,
10400 -                               NULL); 
10401 +                               SECTORSIZE, &retlen, movebuf);
10402                         if (ret != -EIO) 
10403                                 DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
10404                                         "away on retry?\n");
10405                  }
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);
10412         }
10413  
10414         /*
10415 @@ -326,7 +339,6 @@
10416                  if (INFTL_formatblock(inftl, thisEUN) < 0) {
10417                         /*
10418                          * Could not erase : mark block as reserved.
10419 -                        * FixMe: Update Bad Unit Table on disk.
10420                          */
10421                         inftl->PUtable[thisEUN] = BLOCK_RESERVED;
10422                  } else {
10423 @@ -354,8 +366,8 @@
10424         u16 ChainLength = 0, thislen;
10425         u16 chain, EUN;
10426  
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);
10431  
10432         for (chain = 0; chain < inftl->nb_blocks; chain++) {
10433                 EUN = inftl->VUtable[chain];
10434 @@ -416,8 +428,8 @@
10435         size_t retlen;
10436         int silly, silly2 = 3;
10437  
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);
10442  
10443         do {
10444                 /*
10445 @@ -578,8 +590,8 @@
10446         struct inftl_bci bci;
10447         size_t retlen;
10448  
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);
10453  
10454         memset(BlockUsed, 0, sizeof(BlockUsed));
10455         memset(BlockDeleted, 0, sizeof(BlockDeleted));
10456 @@ -668,7 +680,6 @@
10457                  if (INFTL_formatblock(inftl, thisEUN) < 0) {
10458                         /*
10459                          * Could not erase : mark block as reserved.
10460 -                        * FixMe: Update Bad Unit Table on medium.
10461                          */
10462                         inftl->PUtable[thisEUN] = BLOCK_RESERVED;
10463                  } else {
10464 @@ -698,8 +709,8 @@
10465         size_t retlen;
10466         struct inftl_bci bci;
10467  
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);
10472  
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);
10478         size_t retlen;
10479 -       u8 eccbuf[6];
10480 +       struct inftl_oob oob;
10481         char *p, *pend;
10482  
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);
10487  
10488         /* Is block all zero? */
10489         pend = buffer + SECTORSIZE;
10490 @@ -778,11 +789,13 @@
10491                         return 1;
10492                 }
10493  
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);
10500                 /*
10501 -                * No need to write SECTOR_USED flags since they are written
10502 +                * need to write SECTOR_USED flags since they are not written
10503                  * in mtd_writeecc
10504                  */
10505         } else {
10506 @@ -803,8 +816,8 @@
10507          struct inftl_bci bci;
10508         size_t retlen;
10509  
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);
10514  
10515         while (thisEUN < inftl->nb_blocks) {
10516                 if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
10517 @@ -846,9 +859,8 @@
10518         } else {
10519                 size_t retlen;
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,
10525 +                   buffer))
10526                         return -EIO;
10527         }
10528         return 0;
10529 @@ -881,7 +893,7 @@
10530  
10531  int __init init_inftl(void)
10532  {
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);
10536  
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
10542 @@ -8,7 +8,7 @@
10543   * Author: Fabrice Bellard (fabrice.bellard@netgem.com) 
10544   * Copyright (C) 2000 Netgem S.A.
10545   *
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 $
10548   *
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
10551 @@ -41,7 +41,7 @@
10552  #include <linux/mtd/inftl.h>
10553  #include <linux/mtd/compatmac.h>
10554  
10555 -char inftlmountrev[]="$Revision: 1.11 $";
10556 +char inftlmountrev[]="$Revision: 1.14 $";
10557  
10558  /*
10559   * find_boot_record: Find the INFTL Media Header and its Spare copy which
10560 @@ -54,14 +54,13 @@
10561  {
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;
10569 -       int retlen;
10570 +       size_t retlen;
10571  
10572 -       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=0x%x)\n",
10573 -               (int)inftl);
10574 +       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=%p)\n", inftl);
10575  
10576          /*
10577          * Assume logical EraseSize == physical erasesize for starting the
10578 @@ -72,7 +71,6 @@
10579          inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
10580  
10581         inftl->MediaUnit = BLOCK_NIL;
10582 -       inftl->SpareMediaUnit = BLOCK_NIL;
10583  
10584         /* Search for a valid boot record */
10585         for (block = 0; block < inftl->nb_blocks; block++) {
10586 @@ -82,8 +80,11 @@
10587                  * Check for BNAND header first. Then whinge if it's found
10588                  * but later checks fail.
10589                  */
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;
10598  
10599                         if (warncount) {
10600 @@ -114,36 +115,28 @@
10601                         continue;
10602                 }
10603  
10604 -               if (boot_record_count) {
10605 -                       /*
10606 -                        * We've already processed one. So we just check if
10607 -                        * this one is the same as the first one we found.
10608 -                        */
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);
10614 -                               return -1;
10615 -                       }
10616 -                       if (boot_record_count == 1)
10617 -                               inftl->SpareMediaUnit = block;
10618 -
10619 -                       /*
10620 -                        * Mark this boot record (INFTL MediaHeader) block as
10621 -                        * reserved.
10622 -                        */
10623 -                       inftl->PUtable[block] = BLOCK_RESERVED;
10624 -
10625 -                       boot_record_count++;
10626 -                       continue;
10627 -               }
10628  
10629                 /*
10630                  * This is the first we've seen.
10631                  * Copy the media header structure into place.
10632                  */
10633                 memcpy(mh, buf, sizeof(struct INFTLMediaHeader));
10634 +
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");
10641 +                       return -1;
10642 +               }
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");
10647 +                       return -1;
10648 +               }
10649 +
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;
10661                 }
10662  
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));
10671                         return -ENOMEM;
10672                 }
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));
10680                         return -ENOMEM;
10681                 }
10682 @@ -317,34 +311,23 @@
10683                 /* Mark this boot record (NFTL MediaHeader) block as reserved */
10684                 inftl->PUtable[block] = BLOCK_RESERVED;
10685  
10686 -#if 0
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);
10700 -                                       return -1;
10701 -                               }
10702 +                       int physblock;
10703 +                       /* If any of the physical eraseblocks are bad, don't
10704 +                          use the unit. */
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;
10708                         }
10709 -                       /* Mark the Bad Erase Unit as RESERVED in PUtable */
10710 -                       if (buf[i & (SECTORSIZE - 1)] != 0xff)
10711 -                               inftl->PUtable[i] = BLOCK_RESERVED;
10712                 }
10713 -#endif
10714  
10715                 inftl->MediaUnit = block;
10716 -               boot_record_count++;
10717 +               return 0;
10718         }
10719 -               
10720 -       return boot_record_count ? 0 : -1;
10721 +
10722 +       /* Not found. */
10723 +       return -1;
10724  }
10725  
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)
10730  {
10731 -       int i, retlen;
10732 -       u8 buf[SECTORSIZE];
10733 +       u8 buf[SECTORSIZE + inftl->mbd.mtd->oobsize];
10734 +       size_t retlen;
10735 +       int i;
10736  
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);
10742  
10743         for (i = 0; i < len; i += SECTORSIZE) {
10744 -               /*
10745 -                * We want to read the sector without ECC check here since a
10746 -                * free sector does not have ECC syndrome on it yet.
10747 -                */
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)
10750                         return -1;
10751                 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
10752                         return -1;
10753  
10754                 if (check_oob) {
10755 -                       if (MTD_READOOB(inftl->mbd.mtd, address,
10756 -                           inftl->mbd.mtd->oobsize, &retlen, buf) < 0)
10757 -                               return -1;
10758 -                       if (memcmpb(buf, 0xff, inftl->mbd.mtd->oobsize) != 0)
10759 +                       if (memcmpb(buf + SECTORSIZE, 0xff, inftl->mbd.mtd->oobsize) != 0)
10760                                 return -1;
10761                 }
10762                 address += SECTORSIZE;
10763 @@ -402,52 +379,62 @@
10764   * Return: 0 when succeed, -1 on error.
10765   *
10766   * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? 
10767 - *       2. UnitSizeFactor != 0xFF
10768   */
10769  int INFTL_formatblock(struct INFTLrecord *inftl, int block)
10770  {
10771 -       int retlen;
10772 +       size_t retlen;
10773         struct inftl_unittail uci;
10774         struct erase_info *instr = &inftl->instr;
10775 +       int physblock;
10776  
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);
10781  
10782         memset(instr, 0, sizeof(struct erase_info));
10783  
10784 +       /* FIXME: Shouldn't we be setting the 'discarded' flag to zero
10785 +          _first_? */
10786 +
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);
10797 +
10798 +               if (instr->state == MTD_ERASE_FAILED) {
10799 +                       printk(KERN_WARNING "INFTL: error while formatting block %d\n",
10800 +                               block);
10801 +                       goto fail;
10802 +               }
10803  
10804 -       if (instr->state == MTD_ERASE_FAILED) {
10805                 /*
10806 -                * Could not format, FixMe: We should update the BadUnitTable 
10807 -                * both in memory and on disk.
10808 -                */
10809 -               printk(KERN_WARNING "INFTL: error while formatting block %d\n",
10810 -                       block);
10811 -               return -1;
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.
10815 +               */
10816 +               if (check_free_sectors(inftl, instr->addr, instr->len, 1) != 0)
10817 +                       goto fail;
10818         }
10819  
10820 -       /*
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.
10824 -        */
10825 -       if (check_free_sectors(inftl, instr->addr, inftl->EraseSize, 1) != 0)
10826 -               return -1;
10827 -
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)
10838 -               return -1;
10839 +               goto fail;
10840         return 0;
10841 +fail:
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);
10845 +       return -1;
10846  }
10847  
10848  /*
10849 @@ -472,7 +459,6 @@
10850                 if (INFTL_formatblock(inftl, block) < 0) {
10851                         /*
10852                          * Cannot format !!!! Mark it as Bad Unit,
10853 -                        * FixMe: update the BadUnitTable on disk.
10854                          */
10855                         inftl->PUtable[block] = BLOCK_RESERVED;
10856                 } else {
10857 @@ -565,10 +551,11 @@
10858         int chain_length, do_format_chain;
10859         struct inftl_unithead1 h0;
10860         struct inftl_unittail h1;
10861 -       int i, retlen;
10862 +       size_t retlen;
10863 +       int i;
10864         u8 *ANACtable, ANAC;
10865  
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);
10868  
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
10875 @@ -1,5 +1,5 @@
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 $
10879  
10880  menu "Mapping drivers for chip access"
10881         depends on MTD!=n
10882 @@ -19,7 +19,8 @@
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.
10889  
10890  config MTD_PHYSMAP_START
10891         hex "Physical start address of flash mapping"
10892 @@ -30,6 +31,8 @@
10893           are mapped on your particular target board. Refer to the
10894           memory map which should hopefully be in the documentation for
10895           your board.
10896 +         Ignore this option if you use run-time physmap configuration
10897 +         (i.e., run-time calling physmap_configure()).
10898  
10899  config MTD_PHYSMAP_LEN
10900         hex "Physical length of flash mapping"
10901 @@ -42,9 +45,11 @@
10902           than the total amount of flash present. Refer to the memory
10903           map which should hopefully be in the documentation for your
10904           board.
10905 +         Ignore this option if you use run-time physmap configuration
10906 +         (i.e., run-time calling physmap_configure()).
10907  
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
10913         default "2"
10914         help
10915 @@ -52,6 +57,8 @@
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()).
10921  
10922  config MTD_SUN_UFLASH
10923         tristate "Sun Microsystems userflash support"
10924 @@ -94,7 +101,7 @@
10925           By default the flash is split into 3 partitions which are accessed
10926           as separate MTD devices. This board utilizes Intel StrataFlash.
10927           More info at
10928 -         <http://www.arcomcontrols.com/products/icp/pc104/processors/>.
10929 +         <http://www.arcomcontrols.com/products/icp/pc104/processors/SBC_GX1.htm>.
10930  
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>.
10939  
10940  config MTD_LUBBOCK
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>.
10948  
10949  config MTD_VMAX
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/>.
10957  
10958  config MTD_SCx200_DOCFLASH
10959         tristate "Flash device mapped with DOCCS on NatSemi SCx200"
10960 @@ -151,11 +158,11 @@
10961  
10962           BE VERY CAREFUL.
10963  
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
10970         help
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.
10974  
10975           BE VERY CAREFUL.
10976 @@ -177,7 +184,7 @@
10977  
10978  config MTD_LASAT
10979         tristate "Flash chips on LASAT board"
10980 -       depends on LASAT && MTD_CFI
10981 +       depends on LASAT
10982         help
10983           Support for the flash chips on the Lasat 100 and 200 boards.
10984  
10985 @@ -210,13 +217,59 @@
10986           You can say 'Y' to both this and 'MTD_PB1XXX_BOOT' above, to use
10987           both banks.
10988  
10989 +config MTD_PB1550
10990 +       tristate "Flash devices on Alchemy PB1550 board"
10991 +       depends on MIPS && MIPS_PB1550
10992 +       help
10993 +         Flash memory access on Alchemy Pb1550 board
10994 +
10995 +config MTD_PB1550_BOOT
10996 +       bool "PB1550 boot flash device"
10997 +       depends on MTD_PB1550
10998 +       help
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
11001 +         both banks.
11002 +
11003 +config MTD_PB1550_USER
11004 +       bool "PB1550 user flash device"
11005 +       depends on MTD_PB1550
11006 +       default y if MTD_PB1550_BOOT = n
11007 +       help
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
11010 +         both banks.
11011 +
11012 +config MTD_DB1550
11013 +       tristate "Flash devices on Alchemy DB1550 board"
11014 +       depends on MIPS && MIPS_DB1550
11015 +       help
11016 +         Flash memory access on Alchemy Db1550 board
11017 +
11018 +config MTD_DB1550_BOOT
11019 +       bool "DB1550 boot flash device"
11020 +       depends on MTD_DB1550
11021 +       help
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
11024 +         both banks.
11025 +
11026 +config MTD_DB1550_USER
11027 +       bool "DB1550 user flash device"
11028 +       depends on MTD_DB1550
11029 +       default y if MTD_DB1550_BOOT = n
11030 +       help
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
11033 +         both banks.
11034 +
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
11038         help
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>
11044  
11045  config MTD_DILNETPC_BOOTSIZE
11046         hex "Size of DIL/Net PC flash boot partition"
11047 @@ -235,6 +288,13 @@
11048  
11049           BE VERY CAREFUL.
11050  
11051 +config MTD_SBC8240
11052 +       tristate "Flash device on SBC8240"
11053 +       depends on PPC32 && MTD_JEDECPROBE && 6xx && 8260
11054 +       help
11055 +          Flash access on the SBC8240 board from Wind River.  See
11056 +          <http://www.windriver.com/products/sbc8240/>
11057 +
11058  config MTD_TQM8XXL
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/>.
11067  
11068  config MTD_MBX860
11069         tristate "System flash on MBX860 board"
11070 @@ -265,7 +325,7 @@
11071  
11072  config MTD_DBOX2
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
11076         help
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'.
11081  
11082  config MTD_EBONY
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
11087         help
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'.
11091  
11092 +config MTD_OCOTEA
11093 +       tristate "Flash devices mapped on IBM 440GX Ocotea"
11094 +       depends on MTD_CFI && PPC32 && 44x && OCOTEA
11095 +       help
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'.
11099 +
11100  config MTD_REDWOOD
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'.
11106  
11107 +config MTD_IPAQ
11108 +       tristate "CFI Flash device mapped on Compaq/HP iPAQ"
11109 +       depends on ARM && IPAQ_HANDHELD && MTD_CFI
11110 +       help
11111 +         This provides a driver for the on-board flash of the iPAQ.
11112 +
11113  config MTD_DC21285
11114         tristate "CFI Flash device mapped on DC21285 Footbridge"
11115         depends on ARM && MTD_CFI && ARCH_FOOTBRIDGE && MTD_COMPLEX_MAPPINGS
11116         help
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>.
11121  
11122  config MTD_IQ80310
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'.
11127  
11128 +config MTD_IXP4XX
11129 +       tristate "CFI Flash device mapped on Intel IXP4xx based systems"
11130 +       depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX
11131 +       help
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'.
11136 +
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
11140 +       help
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'.
11145 +
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'.
11152  
11153 +config MTD_NOR_TOTO
11154 +       tristate "NOR Flash device on TOTO board"
11155 +       depends on ARM && ARCH_OMAP && OMAP_TOTO
11156 +       help
11157 +         This enables access to the NOR flash on the Texas Instruments
11158 +         TOTO board.
11159 +
11160  config MTD_H720X
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'.
11166  
11167 +config MTD_MPC1211
11168 +       tristate "CFI Flash device mapped on Interface MPC-1211"
11169 +       depends on SUPERH && SH_MPC1211 && MTD_CFI
11170 +       help
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'.
11173 +
11174  # This needs CFI or JEDEC, depending on the cards found.
11175  config MTD_PCI
11176         tristate "PCI MTD driver"
11177 @@ -480,5 +586,28 @@
11178         help
11179           Map driver to support image based filesystems for uClinux.
11180  
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
11189 +       help
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.
11193 +
11194 +config MTD_DMV182
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
11201 +        help
11202 +          Map driver for Dy-4 SVME/DMV-182 board.
11203 +
11204  endmenu
11205  
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
11210 @@ -1,7 +1,7 @@
11211  #
11212  # linux/drivers/maps/Makefile
11213  #
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 $
11216  
11217  ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y)
11218  obj-$(CONFIG_MTD)              += map_funcs.o
11219 @@ -19,7 +19,7 @@
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
11228 @@ -31,6 +31,7 @@
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
11236 @@ -42,6 +43,9 @@
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
11246 @@ -52,6 +56,14 @@
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
11265 @@ -2,7 +2,7 @@
11266   * amd76xrom.c
11267   *
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 $
11271   */
11272  
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>
11284  
11285  
11286 +#define xstr(s) str(s)
11287 +#define str(s) #s
11288 +#define MOD_NAME xstr(KBUILD_BASENAME)
11289 +
11290 +#define ADDRESS_NAME_LEN 18
11291 +
11292 +#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
11293 +
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;
11301 +};
11302 +
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];
11312  };
11313  
11314 -
11315 -static struct amd76xrom_map_info amd76xrom_map = {
11316 -       .map = {
11317 -               .name = "AMD76X rom",
11318 -               .size = 0,
11319 -               .buswidth = 1,
11320 -       },
11321 -       .mtd = 0,
11322 -       .window_addr = 0,
11323 +static struct amd76xrom_window amd76xrom_window = {
11324 +       .maps = LIST_HEAD_INIT(amd76xrom_window.maps),
11325  };
11326  
11327 +static void amd76xrom_cleanup(struct amd76xrom_window *window)
11328 +{
11329 +       struct amd76xrom_map_info *map, *scratch;
11330 +       u8 byte;
11331 +
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);
11336 +       }
11337 +
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);
11342 +               }
11343 +               del_mtd_device(map->mtd);
11344 +               map_destroy(map->mtd);
11345 +               list_del(&map->list);
11346 +               kfree(map);
11347 +       }
11348 +       if (window->rsrc.parent) 
11349 +               release_resource(&window->rsrc);
11350 +
11351 +       if (window->virt) {
11352 +               iounmap(window->virt);
11353 +               window->virt = NULL;
11354 +               window->phys = 0;
11355 +               window->size = 0;
11356 +               window->pdev = NULL;
11357 +       }
11358 +}
11359 +
11360 +
11361  static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
11362         const struct pci_device_id *ent)
11363  {
11364 -       struct rom_window {
11365 -               u32 start;
11366 -               u32 size;
11367 -               u8 segen_bits;
11368 -       };
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 },
11373 -               { 0         , 0,           0 },
11374 -       };
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 };
11380         u8 byte;
11381 -       struct amd76xrom_map_info *info = &amd76xrom_map;
11382 -       struct rom_window *window;
11383 -       int i;
11384 -       u32 rom_size;
11385 -
11386 -       window = &rom_window[0];
11387 -
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")) {
11393 -                       break;
11394 -               }
11395 -               window++;
11396 +       struct amd76xrom_window *window = &amd76xrom_window;
11397 +       struct amd76xrom_map_info *map = 0;
11398 +       unsigned long map_top;
11399 +
11400 +       /* Remember the pci dev I find the window in */
11401 +       window->pdev = pdev;
11402 +
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 */
11407 +       }
11408 +       else if ((byte & (1<<7)) == (1<<7)) {
11409 +               window->phys = 0xffc00000; /* 4MiB */
11410 +       }
11411 +       else {
11412 +               window->phys = 0xffff0000; /* 64KiB */
11413         }
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;
11418 +       
11419 +       /*
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.
11425 +        */
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",
11435 +                       __func__,
11436 +                       window->rsrc.start, window->rsrc.end);
11437         }
11438 -#endif /* REQUEST_MEM_REGION */
11439 +
11440 +#if 0
11441  
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);
11446 +#endif
11447  
11448         /* Enable writes through the rom window */
11449         pci_read_config_byte(pdev, 0x40, &byte);
11450         pci_write_config_byte(pdev, 0x40, byte | 1);
11451 -
11452 +       
11453         /* FIXME handle registers 0x80 - 0x8C the bios region locks */
11454  
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");
11462 +               goto out;
11463 +       }
11464 +
11465 +       /* Get the first address to look for an rom chip at */
11466 +       map_top = window->phys;
11467 +#if 1
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.
11471 +        */
11472 +       if (map_top < 0xffc00000) {
11473 +               map_top = 0xffc00000;
11474 +       }
11475 +#endif
11476 +       /* Loop  through and look for rom chips */
11477 +       while((map_top - 1) < 0xffffffffUL) {
11478 +               struct cfi_private *cfi;
11479 +               unsigned long offset;
11480 +               int i;
11481  
11482 -       if (!info->window_addr) {
11483 -               printk(KERN_ERR "Failed to ioremap\n");
11484 -               goto err_out_free_mmio_region;
11485 -       }
11486 -       info->mtd = 0;
11487 -       for(i = 0; (rom_size = rom_probe_sizes[i]); i++) {
11488 -               char **chip_type;
11489 -               if (rom_size > window->size) {
11490 -                       continue;
11491 -               }
11492 -               info->map.phys = window->start + window->size - rom_size;
11493 -               info->map.virt = 
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);
11500 +               if (!map) {
11501 +                       map = kmalloc(sizeof(*map), GFP_KERNEL);
11502                 }
11503 -               if (info->mtd) {
11504 -                       break;
11505 +               if (!map) {
11506 +                       printk(KERN_ERR MOD_NAME ": kmalloc failed");
11507 +                       goto out;
11508 +               }
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);
11520 +
11521 +               /* There is no generic VPP support */
11522 +               for(map->map.bankwidth = 32; map->map.bankwidth; 
11523 +                       map->map.bankwidth >>= 1)
11524 +               {
11525 +                       char **probe_type;
11526 +                       /* Skip bankwidths that are not supported */
11527 +                       if (!map_bankwidth_supported(map->map.bankwidth))
11528 +                               continue;
11529 +
11530 +                       /* Setup the map methods */
11531 +                       simple_map_init(&map->map);
11532 +
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);
11537 +                               if (map->mtd)
11538 +                                       goto found;
11539 +                       }
11540 +               }
11541 +               map_top += ROM_PROBE_STEP_SIZE;
11542 +               continue;
11543 +       found:
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;
11550 +               }
11551 +               if (window->rsrc.parent) {
11552 +                       /*
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.
11556 +                        */
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;
11565 +                       }
11566 +               }
11567 +
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;
11574                 }
11575 +               
11576 +               /* Now that the mtd devices is complete claim and export it */
11577 +               map->mtd->owner = THIS_MODULE;
11578 +               add_mtd_device(map->mtd);
11579 +
11580 +
11581 +               /* Calculate the new value of map_top */
11582 +               map_top += map->mtd->size;
11583 +
11584 +               /* File away the map structure */
11585 +               list_add(&map->list, &window->maps);
11586 +               map = 0;
11587         }
11588 -       if (!info->mtd) {
11589 -               goto err_out_iounmap;
11590 +
11591 + out:
11592 +       /* Free any left over map structures */
11593 +       if (map) {
11594 +               kfree(map);
11595 +       }
11596 +       /* See if I have any map structures */
11597 +       if (list_empty(&window->maps)) {
11598 +               amd76xrom_cleanup(window);
11599 +               return -ENODEV;
11600         }
11601 -       printk(KERN_NOTICE "amd76xrom chip at offset: 0x%x\n",
11602 -               window->size - rom_size);
11603 -               
11604 -       info->mtd->owner = THIS_MODULE;
11605 -       add_mtd_device(info->mtd);
11606 -       info->window_start = window->start;
11607 -       info->window_size = window->size;
11608         return 0;
11609 -
11610 -err_out_iounmap:
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);
11615 -err_out_none:
11616 -#endif /* REQUEST_MEM_REGION */
11617 -       return -ENODEV;
11618  }
11619  
11620  
11621  static void __devexit amd76xrom_remove_one (struct pci_dev *pdev)
11622  {
11623 -       struct amd76xrom_map_info *info = &amd76xrom_map;
11624 -       u8 byte;
11625 -
11626 -       del_mtd_device(info->mtd);
11627 -       map_destroy(info->mtd);
11628 -       info->mtd = 0;
11629 -       info->map.virt = 0;
11630 -
11631 -       iounmap((void *)(info->window_addr));
11632 -       info->window_addr = 0;
11633 -
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;
11638  
11639 -#if REQUEST_MEM_REGION
11640 -       release_mem_region(info->window_start, info->window_size);
11641 -#endif /* REQUEST_MEM_REGION */
11642 +       amd76xrom_cleanup(window);
11643  }
11644  
11645  static struct pci_device_id amd76xrom_pci_tbl[] = {
11646 @@ -173,7 +286,7 @@
11647  
11648  #if 0
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 @@
11656  {
11657         struct pci_dev *pdev;
11658         struct pci_device_id *id;
11659 -       pdev = 0;
11660 +       pdev = NULL;
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);
11664                 if (pdev) {
11665                         break;
11666                 }
11667         }
11668         if (pdev) {
11669 -               amd76xrom_map.pdev = pdev;
11670                 return amd76xrom_init_one(pdev, &amd76xrom_pci_tbl[0]);
11671         }
11672         return -ENXIO;
11673 @@ -203,7 +315,7 @@
11674  
11675  static void __exit cleanup_amd76xrom(void)
11676  {
11677 -       amd76xrom_remove_one(amd76xrom_map.pdev);
11678 +       amd76xrom_remove_one(amd76xrom_window.pdev);
11679  }
11680  
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
11686 @@ -1,5 +1,5 @@
11687  /*
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 $
11690   * 
11691   * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for 
11692   *                              IBM 405LP Arctic boards.
11693 @@ -72,7 +72,7 @@
11694  static struct map_info arctic_mtd_map = {
11695         .name           = NAME,
11696         .size           = SIZE,
11697 -       .buswidth       = BUSWIDTH,
11698 +       .bankwidth      = BUSWIDTH,
11699         .phys           = PADDR,
11700  };
11701  
11702 @@ -98,7 +98,7 @@
11703  {
11704         printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
11705  
11706 -       arctic_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE);
11707 +       arctic_mtd_map.virt = (void __iomem *) ioremap(PADDR, SIZE);
11708  
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
11715 @@ -2,7 +2,7 @@
11716   * NV-RAM memory access on autcpu12 
11717   * (C) 2002 Thomas Gleixner (gleixner@autronix.de)
11718   *
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 $ 
11721   *
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
11724 @@ -39,7 +39,7 @@
11725  struct map_info autcpu12_sram_map = {
11726         .name = "SRAM",
11727         .size = 32768,
11728 -       .buswidth = 4,
11729 +       .bankwidth = 4,
11730         .phys = 0x12000000,
11731  };
11732  
11733 @@ -47,7 +47,7 @@
11734  {
11735         int err, save0, save1;
11736  
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");
11741                 err = -EIO;
11742 @@ -76,7 +76,7 @@
11743         /* We have a 128K found, restore 0x10000 and set size
11744          * to 128K
11745          */
11746 -       ma[_write32(&autcpu12_sram_map,save1,0x10000);
11747 +       map_write32(&autcpu12_sram_map,save1,0x10000);
11748         autcpu12_sram_map.size = SZ_128K;
11749  
11750  map:
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
11755 @@ -1,5 +1,5 @@
11756  /*
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 $
11759   * 
11760   * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for 
11761   *                              IBM 405LP Beech boards.
11762 @@ -51,7 +51,7 @@
11763  static struct map_info beech_mtd_map = {
11764         .name =         NAME,
11765         .size =         SIZE,
11766 -       .buswidth =     BUSWIDTH,
11767 +       .bankwidth =    BUSWIDTH,
11768         .phys =         PADDR
11769  };
11770  
11771 @@ -74,7 +74,7 @@
11772  {
11773         printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
11774  
11775 -       beech_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE);
11776 +       beech_mtd_map.virt = (void __iomem *) ioremap(PADDR, SIZE);
11777  
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
11784 @@ -1,7 +1,7 @@
11785  /*
11786   * Flash on Cirrus CDB89712
11787   *
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 $
11790   */
11791  
11792  #include <linux/module.h>
11793 @@ -23,7 +23,7 @@
11794  struct map_info cdb89712_flash_map = {
11795         .name = "flash",
11796         .size = FLASH_SIZE,
11797 -       .buswidth = FLASH_WIDTH,
11798 +       .bankwidth = FLASH_WIDTH,
11799         .phys = FLASH_START,
11800  };
11801  
11802 @@ -44,7 +44,7 @@
11803                 goto out;
11804         }
11805         
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");
11810                 err = -EIO;
11811 @@ -93,7 +93,7 @@
11812  struct map_info cdb89712_sram_map = {
11813         .name = "SRAM",
11814         .size = SRAM_SIZE,
11815 -       .buswidth = SRAM_WIDTH,
11816 +       .bankwidth = SRAM_WIDTH,
11817         .phys = SRAM_START,
11818  };
11819  
11820 @@ -114,7 +114,7 @@
11821                 goto out;
11822         }
11823         
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");
11828                 err = -EIO;
11829 @@ -161,7 +161,7 @@
11830  struct map_info cdb89712_bootrom_map = {
11831         .name = "BootROM",
11832         .size = BOOTROM_SIZE,
11833 -       .buswidth = BOOTROM_WIDTH,
11834 +       .bankwidth = BOOTROM_WIDTH,
11835         .phys = BOOTROM_START,
11836  };
11837  
11838 @@ -182,7 +182,7 @@
11839                 goto out;
11840         }
11841         
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");
11846                 err = -EIO;
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
11851 @@ -11,7 +11,7 @@
11852   *
11853   * (C) 2000 Nicolas Pitre <nico@cam.org>
11854   *
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 $
11857   */
11858  
11859  #include <linux/config.h>
11860 @@ -150,8 +150,8 @@
11861                         break;
11862                 }
11863  
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;
11869  
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
11875 @@ -1,7 +1,7 @@
11876  /*
11877   *  Copyright Â© 2001 Flaga hf. Medical Devices, Kári Davíðsson <kd@flaga.is>
11878   *
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 $
11881   *  
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
11884 @@ -60,7 +60,7 @@
11885  struct map_info flagadm_map = {
11886                 .name =         "FlagaDM flash device",
11887                 .size =         FLASH_SIZE,
11888 -               .buswidth =     2,
11889 +               .bankwidth =    2,
11890  };
11891  
11892  struct mtd_partition flagadm_parts[] = {
11893 @@ -96,7 +96,7 @@
11894                         FLASH_SIZE, FLASH_PHYS_ADDR);
11895         
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,
11899                                         FLASH_SIZE);
11900  
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
11906 @@ -1,5 +1,5 @@
11907  /*
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 $
11910   *
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 @@
11914         char *name;
11915         unsigned long window_addr;
11916         unsigned long window_size;
11917 -       int buswidth;
11918 +       int bankwidth;
11919         int num_partitions;
11920  };
11921  
11922 @@ -116,7 +116,7 @@
11923          "big flash",     // name
11924         0x08000000,      // window_addr
11925         0x02000000,      // window_size
11926 -        4,               // buswidth
11927 +        4,               // bankwidth
11928         1,               // num_partitions
11929      }
11930  
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
11938      },
11939  
11940 @@ -170,14 +170,14 @@
11941  
11942  
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");
11948                         return -EIO;
11949                 }
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;
11956  #endif
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
11961 @@ -0,0 +1,188 @@
11962 +/*
11963 + * Flash memory access on Alchemy Db1550 board
11964 + * 
11965 + * $Id: db1550-flash.c,v 1.4 2004/09/16 23:27:12 gleixner Exp $
11966 + *
11967 + * (C) 2004 Embedded Edge, LLC, based on db1550-flash.c:
11968 + * (C) 2003 Pete Popov <pete_popov@yahoo.com>
11969 + * 
11970 + */
11971 +
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>
11977 +
11978 +#include <linux/mtd/mtd.h>
11979 +#include <linux/mtd/map.h>
11980 +#include <linux/mtd/partitions.h>
11981 +
11982 +#include <asm/io.h>
11983 +#include <asm/au1000.h>
11984 +
11985 +#ifdef         DEBUG_RW
11986 +#define        DBG(x...)       printk(x)
11987 +#else
11988 +#define        DBG(x...)       
11989 +#endif
11990 +
11991 +static unsigned long window_addr;
11992 +static unsigned long window_size;
11993 +
11994 +
11995 +static struct map_info db1550_map = {
11996 +       .name = "Db1550 flash",
11997 +};
11998 +
11999 +static unsigned char flash_bankwidth = 4;
12000 +
12001 +/* 
12002 + * Support only 64MB NOR Flash parts
12003 + */
12004 +
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
12011 +#endif
12012 +
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
12016 + * partition.
12017 + */
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
12022 +        */
12023 +        {
12024 +                .name = "User FS",
12025 +                .size =   (0x1FC00000 - 0x18000000),
12026 +                .offset = 0x0000000
12027 +        },{
12028 +                .name = "yamon",
12029 +                .size = 0x0100000,
12030 +               .offset = MTDPART_OFS_APPEND,
12031 +                .mask_flags = MTD_WRITEABLE
12032 +        },{
12033 +                .name = "raw kernel",
12034 +               .size = (0x300000 - 0x40000), /* last 256KB is yamon env */
12035 +               .offset = MTDPART_OFS_APPEND,
12036 +        }
12037 +};
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
12042 +        */
12043 +        {
12044 +                .name = "User FS",
12045 +                .size =   0x03c00000,
12046 +                .offset = 0x0000000
12047 +        },{
12048 +                .name = "yamon",
12049 +                .size = 0x0100000,
12050 +               .offset = MTDPART_OFS_APPEND,
12051 +                .mask_flags = MTD_WRITEABLE
12052 +        },{
12053 +                .name = "raw kernel",
12054 +               .size = (0x300000-0x40000), /* last 256KB is yamon env */
12055 +               .offset = MTDPART_OFS_APPEND,
12056 +        }
12057 +};
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
12062 +        */
12063 +        {
12064 +                .name = "User FS",
12065 +                .size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */
12066 +                .offset = 0x0000000
12067 +        },{
12068 +                .name = "raw kernel",
12069 +               .size = MTDPART_SIZ_FULL,
12070 +               .offset = MTDPART_OFS_APPEND,
12071 +        }
12072 +};
12073 +#else
12074 +#error MTD_DB1550 define combo error /* should never happen */
12075 +#endif
12076 +
12077 +#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
12078 +
12079 +static struct mtd_info *mymtd;
12080 +
12081 +/*
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.
12086 + */
12087 +int setup_flash_params(void)
12088 +{
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; 
12098 +#endif
12099 +       return 0;
12100 +}
12101 +
12102 +int __init db1550_mtd_init(void)
12103 +{
12104 +       struct mtd_partition *parts;
12105 +       int nb_parts = 0;
12106 +       
12107 +       /* Default flash bankwidth */
12108 +       db1550_map.bankwidth = flash_bankwidth;
12109 +
12110 +       if (setup_flash_params()) 
12111 +               return -ENXIO;
12112 +
12113 +       /*
12114 +        * Static partition definition selection
12115 +        */
12116 +       parts = db1550_partitions;
12117 +       nb_parts = NB_OF(db1550_partitions);
12118 +       db1550_map.size = window_size;
12119 +
12120 +       /*
12121 +        * Now let's probe for the actual flash.  Do it here since
12122 +        * specific machine settings might have been set above.
12123 +        */
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;
12131 +
12132 +       add_mtd_partitions(mymtd, parts, nb_parts);
12133 +       return 0;
12134 +}
12135 +
12136 +static void __exit db1550_mtd_cleanup(void)
12137 +{
12138 +       if (mymtd) {
12139 +               del_mtd_partitions(mymtd);
12140 +               map_destroy(mymtd);
12141 +       }
12142 +}
12143 +
12144 +module_init(db1550_mtd_init);
12145 +module_exit(db1550_mtd_cleanup);
12146 +
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
12154 @@ -0,0 +1,219 @@
12155 +/*
12156 + * Flash memory access on Alchemy Db1xxx boards
12157 + * 
12158 + * $Id: db1x00-flash.c,v 1.4 2004/09/16 23:27:12 gleixner Exp $
12159 + *
12160 + * (C) 2003 Pete Popov <ppopov@pacbell.net>
12161 + * 
12162 + */
12163 +
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>
12169 +
12170 +#include <linux/mtd/mtd.h>
12171 +#include <linux/mtd/map.h>
12172 +#include <linux/mtd/partitions.h>
12173 +
12174 +#include <asm/io.h>
12175 +#include <asm/au1000.h>
12176 +#include <asm/db1x00.h>
12177 +
12178 +#ifdef         DEBUG_RW
12179 +#define        DBG(x...)       printk(x)
12180 +#else
12181 +#define        DBG(x...)       
12182 +#endif
12183 +
12184 +static unsigned long window_addr;
12185 +static unsigned long window_size;
12186 +static unsigned long flash_size;
12187 +
12188 +static BCSR * const bcsr = (BCSR *)0xAE000000;
12189 +static unsigned char flash_bankwidth = 4;
12190 +
12191 +/* 
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.
12196 + */
12197 +
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
12201 + * partition.
12202 + */
12203 +static struct mtd_partition db1x00_partitions[] = {
12204 +        {
12205 +                .name         =  "User FS",
12206 +                .size         =  0x1c00000,
12207 +                .offset       =  0x0000000
12208 +        },{
12209 +                .name         =  "yamon",
12210 +                .size         =  0x0100000,
12211 +               .offset       =  MTDPART_OFS_APPEND,
12212 +                .mask_flags   =  MTD_WRITEABLE
12213 +        },{
12214 +                .name         =  "raw kernel",
12215 +               .size         =  (0x300000-0x40000), /* last 256KB is env */
12216 +               .offset       =  MTDPART_OFS_APPEND,
12217 +        }
12218 +};
12219 +#elif defined(DB1X00_BOOT_ONLY)
12220 +static struct mtd_partition db1x00_partitions[] = {
12221 +        {
12222 +                .name         =  "User FS",
12223 +                .size         =  0x00c00000,
12224 +                .offset       =  0x0000000
12225 +        },{
12226 +                .name         =  "yamon",
12227 +                .size         =  0x0100000,
12228 +               .offset       =  MTDPART_OFS_APPEND,
12229 +                .mask_flags   =  MTD_WRITEABLE
12230 +        },{
12231 +                .name         =  "raw kernel",
12232 +               .size         =  (0x300000-0x40000), /* last 256KB is env */
12233 +               .offset       =  MTDPART_OFS_APPEND,
12234 +        }
12235 +};
12236 +#elif defined(DB1X00_USER_ONLY)
12237 +static struct mtd_partition db1x00_partitions[] = {
12238 +        {
12239 +                .name         =  "User FS",
12240 +                .size         =  0x0e00000,
12241 +                .offset       =  0x0000000
12242 +        },{
12243 +                .name         =  "raw kernel",
12244 +               .size         =  MTDPART_SIZ_FULL,
12245 +               .offset       =  MTDPART_OFS_APPEND,
12246 +        }
12247 +};
12248 +#else
12249 +#error MTD_DB1X00 define combo error /* should never happen */
12250 +#endif
12251 +#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
12252 +
12253 +#define NAME           "Db1x00 Linux Flash"
12254 +
12255 +static struct map_info db1xxx_mtd_map = {
12256 +       .name           = NAME,
12257 +};
12258 +
12259 +static struct mtd_partition *parsed_parts;
12260 +static struct mtd_info *db1xxx_mtd;
12261 +
12262 +/*
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.
12267 + */
12268 +int setup_flash_params(void)
12269 +{
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; 
12282 +#endif
12283 +                       break;
12284 +               case 1:
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;
12302 +#endif
12303 +                       break;
12304 +               case 2:
12305 +                       /* 256 Mbit devices */
12306 +                       flash_size = 0x4000000; /* 64MB per part */
12307 +#if defined(DB1X00_BOTH_BANKS)
12308 +                       return 1;
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 */
12316 +                       return 1;
12317 +#endif
12318 +                       break;
12319 +               default:
12320 +                       return 1;
12321 +       }
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;
12326 +       return 0;
12327 +}
12328 +
12329 +int __init db1x00_mtd_init(void)
12330 +{
12331 +       struct mtd_partition *parts;
12332 +       int nb_parts = 0;
12333 +       
12334 +       if (setup_flash_params()) 
12335 +               return -ENXIO;
12336 +
12337 +       /*
12338 +        * Static partition definition selection
12339 +        */
12340 +       parts = db1x00_partitions;
12341 +       nb_parts = NB_OF(db1x00_partitions);
12342 +
12343 +       /*
12344 +        * Now let's probe for the actual flash.  Do it here since
12345 +        * specific machine settings might have been set above.
12346 +        */
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;
12353 +
12354 +       add_mtd_partitions(db1xxx_mtd, parts, nb_parts);
12355 +       return 0;
12356 +}
12357 +
12358 +static void __exit db1x00_mtd_cleanup(void)
12359 +{
12360 +       if (db1xxx_mtd) {
12361 +               del_mtd_partitions(db1xxx_mtd);
12362 +               map_destroy(db1xxx_mtd);
12363 +               if (parsed_parts)
12364 +                       kfree(parsed_parts);
12365 +       }
12366 +}
12367 +
12368 +module_init(db1x00_mtd_init);
12369 +module_exit(db1x00_mtd_cleanup);
12370 +
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
12378 @@ -1,5 +1,5 @@
12379  /*
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 $
12382   *
12383   * D-Box 2 flash driver
12384   */
12385 @@ -13,6 +13,7 @@
12386  #include <linux/mtd/map.h>
12387  #include <linux/mtd/partitions.h>
12388  #include <linux/config.h>
12389 +#include <linux/errno.h>
12390  
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
12395         },
12396         {
12397 -       .name           = "flfs (ppcboot)",
12398 +       .name           = "FLFS (U-Boot)",
12399         .size           = 128 * 1024, 
12400         .offset         = MTDPART_OFS_APPEND, 
12401         .mask_flags     = 0
12402         },
12403         {
12404 -       .name           = "root (cramfs)",      
12405 +       .name           = "Root (SquashFS)",    
12406         .size           = 7040 * 1024, 
12407         .offset         = MTDPART_OFS_APPEND, 
12408         .mask_flags     = 0
12409         },
12410         {
12411 -       .name           = "var (jffs2)",
12412 +       .name           = "var (JFFS2)",
12413         .size           = 896 * 1024, 
12414         .offset         = MTDPART_OFS_APPEND, 
12415         .mask_flags     = 0
12416         },
12417         {
12418 -       .name           = "flash without bootloader",   
12419 +       .name           = "Flash without bootloader",   
12420         .size           = MTDPART_SIZ_FULL, 
12421         .offset         = 128 * 1024, 
12422         .mask_flags     = 0
12423         },
12424         {
12425 -       .name           = "complete flash",     
12426 +       .name           = "Complete Flash",     
12427         .size           = MTDPART_SIZ_FULL, 
12428         .offset         = 0, 
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,
12434 -       .buswidth       = 4,
12435 +       .bankwidth      = 4,
12436         .phys           = WINDOW_ADDR,
12437  };
12438  
12439  int __init init_dbox2_flash(void)
12440  {
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);
12444  
12445         if (!dbox2_flash_map.virt) {
12446                 printk("Failed to ioremap\n");
12447 @@ -86,7 +87,7 @@
12448         mymtd = do_map_probe("cfi_probe", &dbox2_flash_map);
12449         if (!mymtd) {
12450             // Probe for single Intel 28F640
12451 -           dbox2_flash_map.buswidth = 2;
12452 +           dbox2_flash_map.bankwidth = 2;
12453         
12454             mymtd = do_map_probe("cfi_probe", &dbox2_flash_map);
12455         }
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
12460 @@ -5,13 +5,14 @@
12461   *
12462   * This code is GPL
12463   * 
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 $
12466   */
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>
12473  
12474  #include <linux/mtd/mtd.h>
12475  #include <linux/mtd/map.h>
12476 @@ -19,91 +20,117 @@
12477  
12478  #include <asm/io.h>
12479  #include <asm/hardware/dec21285.h>
12480 +#include <asm/mach-types.h>
12481  
12482  
12483 -static struct mtd_info *mymtd;
12484 +static struct mtd_info *dc21285_mtd;
12485  
12486 -__u8 dc21285_read8(struct map_info *map, unsigned long ofs)
12487 +#ifdef CONFIG_ARCH_NETWINDER
12488 +/* 
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
12492 + * write access.
12493 + */
12494 +static void nw_en_write(void) {
12495 +       extern spinlock_t gpio_lock;
12496 +       unsigned long flags;
12497 +
12498 +       /*
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.
12501 +        */
12502 +       spin_lock_irqsave(&gpio_lock, flags);
12503 +       cpld_modify(1, 1);
12504 +       spin_unlock_irqrestore(&gpio_lock, flags);
12505 +
12506 +       /*
12507 +        * let the ISA bus to catch on...
12508 +        */
12509 +       udelay(25);
12510 +}
12511 +#else
12512 +#define nw_en_write() do { } while (0)
12513 +#endif
12514 +
12515 +static map_word dc21285_read8(struct map_info *map, unsigned long ofs)
12516  {
12517 -       return *(__u8*)(map->map_priv_1 + ofs);
12518 +       return *(uint8_t*)(map->map_priv_1 + ofs);
12519  }
12520  
12521 -__u16 dc21285_read16(struct map_info *map, unsigned long ofs)
12522 +static map_word dc21285_read16(struct map_info *map, unsigned long ofs)
12523  {
12524 -       return *(__u16*)(map->map_priv_1 + ofs);
12525 +       return *(uint16_t*)(map->map_priv_1 + ofs);
12526  }
12527  
12528 -__u32 dc21285_read32(struct map_info *map, unsigned long ofs)
12529 +static map_word dc21285_read32(struct map_info *map, unsigned long ofs)
12530  {
12531 -       return *(__u32*)(map->map_priv_1 + ofs);
12532 +       return *(uint32_t*)(map->map_priv_1 + ofs);
12533  }
12534  
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)
12537  {
12538         memcpy(to, (void*)(map->map_priv_1 + from), len);
12539  }
12540  
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)
12543  {
12544 +       if (machine_is_netwinder())
12545 +               nw_en_write();
12546         *CSR_ROMWRITEREG = adr & 3;
12547         adr &= ~3;
12548 -       *(__u8*)(map->map_priv_1 + adr) = d;
12549 +       *(uint8_t*)(map->map_priv_1 + adr) = d.x[0];
12550  }
12551  
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)
12554  {
12555 +       if (machine_is_netwinder())
12556 +               nw_en_write();
12557         *CSR_ROMWRITEREG = adr & 3;
12558         adr &= ~3;
12559 -       *(__u16*)(map->map_priv_1 + adr) = d;
12560 +       *(uint16_t*)(map->map_priv_1 + adr) = d.x[0];
12561  }
12562  
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)
12565  {
12566 -       *(__u32*)(map->map_priv_1 + adr) = d;
12567 +       if (machine_is_netwinder())
12568 +               nw_en_write();
12569 +       *(uint32_t*)(map->map_priv_1 + adr) = d.x[0];
12570  }
12571  
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)
12574  {
12575 -       switch (map->buswidth) {
12576 -               case 4:
12577 -                       while (len > 0) {
12578 -                               __u32 d = *((__u32*)from)++;
12579 -                               dc21285_write32(map, d, to);
12580 -                               to += 4;
12581 -                               len -= 4;
12582 -                       }
12583 -                       break;
12584 -               case 2:
12585 -                       while (len > 0) {
12586 -                               __u16 d = *((__u16*)from)++;
12587 -                               dc21285_write16(map, d, to);
12588 -                               to += 2;
12589 -                               len -= 2;
12590 -                       }
12591 -                       break;
12592 -               case 1:
12593 -                       while (len > 0) {
12594 -                               __u8 d = *((__u8*)from)++;
12595 -                               dc21285_write8(map, d, to);
12596 -                               to++;
12597 -                               len--;
12598 -                       }
12599 -                       break;
12600 +       while (len > 0) {
12601 +               uint32_t d = *((uint32_t*)from)++;
12602 +               dc21285_write32(map, d, to);
12603 +               to += 4;
12604 +               len -= 4;
12605 +       }
12606 +}
12607 +
12608 +static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const void *from, ssize_t len)
12609 +{
12610 +       while (len > 0) {
12611 +               uint16_t d = *((uint16_t*)from)++;
12612 +               dc21285_write16(map, d, to);
12613 +               to += 2;
12614 +               len -= 2;
12615         }
12616  }
12617  
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)
12620 +{
12621 +       uint8_t d = *((uint8_t*)from)++;
12622 +       dc21285_write8(map, d, to);
12623 +       to++;
12624 +       len--;
12625 +}
12626 +
12627 +static struct map_info dc21285_map = {
12628         .name = "DC21285 flash",
12629         .phys = NO_XIP,
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
12639  };
12640  
12641  
12642 @@ -113,81 +140,97 @@
12643  static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
12644  #endif
12645    
12646 -int __init init_dc21285(void)
12647 +static int __init init_dc21285(void)
12648  {
12649  
12650 -       /* 
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.
12655 -        */
12656 -       /* access time */
12657 -       *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16));
12658 -       /* burst time */
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
12663 +       int nrparts;
12664 +#endif
12665  
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;
12675                         break;
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;
12682                         break;
12683                 case SA110_CNTL_ROMWIDTH_32: 
12684 -                       dc21285_map.buswidth = 4; 
12685 +                       dc21285_map.bankwidth = 4; 
12686                         break;
12687 +                       dc21285_map.read = dc21285_read32;
12688 +                       dc21285_map.write = dc21285_write32;
12689 +                       dc21285_map.copy_to = dc21285_copy_to_32;
12690                 default:
12691 -                       printk (KERN_ERR "DC21285 flash: undefined buswidth\n");
12692 +                       printk (KERN_ERR "DC21285 flash: undefined bankwidth\n");
12693                         return -ENXIO;
12694         }
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);
12699  
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");
12705                 return -EIO;
12706         }
12707  
12708 -       mymtd = do_map_probe("cfi_probe", &dc21285_map);
12709 -       if (mymtd) {
12710 -               int nrparts = 0;
12711 +       if (machine_is_ebsa285()) {
12712 +               dc21285_mtd = do_map_probe("cfi_probe", &dc21285_map);
12713 +       } else {
12714 +               dc21285_mtd = do_map_probe("jedec_probe", &dc21285_map);
12715 +       }
12716  
12717 -               mymtd->owner = THIS_MODULE;
12718 -                       
12719 -               /* partition fixup */
12720 +       if (!dc21285_mtd) {
12721 +               iounmap((void *)dc21285_map.map_priv_1);
12722 +               return -ENXIO;
12723 +       }       
12724 +       
12725 +       dc21285_mtd->owner = THIS_MODULE;
12726  
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);
12731 -                       return 0;
12732 -               }
12733 -#endif
12734 -               add_mtd_device(mymtd);
12735 -               return 0;
12736 +       nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, (void *)0);
12737 +       if (nrparts > 0)
12738 +               add_mtd_partitions(dc21285_mtd, dc21285_parts, nrparts);
12739 +       else    
12740 +#endif 
12741 +               add_mtd_device(dc21285_mtd);
12742 +                       
12743 +       if(machine_is_ebsa285()) {
12744 +               /* 
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.
12749 +                */
12750 +               /* access time */
12751 +               *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16));
12752 +               /* burst time */
12753 +               *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20));
12754 +               /* tristate time */
12755 +               *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24));
12756         }
12757 -
12758 -       iounmap((void *)dc21285_map.map_priv_1);
12759 -       return -ENXIO;
12760 +       
12761 +       return 0;
12762  }
12763  
12764  static void __exit cleanup_dc21285(void)
12765  {
12766  #ifdef CONFIG_MTD_PARTITIONS
12767         if (dc21285_parts) {
12768 -               del_mtd_partitions(mymtd);
12769 +               del_mtd_partitions(dc21285_mtd);
12770                 kfree(dc21285_parts);
12771         } else
12772  #endif
12773 -               del_mtd_device(mymtd);
12774 +               del_mtd_device(dc21285_mtd);
12775  
12776 -       map_destroy(mymtd);
12777 +       map_destroy(dc21285_mtd);
12778         iounmap((void *)dc21285_map.map_priv_1);
12779  }
12780  
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
12785 @@ -14,7 +14,7 @@
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
12788   *
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 $
12791   *
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,
12798 -       .buswidth = 1,
12799 +       .bankwidth = 1,
12800         .set_vpp = adnp_set_vpp,
12801         .phys = WINDOW_ADDR
12802  };
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);
12806  
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);
12809  
12810         dnpc_map_flash(dnpc_map.phys, dnpc_map.size);
12811  
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
12816 @@ -0,0 +1,150 @@
12817 +
12818 +/*
12819 + * drivers/mtd/maps/svme182.c
12820 + * 
12821 + * Flash map driver for the Dy4 SVME182 board
12822 + * 
12823 + * $Id: dmv182.c,v 1.4 2004/09/16 23:27:13 gleixner Exp $
12824 + *
12825 + * Copyright 2003-2004, TimeSys Corporation
12826 + *
12827 + * Based on the SVME181 flash map, by Tom Nelson, Dot4, Inc. for TimeSys Corp.
12828 + *
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.
12833 + */
12834 +
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>
12845 +
12846 +/*
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.
12850 + *
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.
12854 + */
12855 +
12856 +#define FLASH_BASE_ADDR 0xf0000000
12857 +#define FLASH_BANK_SIZE (128*1024*1024)
12858 +
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");
12862 +
12863 +static struct map_info svme182_map = {
12864 +       .name           = "Dy4 SVME182",
12865 +       .bankwidth      = 32,
12866 +       .size           =  128 * 1024 * 1024
12867 +};
12868 +
12869 +#define BOOTIMAGE_PART_SIZE            ((6*1024*1024)-RESERVED_PART_SIZE)
12870 +
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)
12878 +
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.
12885 +       {
12886 +               name:       "Lower PABS and CPU 0 bootloader or kernel",
12887 +               size:       6*1024*1024,
12888 +               offset:     0,
12889 +       },
12890 +       {
12891 +               name:       "Root Filesystem",
12892 +               size:       10*1024*1024,
12893 +               offset:     MTDPART_OFS_NXTBLK
12894 +       },
12895 +       {
12896 +               name:       "CPU1 Bootloader",
12897 +               size:       1024*1024,
12898 +               offset:     MTDPART_OFS_NXTBLK,
12899 +       },
12900 +       {
12901 +               name:       "Extra",
12902 +               size:       110*1024*1024,
12903 +               offset:     MTDPART_OFS_NXTBLK
12904 +       },
12905 +       {
12906 +               name:       "Foundation Firmware and Upper PABS",
12907 +               size:       1024*1024,
12908 +               offset:     MTDPART_OFS_NXTBLK,
12909 +               mask_flags: MTD_WRITEABLE // read-only
12910 +       }
12911 +};
12912 +
12913 +static struct mtd_info *this_mtd;
12914 +
12915 +static int __init init_svme182(void)
12916 +{
12917 +       struct mtd_partition *partitions;
12918 +       int num_parts = sizeof(svme182_partitions) / sizeof(struct mtd_partition);
12919 +
12920 +       partitions = svme182_partitions;
12921 +
12922 +       svme182_map.virt = 
12923 +               (void __iomem *)ioremap(FLASH_BASE_ADDR, svme182_map.size);
12924 +               
12925 +       if (svme182_map.virt == 0) {
12926 +               printk("Failed to ioremap FLASH memory area.\n");
12927 +               return -EIO;
12928 +       }
12929 +
12930 +       simple_map_init(&svme182_map);
12931 +
12932 +       this_mtd = do_map_probe("cfi_probe", &svme182_map);
12933 +       if (!this_mtd)
12934 +       {
12935 +               iounmap((void *)svme182_map.virt);
12936 +               return -ENXIO;
12937 +       }
12938 +
12939 +       printk(KERN_NOTICE "SVME182 flash device: %dMiB at 0x%08x\n",
12940 +                  this_mtd->size >> 20, FLASH_BASE_ADDR);
12941 +
12942 +       this_mtd->owner = THIS_MODULE;
12943 +       add_mtd_partitions(this_mtd, partitions, num_parts);
12944 +
12945 +       return 0;
12946 +}
12947 +
12948 +static void __exit cleanup_svme182(void)
12949 +{
12950 +       if (this_mtd)
12951 +       {
12952 +               del_mtd_partitions(this_mtd);
12953 +               map_destroy(this_mtd);
12954 +       }
12955 +
12956 +       if (svme182_map.virt)
12957 +       {
12958 +               iounmap((void *)svme182_map.virt);
12959 +               svme182_map.virt = 0;
12960 +       }
12961 +
12962 +       return;
12963 +}
12964 +
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
12971 @@ -1,11 +1,11 @@
12972  /*
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 $
12975   * 
12976   * Mapping for Ebony user flash
12977   *
12978 - * Matt Porter <mporter@mvista.com>
12979 + * Matt Porter <mporter@kernel.crashing.org>
12980   *
12981 - * Copyright 2002 MontaVista Software Inc.
12982 + * Copyright 2002-2004 MontaVista Software Inc.
12983   *
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>
12996  
12997  static struct mtd_info *flash;
12998  
12999  static struct map_info ebony_small_map = {
13000         .name =         "Ebony small flash",
13001         .size =         EBONY_SMALL_FLASH_SIZE,
13002 -       .buswidth =     1,
13003 +       .bankwidth =    1,
13004  };
13005  
13006  static struct map_info ebony_large_map = {
13007         .name =         "Ebony large flash",
13008         .size =         EBONY_LARGE_FLASH_SIZE,
13009 -       .buswidth =     1,
13010 +       .bankwidth =    1,
13011  };
13012  
13013  static struct mtd_partition ebony_small_partitions[] = {
13014 @@ -63,7 +64,7 @@
13015  int __init init_ebony(void)
13016  {
13017         u8 fpga0_reg;
13018 -       unsigned long fpga0_adr;
13019 +       u8 *fpga0_adr;
13020         unsigned long long small_flash_base, large_flash_base;
13021  
13022         fpga0_adr = ioremap64(EBONY_FPGA_ADDR, 16);
13023 @@ -71,7 +72,7 @@
13024                 return -ENOMEM;
13025  
13026         fpga0_reg = readb(fpga0_adr);
13027 -       iounmap64(fpga0_adr);
13028 +       iounmap(fpga0_adr);
13029  
13030         if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
13031                         !EBONY_FLASH_SEL(fpga0_reg))
13032 @@ -93,7 +94,7 @@
13033  
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);
13039  
13040         if (!ebony_small_map.virt) {
13041 @@ -160,5 +161,5 @@
13042  module_exit(cleanup_ebony);
13043  
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
13052 @@ -1,5 +1,5 @@
13053  /*
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 $
13056   *
13057   * Handle mapping of the NOR flash on Cogent EDB7312 boards
13058   *
13059 @@ -28,8 +28,8 @@
13060  #define BUSWIDTH    2
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 }
13067  
13068  #define MSG_PREFIX "EDB7312-NOR:"   /* prefix for our printk()'s */
13069  #define MTDID      "edb7312-nor"    /* for mtdparts= partitioning */
13070 @@ -39,7 +39,7 @@
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,
13077  };
13078  
13079 @@ -82,8 +82,8 @@
13080  
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);
13087  
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
13094 @@ -16,7 +16,7 @@
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
13097  
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 $
13100  
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.
13103 @@ -53,7 +53,7 @@
13104  #define PAGE_IO_SIZE 2
13105  
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;
13110  
13111  /* partition_info gives details on the logical partitions that the split the 
13112 @@ -107,39 +107,19 @@
13113  }
13114  
13115  
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)
13118  {
13119 -       __u8 ret;
13120 +       map_word ret;
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);
13125 -       return ret;
13126 -}
13127 -
13128 -static __u16 elan_104nc_read16(struct map_info *map, unsigned long ofs)
13129 -{
13130 -       __u16 ret;
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);
13135 -       return ret;
13136 -}
13137 -
13138 -static __u32 elan_104nc_read32(struct map_info *map, unsigned long ofs)
13139 -{
13140 -       __u32 ret;
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);
13146         return ret;
13147  }
13148  
13149  static void elan_104nc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
13150  {
13151 -       while(len) {
13152 +       while (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 @@
13157         }
13158  }
13159  
13160 -static void elan_104nc_write8(struct map_info *map, __u8 d, unsigned long adr)
13161 -{
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);
13166 -}
13167 -
13168 -static void elan_104nc_write16(struct map_info *map, __u16 d, unsigned long adr)
13169 -{
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);
13174 -}
13175 -
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)
13178  {
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);
13184  }
13185  
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
13189                         the chips */
13190 -       .buswidth = 2,
13191 -       .read8 = elan_104nc_read8,
13192 -       .read16 = elan_104nc_read16,
13193 -       .read32 = elan_104nc_read32,
13194 +       .bankwidth = 2,
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
13202  };
13203  
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. */
13207  
13208 -       iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
13209 +       iomapadr = (void __iomem *)ioremap(WINDOW_START, WINDOW_LENGTH);
13210         if (!iomapadr) {
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
13217 @@ -5,7 +5,7 @@
13218   *  Copyright (C) 2001 Altera Corporation
13219   *  Copyright (C) 2001 Red Hat, Inc.
13220   *
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 $ 
13223   *
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
13226 @@ -50,7 +50,7 @@
13227  static struct map_info epxa_map = {
13228         .name =         "EPXA flash",
13229         .size =         FLASH_SIZE,
13230 -       .buswidth =     2,
13231 +       .bankwidth =    2,
13232         .phys =         FLASH_START,
13233  };
13234  
13235 @@ -62,7 +62,7 @@
13236         
13237         printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
13238  
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);
13243                 return -EIO;
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
13248 @@ -1,6 +1,6 @@
13249  /* fortunet.c memory map
13250   *
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 $
13253   */
13254  
13255  #include <linux/module.h>
13256 @@ -25,7 +25,7 @@
13257  struct map_region
13258  {
13259         int                     window_addr_physical;
13260 -       int                     altbuswidth;
13261 +       int                     altbankwidth;
13262         struct map_info         map_info;
13263         struct mtd_info         *mymtd;
13264         struct mtd_partition    parts[MAX_NUM_PARTITIONS];
13265 @@ -41,7 +41,7 @@
13266  
13267  struct map_info default_map = {
13268         .size = DEF_WINDOW_SIZE,
13269 -       .buswidth = 4,
13270 +       .bankwidth = 4,
13271  };
13272  
13273  static char * __init get_string_option(char *dest,int dest_size,char *sor)
13274 @@ -102,7 +102,7 @@
13275         if(params[0]<1)
13276         {
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");
13280                 return 1;
13281         }
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 @@
13293         }
13294         if(params[0]>3)
13295         {
13296 -               map_regions[params[1]].map_info.buswidth = params[4];
13297 +               map_regions[params[1]].map_info.bankwidth = params[4];
13298         }
13299         if(params[0]>4)
13300         {
13301 -               map_regions[params[1]].altbuswidth = params[5];
13302 +               map_regions[params[1]].altbankwidth = params[5];
13303         }
13304         return 1;
13305  }
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,
13317  
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))
13330                         {
13331 -                               printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate buswidth "
13332 +                               printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth "
13333                                         "for %s flash.\n",
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);
13341                         }
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
13346 @@ -2,9 +2,11 @@
13347   * Flash memory access on Hynix GMS30C7201/HMS30C7202 based 
13348   * evaluation boards
13349   * 
13350 + * $Id: h720x-flash.c,v 1.10 2004/09/16 23:27:13 gleixner Exp $
13351 + *
13352   * (C) 2002 Jungjun Kim <jungjun.kim@hynix.com>
13353   *     2003 Thomas Gleixner <tglx@linutronix.de>       
13354 -*/
13355 + */
13356  
13357  #include <linux/config.h>
13358  #include <linux/module.h>
13359 @@ -24,7 +26,7 @@
13360  
13361  static struct map_info h720x_map = {
13362         .name =         "H720X",
13363 -       .buswidth =     4,
13364 +       .bankwidth =    4,
13365         .size =         FLASH_SIZE,
13366         .phys =         FLASH_PHYS,
13367  };
13368 @@ -71,7 +73,7 @@
13369  
13370         char    *part_type = NULL;
13371         
13372 -       h720x_map.virt = (unsigned long)ioremap(FLASH_PHYS, FLASH_SIZE);
13373 +       h720x_map.virt = (void __iomem *)ioremap(FLASH_PHYS, FLASH_SIZE);
13374  
13375         if (!h720x_map.virt) {
13376                 printk(KERN_ERR "H720x-MTD: ioremap failed\n");
13377 @@ -80,13 +82,13 @@
13378  
13379         simple_map_init(&h720x_map);
13380  
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);
13385         if (!mymtd) {
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);
13392         }
13393             
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
13398 @@ -0,0 +1,380 @@
13399 +/*
13400 + * ichxrom.c
13401 + *
13402 + * Normal mappings of chips in physical memory
13403 + * $Id: ichxrom.c,v 1.13 2004/09/17 11:45:06 eric Exp $
13404 + */
13405 +
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>
13419 +
13420 +#define xstr(s) str(s)
13421 +#define str(s) #s
13422 +#define MOD_NAME xstr(KBUILD_BASENAME)
13423 +
13424 +#define ADDRESS_NAME_LEN 18
13425 +
13426 +#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
13427 +
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
13433 +
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;
13441 +};
13442 +
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];
13449 +};
13450 +
13451 +static struct ichxrom_window ichxrom_window = {
13452 +       .maps = LIST_HEAD_INIT(ichxrom_window.maps),
13453 +};
13454 +
13455 +static void ichxrom_cleanup(struct ichxrom_window *window)
13456 +{
13457 +       struct ichxrom_map_info *map, *scratch;
13458 +       u16 word;
13459 +
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);
13463 +
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);
13471 +               kfree(map);
13472 +       }
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;
13481 +       }
13482 +}
13483 +
13484 +
13485 +static int __devinit ichxrom_init_one (struct pci_dev *pdev,
13486 +       const struct pci_device_id *ent)
13487 +{
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;
13492 +       u8 byte;
13493 +       u16 word;
13494 +
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.
13501 +        *
13502 +        * Also you can page firmware hubs if an 8MB window isn't enough 
13503 +        * but don't currently handle that case either.
13504 +        */
13505 +       window->pdev = pdev;
13506 +
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;
13515 +               }
13516 +               else if ((byte & 0x0e) == 0x0e) {
13517 +                       window->phys = 0xff500000;
13518 +               }
13519 +               else if ((byte & 0x0c) == 0x0c) {
13520 +                       window->phys = 0xff600000;
13521 +               }
13522 +               else if ((byte & 0x08) == 0x08) {
13523 +                       window->phys = 0xff700000;
13524 +               }
13525 +       }
13526 +       else if ((byte & 0xfe) == 0xfe) {
13527 +               window->phys = 0xffc80000;
13528 +       }
13529 +       else if ((byte & 0xfc) == 0xfc) {
13530 +               window->phys = 0xffd00000;
13531 +       }
13532 +       else if ((byte & 0xf8) == 0xf8) {
13533 +               window->phys = 0xffd80000;
13534 +       }
13535 +       else if ((byte & 0xf0) == 0xf0) {
13536 +               window->phys = 0xffe00000;
13537 +       }
13538 +       else if ((byte & 0xe0) == 0xe0) {
13539 +               window->phys = 0xffe80000;
13540 +       }
13541 +       else if ((byte & 0xc0) == 0xc0) {
13542 +               window->phys = 0xfff00000;
13543 +       }
13544 +       else if ((byte & 0x80) == 0x80) {
13545 +               window->phys = 0xfff80000; 
13546 +       }
13547 +
13548 +       if (window->phys == 0) {
13549 +               printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
13550 +               goto out;
13551 +       }
13552 +       window->phys -= 0x400000UL;
13553 +       window->size = (0xffffffffUL - window->phys) + 1UL;
13554 +
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.
13560 +                */
13561 +               printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n");
13562 +               goto out;
13563 +       }
13564 +       pci_write_config_word(pdev, BIOS_CNTL, word | 1);
13565 +
13566 +       /*
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.
13569 +        */
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",
13579 +                       __func__,
13580 +                       window->rsrc.start, window->rsrc.end);
13581 +       }
13582 +
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);
13588 +               goto out;
13589 +       }
13590 +
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;
13595 +       }
13596 +#if 1
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.
13600 +        */
13601 +       if (map_top < 0xffc00000) {
13602 +               map_top = 0xffc00000;
13603 +       }
13604 +#endif
13605 +       /* Loop through and look for rom chips */
13606 +       while((map_top - 1) < 0xffffffffUL) {
13607 +               struct cfi_private *cfi;
13608 +               unsigned long offset;
13609 +               int i;
13610 +
13611 +               if (!map) {
13612 +                       map = kmalloc(sizeof(*map), GFP_KERNEL);
13613 +               }
13614 +               if (!map) {
13615 +                       printk(KERN_ERR MOD_NAME ": kmalloc failed");
13616 +                       goto out;
13617 +               }
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);
13629 +
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.
13633 +                */
13634 +               for(map->map.bankwidth = 32; map->map.bankwidth; 
13635 +                       map->map.bankwidth >>= 1)
13636 +               {
13637 +                       char **probe_type;
13638 +                       /* Skip bankwidths that are not supported */
13639 +                       if (!map_bankwidth_supported(map->map.bankwidth))
13640 +                               continue;
13641 +
13642 +                       /* Setup the map methods */
13643 +                       simple_map_init(&map->map);
13644 +
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);
13649 +                               if (map->mtd)
13650 +                                       goto found;
13651 +                       }
13652 +               }
13653 +               map_top += ROM_PROBE_STEP_SIZE;
13654 +               continue;
13655 +       found:
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;
13662 +               }
13663 +               if (window->rsrc.parent) {
13664 +                       /*
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.
13668 +                        */
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;
13677 +                       }
13678 +               }
13679 +
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;
13686 +               }
13687 +               
13688 +               /* Now that the mtd devices is complete claim and export it */
13689 +               map->mtd->owner = THIS_MODULE;
13690 +               add_mtd_device(map->mtd);
13691 +
13692 +
13693 +               /* Calculate the new value of map_top */
13694 +               map_top += map->mtd->size;
13695 +
13696 +               /* File away the map structure */
13697 +               list_add(&map->list, &window->maps);
13698 +               map = 0;
13699 +       }
13700 +
13701 + out:
13702 +       /* Free any left over map structures */
13703 +       if (map) {
13704 +               kfree(map);
13705 +       }
13706 +       /* See if I have any map structures */
13707 +       if (list_empty(&window->maps)) {
13708 +               ichxrom_cleanup(window);
13709 +               return -ENODEV;
13710 +       }
13711 +       return 0;
13712 +
13713 +}
13714 +
13715 +
13716 +static void __devexit ichxrom_remove_one (struct pci_dev *pdev)
13717 +{
13718 +       struct ichxrom_window *window = &ichxrom_window;
13719 +       ichxrom_cleanup(window);
13720 +}
13721 +
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, },
13733 +       { 0, },
13734 +};
13735 +
13736 +MODULE_DEVICE_TABLE(pci, ichxrom_pci_tbl);
13737 +
13738 +#if 0
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,
13744 +};
13745 +#endif
13746 +
13747 +int __init init_ichxrom(void)
13748 +{
13749 +       struct pci_dev *pdev;
13750 +       struct pci_device_id *id;
13751 +
13752 +       pdev = NULL;
13753 +       for (id = ichxrom_pci_tbl; id->vendor; id++) {
13754 +               pdev = pci_find_device(id->vendor, id->device, NULL);
13755 +               if (pdev) {
13756 +                       break;
13757 +               }
13758 +       }
13759 +       if (pdev) {
13760 +               return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]);
13761 +       }
13762 +       return -ENXIO;
13763 +#if 0
13764 +       return pci_module_init(&ichxrom_driver);
13765 +#endif
13766 +}
13767 +
13768 +static void __exit cleanup_ichxrom(void)
13769 +{
13770 +       ichxrom_remove_one(ichxrom_window.pdev);
13771 +}
13772 +
13773 +module_init(init_ichxrom);
13774 +module_exit(cleanup_ichxrom);
13775 +
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
13783 @@ -1,5 +1,5 @@
13784  /*
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 $
13787   *
13788   * Handle mapping of the NOR flash on implementa A7 boards
13789   *
13790 @@ -30,25 +30,25 @@
13791  #define NUM_FLASHBANKS 2
13792  #define BUSWIDTH     4
13793  
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 }
13798  
13799  #define MSG_PREFIX "impA7:"   /* prefix for our printk()'s */
13800  #define MTDID      "impa7-%d"  /* for mtdparts= partitioning */
13801  
13802 -static struct mtd_info *impa7_mtd[NUM_FLASHBANKS] = { 0 };
13803 +static struct mtd_info *impa7_mtd[NUM_FLASHBANKS];
13804  
13805  
13806  static struct map_info impa7_map[NUM_FLASHBANKS] = {
13807         {
13808                 .name = "impA7 NOR Flash Bank #0",
13809                 .size = WINDOW_SIZE0,
13810 -               .buswidth = BUSWIDTH,
13811 +               .bankwidth = BUSWIDTH,
13812         },
13813         {
13814                 .name = "impA7 NOR Flash Bank #1",
13815                 .size = WINDOW_SIZE1,
13816 -               .buswidth = BUSWIDTH,
13817 +               .bankwidth = BUSWIDTH,
13818         },
13819  };
13820  
13821 @@ -91,7 +91,7 @@
13822                        pt[i].size, pt[i].addr);
13823  
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
13834 @@ -0,0 +1,258 @@
13835 +/*======================================================================
13836 +
13837 +    drivers/mtd/maps/armflash.c: ARM Flash Layout/Partitioning
13838 +  
13839 +    Copyright (C) 2000 ARM Limited
13840 +  
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.
13845 +  
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.
13850 +  
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
13854 +  
13855 +   This is access code for flashes using ARM's flash partitioning 
13856 +   standards.
13857 +
13858 +   $Id: integrator-flash-v24.c,v 1.14 2004/09/16 23:27:13 gleixner Exp $
13859 +
13860 +======================================================================*/
13861 +
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>
13869 +
13870 +#include <linux/mtd/mtd.h>
13871 +#include <linux/mtd/map.h>
13872 +#include <linux/mtd/partitions.h>
13873 +
13874 +#include <asm/hardware.h>
13875 +#include <asm/io.h>
13876 +#include <asm/system.h>
13877 +
13878 +// board specific stuff - sorry, it should be in arch/arm/mach-*.
13879 +#ifdef CONFIG_ARCH_INTEGRATOR
13880 +
13881 +#define FLASH_BASE     INTEGRATOR_FLASH_BASE
13882 +#define FLASH_SIZE     INTEGRATOR_FLASH_SIZE
13883 +
13884 +#define FLASH_PART_SIZE 0x400000
13885 +
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)
13890 +
13891 +/*
13892 + * Initialise the flash access systems:
13893 + *  - Disable VPP
13894 + *  - Assert WP
13895 + *  - Set write enable bit in EBI reg
13896 + */
13897 +static void armflash_flash_init(void)
13898 +{
13899 +       unsigned int tmp;
13900 +
13901 +       __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
13902 +
13903 +       tmp = __raw_readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
13904 +       __raw_writel(tmp, EBI_CSR1);
13905 +
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);
13910 +       }
13911 +}
13912 +
13913 +/*
13914 + * Shutdown the flash access systems:
13915 + *  - Disable VPP
13916 + *  - Assert WP
13917 + *  - Clear write enable bit in EBI reg
13918 + */
13919 +static void armflash_flash_exit(void)
13920 +{
13921 +       unsigned int tmp;
13922 +
13923 +       __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
13924 +
13925 +       /*
13926 +        * Clear the write enable bit in system controller EBI register.
13927 +        */
13928 +       tmp = __raw_readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
13929 +       __raw_writel(tmp, EBI_CSR1);
13930 +
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);
13935 +       }
13936 +}
13937 +
13938 +static void armflash_flash_wp(int on)
13939 +{
13940 +       unsigned int reg;
13941 +
13942 +       if (on)
13943 +               reg = SC_CTRLC;
13944 +       else
13945 +               reg = SC_CTRLS;
13946 +
13947 +       __raw_writel(INTEGRATOR_SC_CTRL_nFLWP, reg);
13948 +}
13949 +
13950 +static void armflash_set_vpp(struct map_info *map, int on)
13951 +{
13952 +       unsigned int reg;
13953 +
13954 +       if (on)
13955 +               reg = SC_CTRLS;
13956 +       else
13957 +               reg = SC_CTRLC;
13958 +
13959 +       __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
13960 +}
13961 +#endif
13962 +
13963 +#ifdef CONFIG_ARCH_P720T
13964 +
13965 +#define FLASH_BASE             (0x04000000)
13966 +#define FLASH_SIZE             (64*1024*1024)
13967 +
13968 +#define FLASH_PART_SIZE        (4*1024*1024)
13969 +#define FLASH_BLOCK_SIZE       (128*1024)
13970 +
13971 +static void armflash_flash_init(void)
13972 +{
13973 +}
13974 +
13975 +static void armflash_flash_exit(void)
13976 +{
13977 +}
13978 +
13979 +static void armflash_flash_wp(int on)
13980 +{
13981 +}
13982 +
13983 +static void armflash_set_vpp(struct map_info *map, int on)
13984 +{
13985 +}
13986 +#endif
13987 +
13988 +
13989 +static struct map_info armflash_map =
13990 +{
13991 +       .name =         "AFS",
13992 +       .set_vpp =      armflash_set_vpp,
13993 +       .phys =         FLASH_BASE,
13994 +};
13995 +
13996 +static struct mtd_info *mtd;
13997 +static struct mtd_partition *parts;
13998 +static const char *probes[] = { "RedBoot", "afs", NULL };
13999 +
14000 +static int __init armflash_cfi_init(void *base, u_int size)
14001 +{
14002 +       int ret;
14003 +
14004 +       armflash_flash_init();
14005 +       armflash_flash_wp(1);
14006 +
14007 +       /*
14008 +        * look for CFI based flash parts fitted to this board
14009 +        */
14010 +       armflash_map.size       = size;
14011 +       armflash_map.bankwidth   = 4;
14012 +       armflash_map.virt = (void __iomem *) base;
14013 +
14014 +       simple_map_init(&armflash_map);
14015 +
14016 +       /*
14017 +        * Also, the CFI layer automatically works out what size
14018 +        * of chips we have, and does the necessary identification
14019 +        * for us automatically.
14020 +        */
14021 +       mtd = do_map_probe("cfi_probe", &armflash_map);
14022 +       if (!mtd)
14023 +               return -ENXIO;
14024 +
14025 +       mtd->owner = THIS_MODULE;
14026 +
14027 +       ret = parse_mtd_partitions(mtd, probes, &parts, (void *)0);
14028 +       if (ret > 0) {
14029 +               ret = add_mtd_partitions(mtd, parts, ret);
14030 +               if (ret)
14031 +                       printk(KERN_ERR "mtd partition registration "
14032 +                               "failed: %d\n", ret);
14033 +       }
14034 +
14035 +       /*
14036 +        * If we got an error, free all resources.
14037 +        */
14038 +       if (ret < 0) {
14039 +               del_mtd_partitions(mtd);
14040 +               map_destroy(mtd);
14041 +       }
14042 +
14043 +       return ret;
14044 +}
14045 +
14046 +static void armflash_cfi_exit(void)
14047 +{
14048 +       if (mtd) {
14049 +               del_mtd_partitions(mtd);
14050 +               map_destroy(mtd);
14051 +       }
14052 +       if (parts)
14053 +               kfree(parts);
14054 +}
14055 +
14056 +static int __init armflash_init(void)
14057 +{
14058 +       int err = -EBUSY;
14059 +       void *base;
14060 +
14061 +       if (request_mem_region(FLASH_BASE, FLASH_SIZE, "flash") == NULL)
14062 +               goto out;
14063 +
14064 +       base = ioremap(FLASH_BASE, FLASH_SIZE);
14065 +       err = -ENOMEM;
14066 +       if (base == NULL)
14067 +               goto release;
14068 +
14069 +       err = armflash_cfi_init(base, FLASH_SIZE);
14070 +       if (err) {
14071 +               iounmap(base);
14072 +release:
14073 +               release_mem_region(FLASH_BASE, FLASH_SIZE);
14074 +       }
14075 +out:
14076 +       return err;
14077 +}
14078 +
14079 +static void __exit armflash_exit(void)
14080 +{
14081 +       armflash_cfi_exit();
14082 +       iounmap((void *)armflash_map.virt);
14083 +       release_mem_region(FLASH_BASE, FLASH_SIZE);
14084 +       armflash_flash_exit();
14085 +}
14086 +
14087 +module_init(armflash_init);
14088 +module_exit(armflash_exit);
14089 +
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
14097 @@ -22,7 +22,7 @@
14098     This is access code for flashes using ARM's flash partitioning 
14099     standards.
14100  
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 $
14103  
14104  ======================================================================*/
14105  
14106 @@ -108,9 +108,9 @@
14107          * look for CFI based flash parts fitted to this board
14108          */
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;
14117  
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
14122 @@ -0,0 +1,464 @@
14123 +/*
14124 + * Flash memory access on iPAQ Handhelds (either SA1100 or PXA250 based)
14125 + * 
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
14129 + * 
14130 + * $Id: ipaq-flash.c,v 1.2 2004/09/16 23:27:13 gleixner Exp $
14131 + */
14132 +
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>
14144 +
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>
14150 +#endif
14151 +
14152 +#include <asm/hardware.h>
14153 +#include <asm/arch-sa1100/h3600.h>
14154 +#include <asm/io.h>
14155 +
14156 +
14157 +#ifndef CONFIG_IPAQ_HANDHELD
14158 +#error This is for iPAQ Handhelds only
14159 +#endif
14160 +#ifdef CONFIG_SA1100_JORNADA56X
14161 +
14162 +static void jornada56x_set_vpp(struct map_info *map, int vpp)
14163 +{
14164 +       if (vpp)
14165 +               GPSR = GPIO_GPIO26;
14166 +       else
14167 +               GPCR = GPIO_GPIO26;
14168 +       GPDR |= GPIO_GPIO26;
14169 +}
14170 +
14171 +#endif
14172 +
14173 +#ifdef CONFIG_SA1100_JORNADA720
14174 +
14175 +static void jornada720_set_vpp(struct map_info *map, int vpp)
14176 +{
14177 +       if (vpp)
14178 +               PPSR |= 0x80;
14179 +       else
14180 +               PPSR &= ~0x80;
14181 +       PPDR |= 0x80;
14182 +}
14183 +
14184 +#endif
14185 +
14186 +#define MAX_IPAQ_CS 2          /* Number of CS we are going to test */
14187 +
14188 +#define IPAQ_MAP_INIT(X) \
14189 +       { \
14190 +               name:           "IPAQ flash " X, \
14191 +       }
14192 +
14193 +
14194 +static struct map_info ipaq_map[MAX_IPAQ_CS] = {
14195 +       IPAQ_MAP_INIT("bank 1"),
14196 +       IPAQ_MAP_INIT("bank 2")
14197 +};
14198 +
14199 +static struct mtd_info *my_sub_mtd[MAX_IPAQ_CS] = {
14200 +       NULL,
14201 +       NULL
14202 +};
14203 +
14204 +/*
14205 + * Here are partition information for all known IPAQ-based devices.
14206 + * See include/linux/mtd/partitions.h for definition of the mtd_partition
14207 + * structure.
14208 + *
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.
14213 + *
14214 + * Please keep these in alphabetical order, and formatted as per existing
14215 + * entries.  Thanks.
14216 + */
14217 +
14218 +#ifdef CONFIG_IPAQ_HANDHELD
14219 +static unsigned long h3xxx_max_flash_size = 0x04000000;
14220 +static struct mtd_partition h3xxx_partitions[] = {
14221 +       {
14222 +               name:           "H3XXX boot firmware",
14223 +#ifndef CONFIG_LAB
14224 +               size:           0x00040000,
14225 +#else
14226 +               size:           0x00080000,
14227 +#endif
14228 +               offset:         0,
14229 +#ifndef CONFIG_LAB
14230 +               mask_flags:     MTD_WRITEABLE,  /* force read-only */
14231 +#endif
14232 +       }, 
14233 +       {
14234 +               name:           "H3XXX root jffs2",
14235 +#ifndef CONFIG_LAB
14236 +               size:           0x2000000 - 2*0x40000, /* Warning, this is fixed later */
14237 +               offset:         0x00040000,
14238 +#else
14239 +               size:           0x2000000 - 0x40000 - 0x80000, /* Warning, this is fixed later */
14240 +               offset:         0x00080000,
14241 +#endif
14242 +       },
14243 +       {
14244 +               name:           "asset",
14245 +               size:           0x40000,
14246 +               offset:         0x2000000 - 0x40000, /* Warning, this is fixed later */
14247 +               mask_flags:     MTD_WRITEABLE,  /* force read-only */
14248 +       }
14249 +};
14250 +
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 */
14254 +       {
14255 +               name:           "second H3XXX root jffs2",
14256 +               size:           0x1000000 - 0x40000, /* Warning, this is fixed later */
14257 +               offset:         0x00000000,
14258 +       },
14259 +       {
14260 +               name:           "second asset",
14261 +               size:           0x40000,
14262 +               offset:         0x1000000 - 0x40000, /* Warning, this is fixed later */
14263 +               mask_flags:     MTD_WRITEABLE,  /* force read-only */
14264 +       }
14265 +};
14266 +#endif
14267 +
14268 +static spinlock_t ipaq_vpp_lock = SPIN_LOCK_UNLOCKED;
14269 +
14270 +static void h3xxx_set_vpp(struct map_info *map, int vpp)
14271 +{
14272 +       static int nest = 0;
14273 +       
14274 +       spin_lock(&ipaq_vpp_lock);
14275 +       if (vpp)
14276 +               nest++;
14277 +       else
14278 +               nest--;
14279 +       if (nest)
14280 +               assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 1);
14281 +       else
14282 +               assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 0);
14283 +       spin_unlock(&ipaq_vpp_lock);
14284 +}
14285 +
14286 +#endif
14287 +
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[] = {
14291 +       {
14292 +               name:           "Jornada boot firmware",
14293 +               size:           0x00040000,
14294 +               offset:         0,
14295 +               mask_flags:     MTD_WRITEABLE,  /* force read-only */
14296 +       }, {
14297 +               name:           "Jornada root jffs2",
14298 +               size:           MTDPART_SIZ_FULL,
14299 +               offset:         0x00040000,
14300 +       }
14301 +};
14302 +#endif
14303 +
14304 +
14305 +static struct mtd_partition *parsed_parts;
14306 +static struct mtd_info *mymtd;
14307 +
14308 +static unsigned long cs_phys[] = {
14309 +#ifdef CONFIG_ARCH_SA1100
14310 +       SA1100_CS0_PHYS,
14311 +       SA1100_CS1_PHYS,
14312 +       SA1100_CS2_PHYS,
14313 +       SA1100_CS3_PHYS,
14314 +       SA1100_CS4_PHYS,
14315 +       SA1100_CS5_PHYS,
14316 +#else 
14317 +       PXA_CS0_PHYS,
14318 +       PXA_CS1_PHYS,
14319 +       PXA_CS2_PHYS,
14320 +       PXA_CS3_PHYS,
14321 +       PXA_CS4_PHYS,
14322 +       PXA_CS5_PHYS,
14323 +#endif
14324 +};
14325 +
14326 +static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
14327 +
14328 +static int __init h1900_special_case(void);
14329 +
14330 +int __init ipaq_mtd_init(void)
14331 +{
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 */
14338 +
14339 +       /* Default flash bankwidth */
14340 +       // ipaq_map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
14341 +       
14342 +       if (machine_is_h1900())
14343 +       {
14344 +               /* For our intents, the h1900 is not a real iPAQ, so we special-case it. */
14345 +               return h1900_special_case();
14346 +       }
14347 +
14348 +       if (machine_is_h3100() || machine_is_h1900())
14349 +               for(i=0; i<MAX_IPAQ_CS; i++)
14350 +                       ipaq_map[i].bankwidth = 2;
14351 +       else
14352 +               for(i=0; i<MAX_IPAQ_CS; i++)
14353 +                       ipaq_map[i].bankwidth = 4;
14354 +                       
14355 +       /*
14356 +        * Static partition definition selection
14357 +        */
14358 +       part_type = "static";
14359 +
14360 +       simple_map_init(&ipaq_map[0]);
14361 +       simple_map_init(&ipaq_map[1]);
14362 +
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;
14374 +               }
14375 +               if (machine_is_h3600()) {
14376 +                       /* No asset partition here */
14377 +                       h3xxx_partitions[1].size += 0x40000;
14378 +                       nb_parts--;
14379 +               }
14380 +       }
14381 +#endif
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;
14388 +       }
14389 +#endif
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;
14396 +       }
14397 +#endif
14398 +
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);
14406 +       }
14407 +#endif
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;
14414 +       }
14415 +#endif
14416 +
14417 +
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]);
14425 +                       }
14426 +                       if (!my_sub_mtd[i]) {
14427 +                               printk(KERN_NOTICE "iPAQ flash: failed to find flash.\n");
14428 +                               if (i)
14429 +                                       break;
14430 +                               else
14431 +                                       return -ENXIO;
14432 +                       } else
14433 +                               printk(KERN_NOTICE "iPAQ flash: found %d bytes\n", my_sub_mtd[i]->size);
14434 +                       
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;
14439 +               }
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 */;
14444 +#      else
14445 +               h3xxx_partitions[1].size = tot_flashsize - 2 * 0x40000;
14446 +#      endif
14447 +               h3xxx_partitions[2].offset = tot_flashsize - 0x40000;
14448 +               /* and concat the devices */
14449 +               mymtd = mtd_concat_create(&my_sub_mtd[0], i,
14450 +                                         "ipaq");
14451 +               if (!mymtd) {
14452 +                       printk("Cannot create iPAQ concat device\n");
14453 +                       return -ENXIO;
14454 +               }
14455 +#else
14456 +               mymtd = my_sub_mtd[0];
14457 +
14458 +               /* 
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. 
14463 +                */
14464 +               mymtd->name = "ipaq";
14465 +
14466 +               if ((machine_is_h3600())) {
14467 +#      ifdef CONFIG_LAB
14468 +                       h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x80000;
14469 +#      else
14470 +                       h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000;
14471 +#      endif
14472 +                       nb_parts = 2;
14473 +               } else {
14474 +#      ifdef CONFIG_LAB
14475 +                       h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000 - 0x80000; /* extra big boot block */
14476 +#      else
14477 +                       h3xxx_partitions[1].size = my_sub_mtd[0]->size - 2*0x40000;
14478 +#      endif
14479 +                       h3xxx_partitions[2].offset = my_sub_mtd[0]->size - 0x40000;
14480 +               }
14481 +
14482 +               if (my_sub_mtd[1]) {
14483 +#      ifdef CONFIG_LAB
14484 +                       h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x80000;
14485 +#      else
14486 +                       h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x40000;
14487 +#      endif
14488 +                       h3xxx_partitions_bank2[1].offset = my_sub_mtd[1]->size - 0x40000;
14489 +               }
14490 +#endif
14491 +       }
14492 +       else {
14493 +               /*
14494 +                * Now let's probe for the actual flash.  Do it here since
14495 +                * specific machine settings might have been set above.
14496 +                */
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]);
14499 +               if (!mymtd)
14500 +                       return -ENXIO;
14501 +               mymtd->owner = THIS_MODULE;
14502 +       }
14503 +
14504 +
14505 +       /*
14506 +        * Dynamic partition selection stuff (might override the static ones)
14507 +        */
14508 +
14509 +        i = parse_mtd_partitions(mymtd, part_probes, &parsed_parts, 0);
14510 +                       
14511 +        if (i > 0) {
14512 +                nb_parts = parsed_nr_parts = i;
14513 +                parts = parsed_parts;
14514 +                part_type = "dynamic";
14515 +        }
14516 +
14517 +        if (!parts) {
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]);
14523 +#endif
14524 +        } else {
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));
14530 +#endif
14531 +        }
14532 +
14533 +        return 0;
14534 +}
14535 +
14536 +static void __exit ipaq_mtd_cleanup(void)
14537 +{
14538 +       int i;
14539 +
14540 +       if (mymtd) {
14541 +               del_mtd_partitions(mymtd);
14542 +#ifndef CONFIG_MTD_CONCAT
14543 +               if (my_sub_mtd[1])
14544 +                       del_mtd_partitions(my_sub_mtd[1]);
14545 +#endif
14546 +               map_destroy(mymtd);
14547 +#ifdef CONFIG_MTD_CONCAT
14548 +               for(i=0; i<MAX_IPAQ_CS; i++) 
14549 +#else
14550 +                       for(i=1; i<MAX_IPAQ_CS; i++) 
14551 +#endif           
14552 +                       {
14553 +                               if (my_sub_mtd[i])
14554 +                                       map_destroy(my_sub_mtd[i]);
14555 +                       }
14556 +               if (parsed_parts)
14557 +                       kfree(parsed_parts);
14558 +       }
14559 +}
14560 +
14561 +static int __init h1900_special_case(void)
14562 +{
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;
14570 +       
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]);
14573 +       if (!mymtd)
14574 +               return -ENODEV;
14575 +       add_mtd_device(mymtd);
14576 +       printk(KERN_NOTICE "iPAQ flash: registered h1910 flash\n");
14577 +       
14578 +       return 0;
14579 +}
14580 +
14581 +module_init(ipaq_mtd_init);
14582 +module_exit(ipaq_mtd_cleanup);
14583 +
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
14591 @@ -1,5 +1,5 @@
14592  /*
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 $
14595   *
14596   * Mapping for the Intel XScale IQ80310 evaluation board
14597   *
14598 @@ -31,7 +31,7 @@
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
14605  };
14606  
14607 @@ -68,7 +68,7 @@
14608         int parsed_nr_parts = 0;
14609         int ret;
14610  
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");
14615                 return -EIO;
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
14620 @@ -0,0 +1,281 @@
14621 +/*
14622 + * $Id: ixp2000.c,v 1.3 2004/09/16 23:27:13 gleixner Exp $
14623 + *
14624 + * drivers/mtd/maps/ixp2000.c
14625 + *
14626 + * Mapping for the Intel XScale IXP2000 based systems
14627 + *
14628 + * Copyright (C) 2002 Intel Corp.
14629 + * Copyright (C) 2003-2004 MontaVista Software, Inc.
14630 + *
14631 + * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
14632 + * Maintainer: Deepak Saxena <dsaxena@plexity.net>
14633 + *
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.
14637 + * 
14638 + */
14639 +
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>
14650 +
14651 +#include <asm/io.h>
14652 +#include <asm/hardware.h>
14653 +#include <asm/mach-types.h>
14654 +#include <asm/mach/flash.h>
14655 +
14656 +#include <linux/reboot.h>
14657 +
14658 +struct ixp2000_flash_info {
14659 +       struct          mtd_info *mtd;
14660 +       struct          map_info map;
14661 +       struct          mtd_partition *partitions;
14662 +       struct          resource *res;
14663 +       int             nr_banks;
14664 +};
14665 +
14666 +static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
14667 +{      
14668 +       unsigned long (*set_bank)(unsigned long) = 
14669 +               (unsigned long(*)(unsigned long))map->map_priv_2;
14670 +
14671 +       return (set_bank ? set_bank(ofs) : ofs);
14672 +}
14673 +
14674 +#ifdef __ARMEB__
14675 +/*
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.
14679 + */
14680 +static int erratum44_workaround = 0;
14681 +
14682 +static inline unsigned long address_fix8_write(unsigned long addr)
14683 +{
14684 +       if (erratum44_workaround) {
14685 +               return (addr ^ 3);
14686 +       }
14687 +       return addr;
14688 +}
14689 +#else
14690 +
14691 +#define address_fix8_write(x)  (x)
14692 +#endif
14693 +
14694 +static map_word ixp2000_flash_read8(struct map_info *map, unsigned long ofs)
14695 +{
14696 +       map_word val;
14697 +
14698 +       val.x[0] =  *((u8 *)(map->map_priv_1 + flash_bank_setup(map, ofs)));
14699 +       return val;
14700 +}
14701 +
14702 +/*
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.
14706 + */
14707 +static void ixp2000_flash_copy_from(struct map_info *map, void *to,
14708 +                             unsigned long from, ssize_t len)
14709 +{
14710 +       from = flash_bank_setup(map, from);
14711 +       while(len--) 
14712 +               *(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++);
14713 +}
14714 +
14715 +static void ixp2000_flash_write8(struct map_info *map, map_word d, unsigned long ofs)
14716 +{
14717 +       *(__u8 *) (address_fix8_write(map->map_priv_1 +
14718 +                                     flash_bank_setup(map, ofs))) = d.x[0];
14719 +}
14720 +
14721 +static void ixp2000_flash_copy_to(struct map_info *map, unsigned long to,
14722 +                           const void *from, ssize_t len)
14723 +{
14724 +       to = flash_bank_setup(map, to);
14725 +       while(len--) {
14726 +               unsigned long tmp = address_fix8_write(map->map_priv_1 + to++);
14727 +               *(__u8 *)(tmp) = *(__u8 *)(from++);
14728 +       }
14729 +}
14730 +
14731 +
14732 +static int ixp2000_flash_remove(struct device *_dev)
14733 +{
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);
14737 +
14738 +       dev_set_drvdata(&dev->dev, NULL);
14739 +
14740 +       if(!info)
14741 +               return 0;
14742 +
14743 +       if (info->mtd) {
14744 +               del_mtd_partitions(info->mtd);
14745 +               map_destroy(info->mtd);
14746 +       }
14747 +       if (info->map.map_priv_1)
14748 +               iounmap((void *) info->map.map_priv_1);
14749 +
14750 +       if (info->partitions) {
14751 +               kfree(info->partitions); }
14752 +
14753 +       if (info->res) {
14754 +               release_resource(info->res);
14755 +               kfree(info->res);
14756 +       }
14757 +
14758 +       if (plat->exit)
14759 +               plat->exit();
14760 +
14761 +       return 0;
14762 +}
14763 +
14764 +
14765 +static int ixp2000_flash_probe(struct device *_dev)
14766 +{
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;
14773 +       int err = -1;
14774 +       
14775 +       if (!ixp_data)
14776 +               return -ENODEV;
14777 +
14778 +       plat = ixp_data->platform_data;
14779 +       if (!plat)
14780 +               return -ENODEV;
14781 +
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));
14785 +
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);
14789 +               return -EIO;
14790 +       }
14791 +
14792 +       info = kmalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL);
14793 +       if(!info) {
14794 +               err = -ENOMEM;
14795 +               goto Error;
14796 +       }       
14797 +       memzero(info, sizeof(struct ixp2000_flash_info));
14798 +
14799 +       dev_set_drvdata(&dev->dev, info);
14800 +
14801 +       /*
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.
14804 +        */
14805 +       info->map.phys = NO_XIP;
14806 +       
14807 +       info->nr_banks = ixp_data->nr_banks;
14808 +       info->map.size = ixp_data->nr_banks * window_size;
14809 +       info->map.bankwidth = 1;
14810 +
14811 +       /*
14812 +        * map_priv_2 is used to store a ptr to to the bank_setup routine
14813 +        */
14814 +       info->map.map_priv_2 = (void __iomem *) ixp_data->bank_setup;
14815 +
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;
14821 +
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");
14827 +               err = -ENOMEM;
14828 +               goto Error;
14829 +       }
14830 +
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");
14836 +               err = -EIO;
14837 +               goto Error;
14838 +       }
14839 +
14840 +       /*
14841 +        * Setup read mode for FLASH
14842 +        */
14843 +       *IXP2000_SLOWPORT_FRM = 1;
14844 +
14845 +#if defined(__ARMEB__)
14846 +       /*
14847 +        * Enable erratum 44 workaround for NPUs with broken slowport
14848 +        */
14849 +
14850 +       errata44_workaround = ixp2000_has_broken_slowport();
14851 +       dev_info(_dev, "Erratum 44 workaround %s\n",
14852 +              erratum44_workaround ? "enabled" : "disabled");
14853 +#endif
14854 +
14855 +       info->mtd = do_map_probe(plat->map_name, &info->map);
14856 +       if (!info->mtd) {
14857 +               dev_err(_dev, "map_probe failed\n");
14858 +               err = -ENXIO;
14859 +               goto Error;
14860 +       }
14861 +       info->mtd->owner = THIS_MODULE;
14862 +
14863 +       err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
14864 +       if (err > 0) {
14865 +               err = add_mtd_partitions(info->mtd, info->partitions, err);
14866 +               if(err)
14867 +                       dev_err(_dev, "Could not parse partitions\n");
14868 +       }
14869 +
14870 +       if (err)
14871 +               goto Error;
14872 +
14873 +       return 0;
14874 +
14875 +Error:
14876 +       ixp2000_flash_remove(_dev);
14877 +       return err;
14878 +}
14879 +
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
14885 +};
14886 +
14887 +static int __init ixp2000_flash_init(void)
14888 +{
14889 +       return driver_register(&ixp2000_flash_driver);
14890 +}
14891 +
14892 +static void __exit ixp2000_flash_exit(void)
14893 +{
14894 +       driver_unregister(&ixp2000_flash_driver);
14895 +}
14896 +
14897 +module_init(ixp2000_flash_init);
14898 +module_exit(ixp2000_flash_exit);
14899 +MODULE_LICENSE("GPL");
14900 +MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
14901 +
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
14906 @@ -0,0 +1,260 @@
14907 +/*
14908 + * $Id: ixp4xx.c,v 1.6 2004/09/17 00:25:06 gleixner Exp $
14909 + *
14910 + * drivers/mtd/maps/ixp4xx.c
14911 + *
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
14915 + *
14916 + * Original Author: Intel Corporation
14917 + * Maintainer: Deepak Saxena <dsaxena@mvista.com>
14918 + *
14919 + * Copyright (C) 2002 Intel Corporation
14920 + * Copyright (C) 2003-2004 MontaVista Software, Inc.
14921 + *
14922 + */
14923 +
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>
14937 +
14938 +#include <linux/reboot.h>
14939 +
14940 +#ifndef __ARMEB__
14941 +#define        BYTE0(h)        ((h) & 0xFF)
14942 +#define        BYTE1(h)        (((h) >> 8) & 0xFF)
14943 +#else
14944 +#define        BYTE0(h)        (((h) >> 8) & 0xFF)
14945 +#define        BYTE1(h)        ((h) & 0xFF)
14946 +#endif
14947 +
14948 +static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
14949 +{
14950 +       map_word val;
14951 +       val.x[0] = *(__u16 *) (map->map_priv_1 + ofs);
14952 +       return val;
14953 +}
14954 +
14955 +/*
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().
14959 + */
14960 +static void ixp4xx_copy_from(struct map_info *map, void *to,
14961 +                            unsigned long from, ssize_t len)
14962 +{
14963 +       int i;
14964 +       u8 *dest = (u8 *) to;
14965 +       u16 *src = (u16 *) (map->map_priv_1 + from);
14966 +       u16 data;
14967 +
14968 +       for (i = 0; i < (len / 2); i++) {
14969 +               data = src[i];
14970 +               dest[i * 2] = BYTE0(data);
14971 +               dest[i * 2 + 1] = BYTE1(data);
14972 +       }
14973 +
14974 +       if (len & 1)
14975 +               dest[len - 1] = BYTE0(src[i]);
14976 +}
14977 +
14978 +/* 
14979 + * Unaligned writes are ignored, causing the 8-bit
14980 + * probe to fail and proceed to the 16-bit probe (which succeeds).
14981 + */
14982 +static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
14983 +{
14984 +       if (!(adr & 1))
14985 +              *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
14986 +}
14987 +
14988 +/* 
14989 + * Fast write16 function without the probing check above
14990 + */
14991 +static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
14992 +{
14993 +       *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
14994 +}
14995 +
14996 +struct ixp4xx_flash_info {
14997 +       struct mtd_info *mtd;
14998 +       struct map_info map;
14999 +       struct mtd_partition *partitions;
15000 +       struct resource *res;
15001 +};
15002 +
15003 +static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
15004 +
15005 +static int ixp4xx_flash_remove(struct device *_dev)
15006 +{
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);
15010 +       map_word d;
15011 +
15012 +       dev_set_drvdata(&dev->dev, NULL);
15013 +
15014 +       if(!info)
15015 +               return 0;
15016 +
15017 +       /*
15018 +        * This is required for a soft reboot to work.
15019 +        */
15020 +       d.x[0] = 0xff;
15021 +       ixp4xx_write16(&info->map, d, 0x55 * 0x2);
15022 +
15023 +       if (info->mtd) {
15024 +               del_mtd_partitions(info->mtd);
15025 +               map_destroy(info->mtd);
15026 +       }
15027 +       if (info->map.map_priv_1)
15028 +               iounmap((void *) info->map.map_priv_1);
15029 +
15030 +       if (info->partitions)
15031 +               kfree(info->partitions);
15032 +
15033 +       if (info->res) {
15034 +               release_resource(info->res);
15035 +               kfree(info->res);
15036 +       }
15037 +
15038 +       if (plat->exit)
15039 +               plat->exit();
15040 +
15041 +       /* Disable flash write */
15042 +       *IXP4XX_EXP_CS0 &= ~IXP4XX_FLASH_WRITABLE;
15043 +
15044 +       return 0;
15045 +}
15046 +
15047 +static int ixp4xx_flash_probe(struct device *_dev)
15048 +{
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;
15052 +       int err = -1;
15053 +
15054 +       if (!plat)
15055 +               return -ENODEV;
15056 +
15057 +       if (plat->init) {
15058 +               err = plat->init();
15059 +               if (err)
15060 +                       return err;
15061 +       }
15062 +
15063 +       info = kmalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL);
15064 +       if(!info) {
15065 +               err = -ENOMEM;
15066 +               goto Error;
15067 +       }       
15068 +       memzero(info, sizeof(struct ixp4xx_flash_info));
15069 +
15070 +       dev_set_drvdata(&dev->dev, info);
15071 +
15072 +       /* 
15073 +        * Enable flash write 
15074 +        * TODO: Move this out to board specific code
15075 +        */
15076 +       *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
15077 +
15078 +       /*
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.
15081 +        */
15082 +       info->map.phys = NO_XIP;
15083 +       info->map.size = dev->resource->end - dev->resource->start + 1;
15084 +
15085 +       /*
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
15088 +        * handle that.
15089 +        */
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,
15095 +
15096 +       info->res = request_mem_region(dev->resource->start, 
15097 +                       dev->resource->end - dev->resource->start + 1, 
15098 +                       "IXP4XXFlash");
15099 +       if (!info->res) {
15100 +               printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n");
15101 +               err = -ENOMEM;
15102 +               goto Error;
15103 +       }
15104 +
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");
15110 +               err = -EIO;
15111 +               goto Error;
15112 +       }
15113 +
15114 +       info->mtd = do_map_probe(plat->map_name, &info->map);
15115 +       if (!info->mtd) {
15116 +               printk(KERN_ERR "IXP4XXFlash: map_probe failed\n");
15117 +               err = -ENXIO;
15118 +               goto Error;
15119 +       }
15120 +       info->mtd->owner = THIS_MODULE;
15121 +       
15122 +       /* Use the fast version */
15123 +       info->map.write = ixp4xx_write16,
15124 +
15125 +       err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
15126 +       if (err > 0) {
15127 +               err = add_mtd_partitions(info->mtd, info->partitions, err);
15128 +               if(err)
15129 +                       printk(KERN_ERR "Could not parse partitions\n");
15130 +       }
15131 +
15132 +       if (err)
15133 +               goto Error;
15134 +
15135 +       return 0;
15136 +
15137 +Error:
15138 +       ixp4xx_flash_remove(_dev);
15139 +       return err;
15140 +}
15141 +
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,
15147 +};
15148 +
15149 +static int __init ixp4xx_flash_init(void)
15150 +{
15151 +       return driver_register(&ixp4xx_flash_driver);
15152 +}
15153 +
15154 +static void __exit ixp4xx_flash_exit(void)
15155 +{
15156 +       driver_unregister(&ixp4xx_flash_driver);
15157 +}
15158 +
15159 +
15160 +module_init(ixp4xx_flash_init);
15161 +module_exit(ixp4xx_flash_exit);
15162 +
15163 +MODULE_LICENSE("GPL");
15164 +MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems")
15165 +MODULE_AUTHOR("Deepak Saxena");
15166 +
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
15171 @@ -1,5 +1,5 @@
15172  /*
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 $
15175   *
15176   * BIOS Flash chip on Intel 440GX board.
15177   *
15178 @@ -46,7 +46,7 @@
15179  struct map_info l440gx_map = {
15180         .name = "L440GX BIOS",
15181         .size = WINDOW_SIZE,
15182 -       .buswidth = BUSWIDTH,
15183 +       .bankwidth = BUSWIDTH,
15184         .phys = WINDOW_ADDR,
15185  #if 0
15186         /* FIXME verify that this is the 
15187 @@ -73,7 +73,7 @@
15188                 return -ENODEV;
15189         }
15190  
15191 -       l440gx_map.virt = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
15192 +       l440gx_map.virt = (void __iomem *)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
15193  
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
15200 @@ -1,14 +1,13 @@
15201  /*
15202 - * Flash device on lasat 100 and 200 boards
15203 + * Flash device on Lasat 100 and 200 boards
15204   *
15205 - * Presumably (C) 2002 Brian Murphy <brian@murphy.dk> or whoever he
15206 - * works for.
15207 + * (C) 2002 Brian Murphy <brian@murphy.dk>
15208   *
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.
15212   *
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 $
15215   *
15216   */
15217  
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>
15223  
15224 -static struct mtd_info *mymtd;
15225 -
15226 -static struct map_info sp_map = {
15227 -       .name = "SP flash",
15228 -       .buswidth = 4,
15229 -};
15230 +static struct mtd_info *lasat_mtd;
15231  
15232  static struct mtd_partition partition_info[LASAT_MTD_LAST];
15233  static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
15234  
15235 -static int __init init_sp(void)
15236 +static void lasat_set_vpp(struct map_info *map, int vpp)
15237  {
15238 -       int i;
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;
15244 -
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;
15248 +       if (vpp)
15249 +           *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
15250 +       else
15251 +           *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit);
15252 +}
15253 +
15254 +static struct map_info lasat_map = {
15255 +       .name = "LASAT flash",
15256 +       .bankwidth = 4,
15257 +       .set_vpp = lasat_set_vpp
15258 +};
15259  
15260 -       simple_map_init(&sp_map);
15261 +static int __init init_lasat(void)
15262 +{
15263 +       int i;
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));
15268 +
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;
15273  
15274 -               printk(KERN_NOTICE "sp flash device: %lx at %lx\n", 
15275 -                       sp_map.size, sp_map.phys);
15276 +       simple_map_init(&lasat_map);
15277  
15278         for (i=0; i < LASAT_MTD_LAST; i++)
15279                 partition_info[i].name = lasat_mtd_partnames[i];
15280  
15281 -       mymtd = do_map_probe("cfi_probe", &sp_map);
15282 -       if (mymtd) {
15283 +       lasat_mtd = do_map_probe("cfi_probe", &lasat_map);
15284 +
15285 +       if (!lasat_mtd)
15286 +           lasat_mtd = do_map_probe("jedec_probe", &lasat_map);
15287 +
15288 +       if (lasat_mtd) {
15289                 u32 size, offset = 0;
15290  
15291 -               mymtd->owner = THIS_MODULE;
15292 +               lasat_mtd->owner = THIS_MODULE;
15293  
15294                 for (i=0; i < LASAT_MTD_LAST; i++) {
15295                         size = lasat_flash_partition_size(i);
15296 @@ -68,26 +76,26 @@
15297                         offset += size;
15298                 }
15299  
15300 -               add_mtd_partitions( mymtd, partition_info, LASAT_MTD_LAST );
15301 +               add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST );
15302                 return 0;
15303         }
15304  
15305         return -ENXIO;
15306  }
15307  
15308 -static void __exit cleanup_sp(void)
15309 +static void __exit cleanup_lasat(void)
15310  {
15311 -       if (mymtd) {
15312 -               del_mtd_partitions(mymtd);
15313 -               map_destroy(mymtd);
15314 +       if (lasat_mtd) {
15315 +               del_mtd_partitions(lasat_mtd);
15316 +               map_destroy(lasat_mtd);
15317         }
15318 -       if (sp_map.virt) {
15319 -               sp_map.virt = 0;
15320 +       if (lasat_map.virt) {
15321 +               lasat_map.virt = 0;
15322         }
15323  }
15324  
15325 -module_init(init_sp);
15326 -module_exit(cleanup_sp);
15327 +module_init(init_lasat);
15328 +module_exit(cleanup_lasat);
15329  
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
15336 @@ -1,5 +1,5 @@
15337  /*
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 $
15340   *
15341   * Map driver for the Lubbock developer platform.
15342   *
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>
15354  
15355  
15356  #define ROM_ADDR       0x00000000
15357 @@ -27,12 +28,19 @@
15358  
15359  #define WINDOW_SIZE    64*1024*1024
15360  
15361 +static void lubbock_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len)
15362 +{
15363 +       consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
15364 +}
15365 +
15366  static struct map_info lubbock_maps[2] = { {
15367         .size =         WINDOW_SIZE,
15368         .phys =         0x00000000,
15369 +       .inval_cache =  lubbock_map_inval_cache,
15370  }, {
15371         .size =         WINDOW_SIZE,
15372         .phys =         0x04000000,
15373 +       .inval_cache =  lubbock_map_inval_cache,
15374  } };
15375  
15376  static struct mtd_partition lubbock_partitions[] = {
15377 @@ -60,10 +68,10 @@
15378  
15379  static int __init init_lubbock(void)
15380  {
15381 -       int flashboot = (CONF_SWITCHES & 1);
15382 +       int flashboot = (LUB_CONF_SWITCHES & 1);
15383         int ret = 0, i;
15384  
15385 -       lubbock_maps[0].buswidth = lubbock_maps[1].buswidth = 
15386 +       lubbock_maps[0].bankwidth = lubbock_maps[1].bankwidth = 
15387                 (BOOT_DEF & 1) ? 2 : 4;
15388  
15389         /* Compensate for the nROMBT switch which swaps the flash banks */
15390 @@ -74,23 +82,28 @@
15391         lubbock_maps[flashboot].name = "Lubbock Boot ROM";
15392  
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);
15398                         if (!ret)
15399                                 ret = -ENOMEM;
15400                         continue;
15401                 }
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]);
15406  
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);
15412  
15413                 mymtds[i] = do_map_probe("cfi_probe", &lubbock_maps[i]);
15414                 
15415                 if (!mymtds[i]) {
15416                         iounmap((void *)lubbock_maps[i].virt);
15417 +                       if (lubbock_maps[i].cached)
15418 +                               iounmap(lubbock_maps[i].cached);
15419                         if (!ret)
15420                                 ret = -EIO;
15421                         continue;
15422 @@ -137,6 +150,8 @@
15423  
15424                 map_destroy(mymtds[i]);
15425                 iounmap((void *)lubbock_maps[i].virt);
15426 +               if (lubbock_maps[i].cached)
15427 +                       iounmap(lubbock_maps[i].cached);
15428  
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
15435 @@ -1,5 +1,5 @@
15436  /*
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 $
15439   *
15440   * Out-of-line map I/O functions for simple maps when CONFIG_COMPLEX_MAPPINGS
15441   * is enabled.
15442 @@ -7,87 +7,35 @@
15443  
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>
15450  
15451  #include <linux/mtd/map.h>
15452 -#include <linux/mtd/cfi.h>
15453  
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)
15456  {
15457 -       return __raw_readb(map->virt + ofs);
15458 +       return inline_map_read(map, ofs);
15459  }
15460  
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)
15463  {
15464 -       return __raw_readw(map->virt + ofs);
15465 -}
15466 -
15467 -static u32 simple_map_read32(struct map_info *map, unsigned long ofs)
15468 -{
15469 -       return __raw_readl(map->virt + ofs);
15470 -}
15471 -
15472 -static u64 simple_map_read64(struct map_info *map, unsigned long ofs)
15473 -{
15474 -#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */
15475 -       BUG();
15476 -       return 0;
15477 -#else
15478 -       return __raw_readll(map->virt + ofs);
15479 -#endif
15480 -}
15481 -
15482 -static void simple_map_write8(struct map_info *map, u8 datum, unsigned long ofs)
15483 -{
15484 -       __raw_writeb(datum, map->virt + ofs);
15485 -       mb();
15486 -}
15487 -
15488 -static void simple_map_write16(struct map_info *map, u16 datum, unsigned long ofs)
15489 -{
15490 -       __raw_writew(datum, map->virt + ofs);
15491 -       mb();
15492 -}
15493 -
15494 -static void simple_map_write32(struct map_info *map, u32 datum, unsigned long ofs)
15495 -{
15496 -       __raw_writel(datum, map->virt + ofs);
15497 -       mb();
15498 -}
15499 -
15500 -static void simple_map_write64(struct map_info *map, u64 datum, unsigned long ofs)
15501 -{
15502 -#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */
15503 -       BUG();
15504 -#else
15505 -       __raw_writell(datum, map->virt + ofs);
15506 -       mb();
15507 -#endif /* CFI_B8 */
15508 +       inline_map_write(map, datum, ofs);
15509  }
15510  
15511  static void simple_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
15512  {
15513 -       memcpy_fromio(to, (char *)map->virt + from, len);
15514 +       inline_map_copy_from(map, to, from, len);
15515  }
15516  
15517  static void simple_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
15518  {
15519 -       memcpy_toio((char *)map->virt + to, from, len);
15520 +       inline_map_copy_to(map, to, from, len);
15521  }
15522  
15523  void simple_map_init(struct map_info *map)
15524  {
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));
15534 +
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;
15539  }
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
15544 @@ -1,5 +1,5 @@
15545  /*
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 $
15548   *
15549   * Handle mapping of the flash on MBX860 boards
15550   *
15551 @@ -54,13 +54,13 @@
15552         .name = "MBX flash",
15553         .size = WINDOW_SIZE,
15554         .phys = WINDOW_ADDR,
15555 -       .buswidth = 4,
15556 +       .bankwidth = 4,
15557  };
15558  
15559  int __init init_mbx(void)
15560  {
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);
15564  
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
15571 @@ -0,0 +1,81 @@
15572 +/*
15573 + * Flash on MPC-1211
15574 + *
15575 + * $Id: mpc1211.c,v 1.4 2004/09/16 23:27:13 gleixner Exp $
15576 + *
15577 + * (C) 2002 Interface, Saito.K & Jeanne
15578 + *
15579 + * GPL'd
15580 + */
15581 +
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>
15590 +
15591 +static struct mtd_info *flash_mtd;
15592 +static struct mtd_partition *parsed_parts;
15593 +
15594 +struct map_info mpc1211_flash_map = {
15595 +       .name           = "MPC-1211 FLASH",
15596 +       .size           = 0x80000,
15597 +       .bankwidth      = 1,
15598 +};
15599 +
15600 +static struct mtd_partition mpc1211_partitions[] = {
15601 +       {
15602 +               .name   = "IPL & ETH-BOOT",
15603 +               .offset = 0x00000000,
15604 +               .size   = 0x10000,
15605 +       },
15606 +       {
15607 +               .name   = "Flash FS",
15608 +               .offset = 0x00010000,
15609 +               .size   = MTDPART_SIZ_FULL,
15610 +       }
15611 +};
15612 +
15613 +static int __init init_mpc1211_maps(void)
15614 +{
15615 +       int nr_parts;
15616 +
15617 +       mpc1211_flash_map.phys = 0;
15618 +       mpc1211_flash_map.virt = (void __iomem *)P2SEGADDR(0);
15619 +
15620 +       simple_map_init(&mpc1211_flash_map);
15621 +
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");
15626 +               return -ENXIO;
15627 +       }
15628 +       printk(KERN_NOTICE "MPC-1211: Flash at 0x%08lx\n", mpc1211_flash_map.virt & 0x1fffffff);
15629 +       flash_mtd->module = THIS_MODULE;
15630 +
15631 +       parsed_parts = mpc1211_partitions;
15632 +       nr_parts = ARRAY_SIZE(mpc1211_partitions);
15633 +
15634 +       add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
15635 +       return 0;
15636 +}
15637 +
15638 +static void __exit cleanup_mpc1211_maps(void)
15639 +{
15640 +       if (parsed_parts)
15641 +               del_mtd_partitions(flash_mtd);
15642 +       else
15643 +               del_mtd_device(flash_mtd);
15644 +       map_destroy(flash_mtd);
15645 +}
15646 +
15647 +module_init(init_mpc1211_maps);
15648 +module_exit(cleanup_mpc1211_maps);
15649 +
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
15657 @@ -3,7 +3,7 @@
15658   * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com)
15659   *     based on sc520cdp.c by Sysgo Real-Time Solutions GmbH
15660   *
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 $
15663   *
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
15666 @@ -84,7 +84,7 @@
15667  static struct map_info netsc520_map = {
15668         .name = "netsc520 Flash Bank",
15669         .size = WINDOW_SIZE,
15670 -       .buswidth = 4,
15671 +       .bankwidth = 4,
15672         .phys = WINDOW_ADDR,
15673  };
15674  
15675 @@ -95,7 +95,7 @@
15676  static int __init init_netsc520(void)
15677  {
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);
15681  
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
15688 @@ -6,7 +6,7 @@
15689   *      (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com)
15690   *      (C) Copyright 2001-2002, SnapGear (www.snapgear.com)
15691   *
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 $
15694   */
15695  
15696  /****************************************************************************/
15697 @@ -65,7 +65,7 @@
15698  static struct map_info nettel_intel_map = {
15699         .name = "SnapGear Intel",
15700         .size = 0,
15701 -       .buswidth = INTEL_BUSWIDTH,
15702 +       .bankwidth = INTEL_BUSWIDTH,
15703  };
15704  
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,
15712  };
15713  
15714  static struct mtd_partition nettel_amd_partitions[] = {
15715 @@ -273,8 +273,7 @@
15716         __asm__ ("wbinvd");
15717  
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");
15724                 return(-EIO);
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
15729 @@ -1,5 +1,5 @@
15730  /*
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 $
15733   *
15734   * Flash on Momenco Ocelot
15735   */
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,
15743  };
15744  
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,
15751  };
15752  
15753 @@ -81,7 +81,7 @@
15754         iounmap(pld);
15755  
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");
15761                 return -EIO;
15762 @@ -101,7 +101,7 @@
15763         nvram_mtd->write = ocelot_ram_write;
15764  
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");
15770                 goto fail_2;
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
15775 @@ -0,0 +1,156 @@
15776 +/*
15777 + * Mapping for Ocotea user flash
15778 + *
15779 + * Matt Porter <mporter@kernel.crashing.org>
15780 + *
15781 + * Copyright 2002-2004 MontaVista Software Inc.
15782 + *
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.
15787 + */
15788 +
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>
15801 +
15802 +static struct mtd_info *flash;
15803 +
15804 +static struct map_info ocotea_small_map = {
15805 +       .name =         "Ocotea small flash",
15806 +       .size =         OCOTEA_SMALL_FLASH_SIZE,
15807 +       .buswidth =     1,
15808 +};
15809 +
15810 +static struct map_info ocotea_large_map = {
15811 +       .name =         "Ocotea large flash",
15812 +       .size =         OCOTEA_LARGE_FLASH_SIZE,
15813 +       .buswidth =     1,
15814 +};
15815 +
15816 +static struct mtd_partition ocotea_small_partitions[] = {
15817 +       {
15818 +               .name =   "pibs",
15819 +               .offset = 0x0,
15820 +               .size =   0x100000,
15821 +       }
15822 +};
15823 +
15824 +static struct mtd_partition ocotea_large_partitions[] = {
15825 +       {
15826 +               .name =   "fs",
15827 +               .offset = 0,
15828 +               .size =   0x300000,
15829 +       },
15830 +       {
15831 +               .name =   "firmware",
15832 +               .offset = 0x300000,
15833 +               .size =   0x100000,
15834 +       }
15835 +};
15836 +
15837 +#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
15838 +
15839 +int __init init_ocotea(void)
15840 +{
15841 +       u8 fpga0_reg;
15842 +       u8 *fpga0_adr;
15843 +       unsigned long long small_flash_base, large_flash_base;
15844 +
15845 +       fpga0_adr = ioremap64(OCOTEA_FPGA_ADDR, 16);
15846 +       if (!fpga0_adr)
15847 +               return -ENOMEM;
15848 +
15849 +       fpga0_reg = readb((unsigned long)fpga0_adr);
15850 +       iounmap(fpga0_adr);
15851 +
15852 +       if (OCOTEA_BOOT_LARGE_FLASH(fpga0_reg)) {
15853 +               small_flash_base = OCOTEA_SMALL_FLASH_HIGH;
15854 +               large_flash_base = OCOTEA_LARGE_FLASH_LOW;
15855 +       }
15856 +       else {
15857 +               small_flash_base = OCOTEA_SMALL_FLASH_LOW;
15858 +               large_flash_base = OCOTEA_LARGE_FLASH_HIGH;
15859 +       }
15860 +
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);
15865 +
15866 +       if (!ocotea_small_map.virt) {
15867 +               printk("Failed to ioremap flash\n");
15868 +               return -EIO;
15869 +       }
15870 +
15871 +       simple_map_init(&ocotea_small_map);
15872 +
15873 +       flash = do_map_probe("map_rom", &ocotea_small_map);
15874 +       if (flash) {
15875 +               flash->owner = THIS_MODULE;
15876 +               add_mtd_partitions(flash, ocotea_small_partitions,
15877 +                                       NB_OF(ocotea_small_partitions));
15878 +       } else {
15879 +               printk("map probe failed for flash\n");
15880 +               return -ENXIO;
15881 +       }
15882 +
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);
15887 +
15888 +       if (!ocotea_large_map.virt) {
15889 +               printk("Failed to ioremap flash\n");
15890 +               return -EIO;
15891 +       }
15892 +
15893 +       simple_map_init(&ocotea_large_map);
15894 +
15895 +       flash = do_map_probe("cfi_probe", &ocotea_large_map);
15896 +       if (flash) {
15897 +               flash->owner = THIS_MODULE;
15898 +               add_mtd_partitions(flash, ocotea_large_partitions,
15899 +                                       NB_OF(ocotea_large_partitions));
15900 +       } else {
15901 +               printk("map probe failed for flash\n");
15902 +               return -ENXIO;
15903 +       }
15904 +
15905 +       return 0;
15906 +}
15907 +
15908 +static void __exit cleanup_ocotea(void)
15909 +{
15910 +       if (flash) {
15911 +               del_mtd_partitions(flash);
15912 +               map_destroy(flash);
15913 +       }
15914 +
15915 +       if (ocotea_small_map.virt) {
15916 +               iounmap((void *)ocotea_small_map.virt);
15917 +               ocotea_small_map.virt = 0;
15918 +       }
15919 +
15920 +       if (ocotea_large_map.virt) {
15921 +               iounmap((void *)ocotea_large_map.virt);
15922 +               ocotea_large_map.virt = 0;
15923 +       }
15924 +}
15925 +
15926 +module_init(init_ocotea);
15927 +module_exit(cleanup_ocotea);
15928 +
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
15936 @@ -1,4 +1,4 @@
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  /* ######################################################################
15940  
15941     Octagon 5066 MTD Driver. 
15942 @@ -62,32 +62,12 @@
15943  }
15944  
15945  
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)
15948  {
15949 -       __u8 ret;
15950 +       map_word ret;
15951         spin_lock(&oct5066_spin);
15952         oct5066_page(map, ofs);
15953 -       ret = readb(iomapadr + (ofs & WINDOW_MASK));
15954 -       spin_unlock(&oct5066_spin);
15955 -       return ret;
15956 -}
15957 -
15958 -static __u16 oct5066_read16(struct map_info *map, unsigned long ofs)
15959 -{
15960 -       __u16 ret;
15961 -       spin_lock(&oct5066_spin);
15962 -       oct5066_page(map, ofs);
15963 -       ret = readw(iomapadr + (ofs & WINDOW_MASK));
15964 -       spin_unlock(&oct5066_spin);
15965 -       return ret;
15966 -}
15967 -
15968 -static __u32 oct5066_read32(struct map_info *map, unsigned long ofs)
15969 -{
15970 -       __u32 ret;
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);
15976         return ret;
15977  }
15978 @@ -109,27 +89,11 @@
15979         }
15980  }
15981  
15982 -static void oct5066_write8(struct map_info *map, __u8 d, unsigned long adr)
15983 -{
15984 -       spin_lock(&oct5066_spin);
15985 -       oct5066_page(map, adr);
15986 -       writeb(d, iomapadr + (adr & WINDOW_MASK));
15987 -       spin_unlock(&oct5066_spin);
15988 -}
15989 -
15990 -static void oct5066_write16(struct map_info *map, __u16 d, unsigned long adr)
15991 -{
15992 -       spin_lock(&oct5066_spin);
15993 -       oct5066_page(map, adr);
15994 -       writew(d, iomapadr + (adr & WINDOW_MASK));
15995 -       spin_unlock(&oct5066_spin);
15996 -}
15997 -
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)
16000  {
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);
16006  }
16007  
16008 @@ -155,14 +119,10 @@
16009                 .name = "Octagon 5066 Socket",
16010                 .phys = NO_XIP,
16011                 .size = 512 * 1024,
16012 -               .buswidth = 1,
16013 -               .read8 = oct5066_read8,
16014 -               .read16 = oct5066_read16,
16015 -               .read32 = oct5066_read32,
16016 +               .bankwidth = 1,
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,
16024                 .map_priv_1 = 1<<6
16025         },
16026 @@ -170,14 +130,10 @@
16027                 .name = "Octagon 5066 Internal Flash",
16028                 .phys = NO_XIP,
16029                 .size = 2 * 1024 * 1024,
16030 -               .buswidth = 1,
16031 -               .read8 = oct5066_read8,
16032 -               .read16 = oct5066_read16,
16033 -               .read32 = oct5066_read32,
16034 +               .bankwidth = 1,
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,
16042                 .map_priv_1 = 2<<6
16043         }
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
16048 @@ -0,0 +1,137 @@
16049 +/*
16050 + * NOR Flash memory access on TI Toto board
16051 + *
16052 + * jzhang@ti.com (C) 2003 Texas Instruments.
16053 + *
16054 + *  (C) 2002 MontVista Software, Inc.
16055 + *
16056 + * $Id: omap-toto-flash.c,v 1.3 2004/09/16 23:27:13 gleixner Exp $
16057 + */
16058 +
16059 +#include <linux/config.h>
16060 +#include <linux/module.h>
16061 +#include <linux/types.h>
16062 +#include <linux/kernel.h>
16063 +
16064 +#include <linux/errno.h>
16065 +#include <linux/init.h>
16066 +
16067 +#include <linux/mtd/mtd.h>
16068 +#include <linux/mtd/map.h>
16069 +#include <linux/mtd/partitions.h>
16070 +
16071 +#include <asm/hardware.h>
16072 +#include <asm/io.h>
16073 +
16074 +
16075 +#ifndef CONFIG_ARCH_OMAP
16076 +#error This is for OMAP architecture only
16077 +#endif
16078 +
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
16082 +
16083 +static struct map_info omap_toto_map_flash = {
16084 +       .name =         "OMAP Toto flash",
16085 +       .bankwidth =    2,
16086 +       .virt =         (void __iomem *)OMAP_TOTO_FLASH_BASE,
16087 +};
16088 +
16089
16090 +static struct mtd_partition toto_flash_partitions[] = {
16091 +       {
16092 +               .name =         "BootLoader",
16093 +               .size =         0x00040000,     /* hopefully u-boot will stay 128k + 128*/
16094 +               .offset =       0,
16095 +               .mask_flags =   MTD_WRITEABLE,  /* force read-only */
16096 +       }, {
16097 +               .name =         "ReservedSpace",
16098 +               .size =         0x00030000,
16099 +               .offset =       MTDPART_OFS_APPEND,
16100 +               //mask_flags:   MTD_WRITEABLE,  /* force read-only */
16101 +       }, {
16102 +               .name =         "EnvArea",      /* bottom 64KiB for env vars */
16103 +               .size =         MTDPART_SIZ_FULL,
16104 +               .offset =       MTDPART_OFS_APPEND,
16105 +       } 
16106 +};
16107 +
16108 +static struct mtd_partition *parsed_parts;
16109 +
16110 +static struct mtd_info *flash_mtd;
16111
16112 +static int __init init_flash (void)   
16113 +{
16114 +
16115 +       struct mtd_partition *parts;
16116 +       int nb_parts = 0;
16117 +       int parsed_nr_parts = 0;
16118 +       const char *part_type;
16119
16120 +       /*
16121 +        * Static partition definition selection
16122 +        */
16123 +       part_type = "static";
16124 +
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);
16129 +
16130 +       simple_map_init(&omap_toto_map_flash);
16131 +       /*
16132 +        * Now let's probe for the actual flash.  Do it here since
16133 +        * specific machine settings might have been set above.
16134 +        */
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);
16138 +       if (!flash_mtd)
16139 +               return -ENXIO;
16140
16141 +       if (parsed_nr_parts > 0) {
16142 +               parts = parsed_parts;
16143 +               nb_parts = parsed_nr_parts;
16144 +       }
16145 +
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)){
16150 +            return -ENXIO;
16151 +        }
16152 +       } else {
16153 +               printk(KERN_NOTICE "Using %s partition definition\n",
16154 +                       part_type);
16155 +               return add_mtd_partitions(flash_mtd, parts, nb_parts);
16156 +       }
16157 +       return 0;
16158 +}
16159
16160 +int __init omap_toto_mtd_init(void)  
16161 +{
16162 +       int status;
16163 +
16164 +       if (status = init_flash()) {
16165 +               printk(KERN_ERR "OMAP Toto Flash: unable to init map for toto flash\n");
16166 +       }
16167 +    return status;
16168 +}
16169 +
16170 +static void  __exit omap_toto_mtd_cleanup(void)  
16171 +{
16172 +       if (flash_mtd) {
16173 +               del_mtd_partitions(flash_mtd);
16174 +               map_destroy(flash_mtd);
16175 +               if (parsed_parts)
16176 +                       kfree(parsed_parts);
16177 +       }
16178 +}
16179 +
16180 +module_init(omap_toto_mtd_init);
16181 +module_exit(omap_toto_mtd_cleanup);
16182 +
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
16190 @@ -0,0 +1,204 @@
16191 +/*
16192 + * Flash memory access on Alchemy Pb1550 board
16193 + * 
16194 + * $Id: pb1550-flash.c,v 1.5 2004/09/16 23:27:13 gleixner Exp $
16195 + *
16196 + * (C) 2004 Embedded Edge, LLC, based on pb1550-flash.c:
16197 + * (C) 2003 Pete Popov <ppopov@pacbell.net>
16198 + * 
16199 + */
16200 +
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>
16206 +
16207 +#include <linux/mtd/mtd.h>
16208 +#include <linux/mtd/map.h>
16209 +#include <linux/mtd/partitions.h>
16210 +
16211 +#include <asm/io.h>
16212 +#include <asm/au1000.h>
16213 +#include <asm/pb1550.h>
16214 +
16215 +#ifdef         DEBUG_RW
16216 +#define        DBG(x...)       printk(x)
16217 +#else
16218 +#define        DBG(x...)       
16219 +#endif
16220 +
16221 +static unsigned long window_addr;
16222 +static unsigned long window_size;
16223 +
16224 +
16225 +static struct map_info pb1550_map = {
16226 +       .name = "Pb1550 flash",
16227 +};
16228 +
16229 +static unsigned char flash_bankwidth = 4;
16230 +
16231 +/* 
16232 + * Support only 64MB NOR Flash parts
16233 + */
16234 +
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
16238 + * partition.
16239 + */
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
16244 +        */
16245 +        {
16246 +                .name = "User FS",
16247 +                .size =   (0x1FC00000 - 0x18000000),
16248 +                .offset = 0x0000000
16249 +        },{
16250 +                .name = "yamon",
16251 +                .size = 0x0100000,
16252 +               .offset = MTDPART_OFS_APPEND,
16253 +                .mask_flags = MTD_WRITEABLE
16254 +        },{
16255 +                .name = "raw kernel",
16256 +               .size = (0x300000 - 0x40000), /* last 256KB is yamon env */
16257 +               .offset = MTDPART_OFS_APPEND,
16258 +        }
16259 +};
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
16264 +        */
16265 +        {
16266 +                .name = "User FS",
16267 +                .size =   0x03c00000,
16268 +                .offset = 0x0000000
16269 +        },{
16270 +                .name = "yamon",
16271 +                .size = 0x0100000,
16272 +               .offset = MTDPART_OFS_APPEND,
16273 +                .mask_flags = MTD_WRITEABLE
16274 +        },{
16275 +                .name = "raw kernel",
16276 +               .size = (0x300000-0x40000), /* last 256KB is yamon env */
16277 +               .offset = MTDPART_OFS_APPEND,
16278 +        }
16279 +};
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
16284 +        */
16285 +        {
16286 +                .name = "User FS",
16287 +                .size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */
16288 +                .offset = 0x0000000
16289 +        },{
16290 +                .name = "raw kernel",
16291 +               .size = MTDPART_SIZ_FULL,
16292 +               .offset = MTDPART_OFS_APPEND,
16293 +        }
16294 +};
16295 +#else
16296 +#error MTD_PB1550 define combo error /* should never happen */
16297 +#endif
16298 +
16299 +#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
16300 +
16301 +static struct mtd_info *mymtd;
16302 +
16303 +/*
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.
16308 + */
16309 +int setup_flash_params(void)
16310 +{
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);
16315 +
16316 +       switch (boot_swapboot) {
16317 +               case 0: /* 512Mbit devices, both enabled */
16318 +               case 1: 
16319 +               case 8:
16320 +               case 9: 
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; 
16330 +#endif
16331 +                       break;
16332 +               case 0xC:
16333 +               case 0xD:
16334 +               case 0xE:
16335 +               case 0xF: 
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; 
16340 +               default:
16341 +                       printk("Pb1550 MTD: unsupported boot:swap setting\n");
16342 +                       return 1;
16343 +       }
16344 +       return 0;
16345 +}
16346 +
16347 +int __init pb1550_mtd_init(void)
16348 +{
16349 +       struct mtd_partition *parts;
16350 +       int nb_parts = 0;
16351 +       
16352 +       /* Default flash bankwidth */
16353 +       pb1550_map.bankwidth = flash_bankwidth;
16354 +
16355 +       if (setup_flash_params()) 
16356 +               return -ENXIO;
16357 +
16358 +       /*
16359 +        * Static partition definition selection
16360 +        */
16361 +       parts = pb1550_partitions;
16362 +       nb_parts = NB_OF(pb1550_partitions);
16363 +       pb1550_map.size = window_size;
16364 +
16365 +       /*
16366 +        * Now let's probe for the actual flash.  Do it here since
16367 +        * specific machine settings might have been set above.
16368 +        */
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;
16376 +
16377 +       add_mtd_partitions(mymtd, parts, nb_parts);
16378 +       return 0;
16379 +}
16380 +
16381 +static void __exit pb1550_mtd_cleanup(void)
16382 +{
16383 +       if (mymtd) {
16384 +               del_mtd_partitions(mymtd);
16385 +               map_destroy(mymtd);
16386 +       }
16387 +}
16388 +
16389 +module_init(pb1550_mtd_init);
16390 +module_exit(pb1550_mtd_cleanup);
16391 +
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
16399 @@ -3,14 +3,14 @@
16400   * 
16401   * (C) 2001 Pete Popov <ppopov@mvista.com>
16402   * 
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 $
16405   */
16406  
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>
16413  
16414  #include <linux/mtd/mtd.h>
16415  #include <linux/mtd/map.h>
16416 @@ -26,102 +26,87 @@
16417  #endif
16418  
16419  #ifdef CONFIG_MIPS_PB1000
16420 +
16421  #define WINDOW_ADDR 0x1F800000
16422  #define WINDOW_SIZE 0x800000
16423 -#endif
16424 -
16425 -
16426 -static struct map_info pb1xxx_map = {
16427 -       .name = "Pb1xxx flash",
16428 -};
16429  
16430 -
16431 -#ifdef CONFIG_MIPS_PB1000
16432 -
16433 -static unsigned long flash_size = 0x00800000;
16434 -static unsigned char flash_buswidth = 4;
16435  static struct mtd_partition pb1xxx_partitions[] = {
16436          {
16437 -                .name = "yamon env",
16438 -                .size = 0x00020000,
16439 -                .offset = 0,
16440 -                .mask_flags = MTD_WRITEABLE
16441 -        },{
16442 -                .name = "User FS",
16443 -                .size = 0x003e0000,
16444 -                .offset = 0x20000,
16445 -        },{
16446 -                .name = "boot code",
16447 -                .size = 0x100000,
16448 -                .offset = 0x400000,
16449 -                .mask_flags = MTD_WRITEABLE
16450 -        },{
16451 -                .name = "raw/kernel",
16452 -                .size = 0x300000,
16453 -                .offset = 0x500000
16454 -        }
16455 +                .name         =  "yamon env",
16456 +                .size         =   0x00020000,
16457 +                .offset       =   0,
16458 +                .mask_flags   =   MTD_WRITEABLE},
16459 +       {
16460 +                .name         =   "User FS",
16461 +                .size         =   0x003e0000,
16462 +                .offset       =   0x20000,},
16463 +       {
16464 +                .name         =   "boot code",
16465 +                .size         =   0x100000,
16466 +                .offset       =   0x400000,
16467 +                .mask_flags   =   MTD_WRITEABLE},
16468 +       {
16469 +                .name         =   "raw/kernel",
16470 +                .size         =   0x300000,
16471 +                .offset       =   0x500000}
16472  };
16473  
16474  #elif defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100)
16475  
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
16482   * partition.
16483   */
16484 -static unsigned long flash_size = 0x04000000;
16485  #define WINDOW_ADDR 0x1C000000
16486  #define WINDOW_SIZE 0x4000000
16487  static struct mtd_partition pb1xxx_partitions[] = {
16488          {
16489 -                .name = "User FS",
16490 -                .size =   0x3c00000,
16491 -                .offset = 0x0000000
16492 -        },{
16493 -                .name = "yamon",
16494 -                .size = 0x0100000,
16495 -                .offset = 0x3c00000,
16496 -                .mask_flags = MTD_WRITEABLE
16497 -        },{
16498 -                .name = "raw kernel",
16499 -                .size = 0x02c0000,
16500 -                .offset = 0x3d00000
16501 +                .name         =   "User FS",
16502 +                .size         =   0x3c00000,
16503 +                .offset       =   0x0000000
16504 +        },{
16505 +                .name         =   "yamon",
16506 +                .size         =   0x0100000,
16507 +                .offset       =   0x3c00000,
16508 +                .mask_flags   =   MTD_WRITEABLE
16509 +        },{
16510 +                .name         =   "raw kernel",
16511 +                .size         =   0x02c0000,
16512 +                .offset       =   0x3d00000
16513          }
16514  };
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[] = {
16520          {
16521 -                .name = "User FS",
16522 -                .size =   0x1c00000,
16523 -                .offset = 0x0000000
16524 -        },{
16525 -                .name = "yamon",
16526 -                .size = 0x0100000,
16527 -                .offset = 0x1c00000,
16528 -                .mask_flags = MTD_WRITEABLE
16529 -        },{
16530 -                .name = "raw kernel",
16531 -                .size = 0x02c0000,
16532 -                .offset = 0x1d00000
16533 +                .name         =   "User FS",
16534 +                .size         =   0x1c00000,
16535 +                .offset       =   0x0000000
16536 +        },{
16537 +                .name         =   "yamon",
16538 +                .size         =   0x0100000,
16539 +                .offset       =   0x1c00000,
16540 +                .mask_flags   =   MTD_WRITEABLE
16541 +        },{
16542 +                .name         =   "raw kernel",
16543 +                .size         =   0x02c0000,
16544 +                .offset       =   0x1d00000
16545          }
16546  };
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[] = {
16552          {
16553 -                .name = "User FS",
16554 -                .size =   0x1e00000,
16555 -                .offset = 0x0000000
16556 -        },{
16557 -                .name = "raw kernel",
16558 -                .size = 0x0200000,
16559 -                .offset = 0x1e00000,
16560 +                .name         =   "User FS",
16561 +                .size         =    0x1e00000,
16562 +                .offset       =    0x0000000
16563 +        },{
16564 +                .name         =    "raw kernel",
16565 +                .size         =    0x0200000,
16566 +                .offset       =    0x1e00000,
16567          }
16568  };
16569  #else
16570 @@ -131,8 +116,20 @@
16571  #error Unsupported board
16572  #endif
16573  
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
16581 +
16582 +static struct map_info pb1xxx_mtd_map = {
16583 +       .name           = NAME,
16584 +       .size           = SIZE,
16585 +       .bankwidth      = BUSWIDTH,
16586 +       .phys           = PADDR,
16587 +};
16588 +
16589 +static struct mtd_info *pb1xxx_mtd;
16590  
16591  int __init pb1xxx_mtd_init(void)
16592  {
16593 @@ -140,49 +137,38 @@
16594         int nb_parts = 0;
16595         char *part_type;
16596         
16597 -       /* Default flash buswidth */
16598 -       pb1xxx_map.buswidth = flash_buswidth;
16599 -
16600         /*
16601          * Static partition definition selection
16602          */
16603         part_type = "static";
16604         parts = pb1xxx_partitions;
16605         nb_parts = ARRAY_SIZE(pb1xxx_partitions);
16606 -       pb1xxx_map.size = flash_size;
16607  
16608         /*
16609          * Now let's probe for the actual flash.  Do it here since
16610          * specific machine settings might have been set above.
16611          */
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);
16616 -
16617 -       simple_map_init(&pb1xxx_map);
16618 -
16619 -       mymtd = do_map_probe("cfi_probe", &pb1xxx_map);
16620 -       if (!mymtd) {
16621 -               iounmap(pb1xxx_map.virt);
16622 -               return -ENXIO;
16623 -       }
16624 -       mymtd->owner = THIS_MODULE;
16625 +                       BUSWIDTH*8);
16626 +       pb1xxx_mtd_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE);
16627 +
16628 +       simple_map_init(&pb1xxx_mtd_map);
16629 +
16630 +       pb1xxx_mtd = do_map_probe("cfi_probe", &pb1xxx_mtd_map);
16631 +       if (!pb1xxx_mtd) return -ENXIO;
16632 +       pb1xxx_mtd->owner = THIS_MODULE;
16633  
16634 -       add_mtd_partitions(mymtd, parts, nb_parts);
16635 +       add_mtd_partitions(pb1xxx_mtd, parts, nb_parts);
16636         return 0;
16637  }
16638  
16639  static void __exit pb1xxx_mtd_cleanup(void)
16640  {
16641 -       if (mymtd) {
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);
16650         }
16651 -       if (pb1xxx_map.virt)
16652 -               iounmap(pb1xxx_map.virt);
16653  }
16654  
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
16660 @@ -7,7 +7,7 @@
16661   * it under the terms of the GNU General Public License version 2 as
16662   * published by the Free Software Foundation.
16663   *
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 $
16666   * 
16667   * Generic PCI memory map driver.  We support the following boards:
16668   *  - Intel IQ80310 ATU.
16669 @@ -39,6 +39,74 @@
16670         struct pci_dev *dev;
16671  };     
16672  
16673 +static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs)
16674 +{
16675 +       struct map_pci_info *map = (struct map_pci_info *)_map;
16676 +       map_word val;
16677 +       val.x[0]= readb(map->base + map->translate(map, ofs));
16678 +//     printk("read8 : %08lx => %02x\n", ofs, val.x[0]);
16679 +       return val;
16680 +}
16681 +
16682 +#if 0
16683 +static map_word mtd_pci_read16(struct map_info *_map, unsigned long ofs)
16684 +{
16685 +       struct map_pci_info *map = (struct map_pci_info *)_map;
16686 +       map_word val;
16687 +       val.x[0] = readw(map->base + map->translate(map, ofs));
16688 +//     printk("read16: %08lx => %04x\n", ofs, val.x[0]);
16689 +       return val;
16690 +}
16691 +#endif
16692 +static map_word mtd_pci_read32(struct map_info *_map, unsigned long ofs)
16693 +{
16694 +       struct map_pci_info *map = (struct map_pci_info *)_map;
16695 +       map_word val;
16696 +       val.x[0] = readl(map->base + map->translate(map, ofs));
16697 +//     printk("read32: %08lx => %08x\n", ofs, val.x[0]);
16698 +       return val;
16699 +}
16700 +
16701 +static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
16702 +{
16703 +       struct map_pci_info *map = (struct map_pci_info *)_map;
16704 +       memcpy_fromio(to, map->base + map->translate(map, from), len);
16705 +}
16706 +
16707 +static void mtd_pci_write8(struct map_info *_map, map_word val, unsigned long ofs)
16708 +{
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));
16712 +}
16713 +
16714 +#if 0
16715 +static void mtd_pci_write16(struct map_info *_map, map_word val, unsigned long ofs)
16716 +{
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));
16720 +}
16721 +#endif
16722 +static void mtd_pci_write32(struct map_info *_map, map_word val, unsigned long ofs)
16723 +{
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));
16727 +}
16728 +
16729 +static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
16730 +{
16731 +       struct map_pci_info *map = (struct map_pci_info *)_map;
16732 +       memcpy_toio(map->base + map->translate(map, to), from, len);
16733 +}
16734 +
16735 +static struct map_info mtd_pci_map = {
16736 +       .phys =         NO_XIP,
16737 +       .copy_from =    mtd_pci_copyfrom,
16738 +       .copy_to =      mtd_pci_copyto,
16739 +};
16740 +
16741  /*
16742   * Intel IOP80310 Flash driver
16743   */
16744 @@ -48,7 +116,10 @@
16745  {
16746         u32 win_base;
16747  
16748 -       map->map.buswidth = 1;
16749 +       map->map.bankwidth = 1;
16750 +       map->map.read = mtd_pci_read8,
16751 +       map->map.write = mtd_pci_write8,
16752 +
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 @@
16757         if (!len || !base)
16758                 return -ENXIO;
16759  
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);
16766  
16767 @@ -215,75 +288,6 @@
16768   * Generic code follows.
16769   */
16770  
16771 -static u8 mtd_pci_read8(struct map_info *_map, unsigned long ofs)
16772 -{
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);
16776 -       return val;
16777 -}
16778 -
16779 -static u16 mtd_pci_read16(struct map_info *_map, unsigned long ofs)
16780 -{
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);
16784 -       return val;
16785 -}
16786 -
16787 -static u32 mtd_pci_read32(struct map_info *_map, unsigned long ofs)
16788 -{
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);
16792 -       return val;
16793 -}
16794 -
16795 -static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
16796 -{
16797 -       struct map_pci_info *map = (struct map_pci_info *)_map;
16798 -       memcpy_fromio(to, map->base + map->translate(map, from), len);
16799 -}
16800 -
16801 -static void mtd_pci_write8(struct map_info *_map, u8 val, unsigned long ofs)
16802 -{
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));
16806 -}
16807 -
16808 -static void mtd_pci_write16(struct map_info *_map, u16 val, unsigned long ofs)
16809 -{
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));
16813 -}
16814 -
16815 -static void mtd_pci_write32(struct map_info *_map, u32 val, unsigned long ofs)
16816 -{
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));
16820 -}
16821 -
16822 -static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
16823 -{
16824 -       struct map_pci_info *map = (struct map_pci_info *)_map;
16825 -       memcpy_toio(map->base + map->translate(map, to), from, len);
16826 -}
16827 -
16828 -static struct map_info mtd_pci_map = {
16829 -       .phys =         NO_XIP,
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,
16838 -};
16839 -
16840  static int __devinit
16841  mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
16842  {
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
16847 @@ -1,5 +1,5 @@
16848  /*
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 $
16851   *
16852   * pcmciamtd.c - MTD driver for PCMCIA flash memory cards
16853   *
16854 @@ -49,7 +49,7 @@
16855  
16856  
16857  #define DRIVER_DESC    "PCMCIA Flash memory card driver"
16858 -#define DRIVER_VERSION "$Revision: 1.48 $"
16859 +#define DRIVER_VERSION "$Revision: 1.51 $"
16860  
16861  /* Size of the PCMCIA address space: 26 bits = 64 MB */
16862  #define MAX_PCMCIA_ADDR        0x4000000
16863 @@ -73,7 +73,7 @@
16864  /* Module parameters */
16865  
16866  /* 2 = do 16-bit transfers, 1 = do 8-bit transfers */
16867 -static int buswidth = 2;
16868 +static int bankwidth = 2;
16869  
16870  /* Speed of memory accesses, in ns */
16871  static int mem_speed;
16872 @@ -93,8 +93,8 @@
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 @@
16884  }
16885  
16886  
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)
16889  {
16890         caddr_t addr;
16891 -       u8 d;
16892 +       map_word d = {{0}};
16893  
16894         addr = remap_window(map, ofs);
16895         if(!addr)
16896 -               return 0;
16897 +               return d;
16898  
16899 -       d = readb(addr);
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]);
16903         return d;
16904  }
16905  
16906  
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)
16909  {
16910         caddr_t addr;
16911 -       u16 d;
16912 +       map_word d = {{0}};
16913  
16914         addr = remap_window(map, ofs);
16915         if(!addr)
16916 -               return 0;
16917 +               return d;
16918  
16919 -       d = readw(addr);
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]);
16923         return d;
16924  }
16925  
16926 @@ -191,26 +191,26 @@
16927  }
16928  
16929  
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)
16932  {
16933         caddr_t addr = remap_window(map, adr);
16934  
16935         if(!addr)
16936                 return;
16937  
16938 -       DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02x", adr, addr, d);
16939 -       writeb(d, addr);
16940 +       DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02x", adr, addr, d.x[0]);
16941 +       writeb(d.x[0], addr);
16942  }
16943  
16944  
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)
16947  {
16948         caddr_t addr = remap_window(map, adr);
16949         if(!addr)
16950                 return;
16951  
16952 -       DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04x", adr, addr, d);
16953 -       writew(d, addr);
16954 +       DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04x", adr, addr, d.x[0]);
16955 +       writew(d.x[0], addr);
16956  }
16957  
16958  
16959 @@ -244,30 +244,30 @@
16960  
16961  #define DEV_REMOVED(x)  (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))
16962  
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)
16965  {
16966         caddr_t win_base = (caddr_t)map->map_priv_2;
16967 -       u8 d;
16968 +       map_word d = {{0}};
16969  
16970         if(DEV_REMOVED(map))
16971 -               return 0;
16972 +               return d;
16973  
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]);
16978         return d;
16979  }
16980  
16981  
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)
16984  {
16985         caddr_t win_base = (caddr_t)map->map_priv_2;
16986 -       u16 d;
16987 +       map_word d = {{0}};
16988  
16989         if(DEV_REMOVED(map))
16990 -               return 0;
16991 +               return d;
16992  
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]);
16997         return d;
16998  }
16999  
17000 @@ -439,9 +439,9 @@
17001                 case CISTPL_DEVICE_GEO: {
17002                         cistpl_device_geo_t *t = &parse.device_geo;
17003                         int i;
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;
17015  
17016 -       if(!dev->pcmcia_map.buswidth)
17017 -               dev->pcmcia_map.buswidth = 2;
17018 +       if(!dev->pcmcia_map.bankwidth)
17019 +               dev->pcmcia_map.bankwidth = 2;
17020  
17021         if(force_size) {
17022                 dev->pcmcia_map.size = force_size << 20;
17023                 DEBUG(2, "size forced to %dM", force_size);
17024         }
17025  
17026 -       if(buswidth) {
17027 -               dev->pcmcia_map.buswidth = buswidth;
17028 -               DEBUG(2, "buswidth forced to %d", buswidth);
17029 +       if(bankwidth) {
17030 +               dev->pcmcia_map.bankwidth = bankwidth;
17031 +               DEBUG(2, "bankwidth forced to %d", bankwidth);
17032         }               
17033  
17034         dev->pcmcia_map.name = dev->mtd_name;
17035 @@ -480,7 +480,7 @@
17036         }
17037  
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);
17041  }
17042  
17043  
17044 @@ -522,12 +522,15 @@
17045         card_settings(dev, link, &new_name);
17046  
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;
17057 +       } else {
17058 +               dev->pcmcia_map.read = pcmcia_read16_remap;
17059 +               dev->pcmcia_map.write = pcmcia_write16_remap;
17060 +       }
17061         if(setvpp == 1)
17062                 dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;
17063  
17064 @@ -536,7 +539,7 @@
17065            whole card - otherwise we try smaller windows until we succeed */
17066  
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;
17070         req.Base = 0;
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;
17082 +               } else {
17083 +                       dev->pcmcia_map.read = pcmcia_read16;
17084 +                       dev->pcmcia_map.write = pcmcia_write16;
17085 +               }
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;
17090         }
17091  
17092 @@ -828,9 +834,9 @@
17093  {
17094         info(DRIVER_DESC " " DRIVER_VERSION);
17095  
17096 -       if(buswidth && buswidth != 1 && buswidth != 2) {
17097 -               info("bad buswidth (%d), using default", buswidth);
17098 -               buswidth = 2;
17099 +       if(bankwidth && bankwidth != 1 && bankwidth != 2) {
17100 +               info("bad bankwidth (%d), using default", bankwidth);
17101 +               bankwidth = 2;
17102         }
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
17109 @@ -1,7 +1,12 @@
17110  /*
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 $
17113   *
17114   * Normal mappings of chips in physical memory
17115 + *
17116 + * Copyright (C) 2003 MontaVista Software Inc.
17117 + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
17118 + *
17119 + * 031022 - [jsun] add run-time configure and partition setup
17120   */
17121  
17122  #include <linux/module.h>
17123 @@ -15,62 +20,38 @@
17124  #include <linux/config.h>
17125  #include <linux/mtd/partitions.h>
17126  
17127 -#define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START
17128 -#define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN
17129 -#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH
17130 -
17131  static struct mtd_info *mymtd;
17132  
17133 -
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,
17143  };
17144  
17145  #ifdef CONFIG_MTD_PARTITIONS
17146  static struct mtd_partition *mtd_parts;
17147  static int                   mtd_parts_nb;
17148  
17149 -static struct mtd_partition physmap_partitions[] = {
17150 -#if 0
17151 -/* Put your own partition definitions here */
17152 -       {
17153 -               .name =         "bootROM",
17154 -               .size =         0x80000,
17155 -               .offset =       0,
17156 -               .mask_flags =   MTD_WRITEABLE,  /* force read-only */
17157 -       }, {
17158 -               .name =         "zImage",
17159 -               .size =         0x100000,
17160 -               .offset =       MTDPART_OFS_APPEND,
17161 -               .mask_flags =   MTD_WRITEABLE,  /* force read-only */
17162 -       }, {
17163 -               .name =         "ramdisk.gz",
17164 -               .size =         0x300000,
17165 -               .offset =       MTDPART_OFS_APPEND,
17166 -               .mask_flags =   MTD_WRITEABLE,  /* force read-only */
17167 -       }, {
17168 -               .name =         "User FS",
17169 -               .size =         MTDPART_SIZ_FULL,
17170 -               .offset =       MTDPART_OFS_APPEND,
17171 -       }
17172 -#endif
17173 -};
17174 +static int num_physmap_partitions;
17175 +static struct mtd_partition *physmap_partitions;
17176  
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};
17180  
17181 +void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
17182 +{
17183 +       physmap_partitions=parts;
17184 +       num_physmap_partitions=num_parts;
17185 +}
17186  #endif /* CONFIG_MTD_PARTITIONS */
17187  
17188 -int __init init_physmap(void)
17189 +static int __init init_physmap(void)
17190  {
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 };
17193         const char **type;
17194  
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);
17199  
17200         if (!physmap_map.virt) {
17201                 printk("Failed to ioremap\n");
17202 @@ -79,7 +60,7 @@
17203  
17204         simple_map_init(&physmap_map);
17205  
17206 -       mymtd = 0;
17207 +       mymtd = NULL;
17208         type = rom_probe_types;
17209         for(; !mymtd && *type; type++) {
17210                 mymtd = do_map_probe(*type, &physmap_map);
17211 @@ -97,11 +78,11 @@
17212                         return 0;
17213                 }
17214  
17215 -               if (NUM_PARTITIONS != 0) 
17216 +               if (num_physmap_partitions != 0) 
17217                 {
17218                         printk(KERN_NOTICE 
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);
17222                         return 0;
17223                 }
17224  
17225 @@ -121,7 +102,7 @@
17226         if (mtd_parts_nb) {
17227                 del_mtd_partitions(mymtd);
17228                 kfree(mtd_parts);
17229 -       } else if (NUM_PARTITIONS) {
17230 +       } else if (num_physmap_partitions) {
17231                 del_mtd_partitions(mymtd);
17232         } else {
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
17238 @@ -5,7 +5,7 @@
17239   *
17240   * This code is GPL
17241   *
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 $
17244   */
17245  
17246  #include <linux/module.h>
17247 @@ -29,9 +29,9 @@
17248  struct map_info pnc_map = {
17249         .name = "PNC-2000",
17250         .size = WINDOW_SIZE,
17251 -       .buswidth = 4,
17252 +       .bankwidth = 4,
17253         .phys = 0xFFFFFFFF,
17254 -       .virt = WINDOW_ADDR,
17255 +       .virt = (void __iomem *)WINDOW_ADDR,
17256  };
17257  
17258  
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
17263 @@ -1,14 +1,13 @@
17264  /*
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 $
17267   *
17268   * drivers/mtd/maps/redwood.c
17269   *
17270   * FLASH map for the IBM Redwood 4/5/6 boards.
17271   *
17272 + * Author: MontaVista Software, Inc. <source@mvista.com>
17273   *
17274 - * Author: Armin Kuster <akuster@mvista.com>
17275 - *
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
17280   * or implied.
17281 @@ -89,7 +88,7 @@
17282  
17283  static struct mtd_partition redwood_flash_partitions[] = {
17284         {
17285 -               .name = "Redwood kernel",
17286 +               .name = "Redwood filesystem",
17287                 .offset = RW_PART0_OF,
17288                 .size = RW_PART0_SZ
17289         },
17290 @@ -100,7 +99,7 @@
17291                 .mask_flags = MTD_WRITEABLE     /* force read-only */
17292         },
17293         {
17294 -               .name = "Redwood filesystem",
17295 +               .name = "Redwood kernel",
17296                 .offset = RW_PART2_OF,
17297                 .size = RW_PART2_SZ
17298         },
17299 @@ -117,7 +116,7 @@
17300  struct map_info redwood_flash_map = {
17301         .name = "IBM Redwood",
17302         .size = WINDOW_SIZE,
17303 -       .buswidth = 2,
17304 +       .bankwidth = 2,
17305         .phys = WINDOW_ADDR,
17306  };
17307  
17308 @@ -133,7 +132,7 @@
17309                         WINDOW_SIZE, WINDOW_ADDR);
17310  
17311         redwood_flash_map.virt =
17312 -               (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
17313 +               (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE);
17314  
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);
17319  
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
17328 @@ -1,5 +1,5 @@
17329  /*
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 $
17332   *
17333   * Handle mapping of the flash on the RPX Lite and CLLF boards
17334   */
17335 @@ -21,14 +21,14 @@
17336  static struct map_info rpxlite_map = {
17337         .name = "RPX",
17338         .size = WINDOW_SIZE,
17339 -       .buswidth = 4,
17340 +       .bankwidth = 4,
17341         .phys = WINDOW_ADDR,
17342  };
17343  
17344  int __init init_rpxlite(void)
17345  {
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);
17349  
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
17356 @@ -3,7 +3,7 @@
17357   * 
17358   * (C) 2000 Nicolas Pitre <nico@cam.org>
17359   * 
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 $
17362   */
17363  
17364  #include <linux/config.h>
17365 @@ -496,6 +496,32 @@
17366  };
17367  #endif
17368  
17369 +#ifdef CONFIG_SA1100_JORNADA56X
17370 +static struct mtd_partition jornada56x_partitions[] = {
17371 +       {
17372 +               .name           = "bootldr",
17373 +               .size           = 0x00040000,
17374 +               .offset         = 0,
17375 +               .mask_flags     = MTD_WRITEABLE,
17376 +       }, {
17377 +               .name           = "rootfs",
17378 +               .size           = MTDPART_SIZ_FULL,
17379 +               .offset         = MTDPART_OFS_APPEND,
17380 +       }
17381 +};
17382 +
17383 +static void jornada56x_set_vpp(struct map_info *map, int vpp)
17384 +{
17385 +       if (vpp)
17386 +               GPSR = GPIO_GPIO26;
17387 +       else
17388 +               GPCR = GPIO_GPIO26;
17389 +       GPDR |= GPIO_GPIO26;
17390 +}
17391 +#else
17392 +#define jornada56x_set_vpp NULL
17393 +#endif
17394 +
17395  #ifdef CONFIG_SA1100_JORNADA720
17396  static struct mtd_partition jornada720_partitions[] = {
17397         {
17398 @@ -822,6 +848,12 @@
17399                 nb_parts     = ARRAY_SIZE(huw_webpanel_partitions);
17400         }
17401  #endif
17402 +#ifdef CONFIG_SA1100_JORNADA56X
17403 +       if (machine_is_jornada56x()) {
17404 +               *parts       = jornada56x_partitions;
17405 +               nb_parts     = ARRAY_SIZE(jornada56x_partitions);
17406 +       }
17407 +#endif
17408  #ifdef CONFIG_SA1100_JORNADA720
17409         if (machine_is_jornada720()) {
17410                 *parts       = jornada720_partitions;
17411 @@ -932,10 +964,10 @@
17412                         break;
17413                 }
17414  
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;
17422  
17423                 simple_map_init(sa[i].map);
17424 @@ -1066,10 +1098,10 @@
17425                 return;
17426         }
17427  
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)
17435                 goto fail;
17436         simple_map_init(&sa1100_probe_map);
17437 @@ -1160,7 +1192,7 @@
17438                 info[0].size = SZ_16M;
17439                 nr = 1;
17440         }
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;
17448                 nr = 1;
17449         }
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;
17454 +               nr = 1;
17455 +       }
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 @@
17460                 return nr;
17461  
17462         /*
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.
17466          */
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
17472 @@ -0,0 +1,247 @@
17473 +/*
17474 + * Handle mapping of the flash memory access routines on the SBC8240 board.
17475 + *
17476 + * Carolyn Smith, Tektronix, Inc.
17477 + *
17478 + * This code is GPLed
17479 + *
17480 + * $Id: sbc8240.c,v 1.4 2004/07/12 22:38:29 dwmw2 Exp $
17481 + *
17482 + */
17483 +
17484 +/*
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.
17491 + */
17492 +
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>
17498 +
17499 +#include <linux/mtd/mtd.h>
17500 +#include <linux/mtd/map.h>
17501 +#include <linux/mtd/cfi.h>
17502 +
17503 +#ifdef CONFIG_MTD_PARTITIONS
17504 +#include <linux/mtd/partitions.h>
17505 +#endif
17506 +
17507 +#define        DEBUG
17508 +
17509 +#ifdef DEBUG
17510 +# define debugk(fmt,args...)   printk(fmt ,##args)
17511 +#else
17512 +# define debugk(fmt,args...)
17513 +#endif
17514 +
17515 +
17516 +#define WINDOW_ADDR0   0xFFF00000              /* 512 KiB */
17517 +#define WINDOW_SIZE0   0x00080000
17518 +#define BUSWIDTH0      1
17519 +
17520 +#define WINDOW_ADDR1   0xFF000000              /* 4 MiB */
17521 +#define WINDOW_SIZE1   0x00400000
17522 +#define BUSWIDTH1      8
17523 +
17524 +#define MSG_PREFIX "sbc8240:"  /* prefix for our printk()'s */
17525 +#define MTDID     "sbc8240-%d" /* for mtdparts= partitioning */
17526 +
17527 +
17528 +static struct map_info sbc8240_map[2] = {
17529 +       {
17530 +               .name           = "sbc8240 Flash Bank #0",
17531 +               .size           = WINDOW_SIZE0,
17532 +               .bankwidth       = BUSWIDTH0,
17533 +       },
17534 +       {
17535 +               .name           = "sbc8240 Flash Bank #1",
17536 +               .size           = WINDOW_SIZE1,
17537 +               .bankwidth       = BUSWIDTH1,
17538 +       }
17539 +};
17540 +
17541 +#define NUM_FLASH_BANKS        (sizeof(sbc8240_map) / sizeof(struct map_info))
17542 +
17543 +/*
17544 + * The following defines the partition layout of SBC8240 boards.
17545 + *
17546 + * See include/linux/mtd/partitions.h for definition of the
17547 + * mtd_partition structure.
17548 + *
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.
17553 + */
17554 +
17555 +#ifdef CONFIG_MTD_PARTITIONS
17556 +
17557 +static struct mtd_partition sbc8240_uboot_partitions [] = {
17558 +       /* Bank 0 */
17559 +       {
17560 +               .name = "U-boot",                       /* U-Boot Firmware      */
17561 +               .offset =       0,
17562 +               .size = 0x00070000,                     /*  7 x 64 KiB sectors  */
17563 +               .mask_flags = MTD_WRITEABLE,            /*  force read-only     */
17564 +       },
17565 +       {
17566 +               .name = "environment",                  /* U-Boot environment   */
17567 +               .offset =       0x00070000,
17568 +               .size = 0x00010000,                     /*  1 x 64 KiB sector   */
17569 +       },
17570 +};
17571 +
17572 +static struct mtd_partition sbc8240_fs_partitions [] = {
17573 +       {
17574 +               .name = "jffs",                         /* JFFS  filesystem     */
17575 +               .offset =       0,
17576 +               .size = 0x003C0000,                     /*  4 * 15 * 64KiB      */
17577 +       },
17578 +       {
17579 +               .name = "tmp32",
17580 +               .offset =       0x003C0000,
17581 +               .size = 0x00020000,                     /*  4 * 32KiB           */
17582 +       },
17583 +       {
17584 +               .name = "tmp8a",
17585 +               .offset =       0x003E0000,
17586 +               .size = 0x00008000,                     /*  4 * 8KiB            */
17587 +       },
17588 +       {
17589 +               .name = "tmp8b",
17590 +               .offset =       0x003E8000,
17591 +               .size = 0x00008000,                     /*  4 * 8KiB            */
17592 +       },
17593 +       {
17594 +               .name = "tmp16",
17595 +               .offset =       0x003F0000,
17596 +               .size = 0x00010000,                     /*  4 * 16KiB           */
17597 +       }
17598 +};
17599 +
17600 +#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
17601 +
17602 +/* trivial struct to describe partition information */
17603 +struct mtd_part_def
17604 +{
17605 +       int nums;
17606 +       unsigned char *type;
17607 +       struct mtd_partition* mtd_part;
17608 +};
17609 +
17610 +static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS];
17611 +static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS];
17612 +
17613 +
17614 +#endif /* CONFIG_MTD_PARTITIONS */
17615 +
17616 +
17617 +int __init init_sbc8240_mtd (void)
17618 +{
17619 +       static struct _cjs {
17620 +               u_long addr;
17621 +               u_long size;
17622 +       } pt[NUM_FLASH_BANKS] = {
17623 +               {
17624 +                       .addr = WINDOW_ADDR0,
17625 +                       .size = WINDOW_SIZE0
17626 +               },
17627 +               {
17628 +                       .addr = WINDOW_ADDR1,
17629 +                       .size = WINDOW_SIZE1
17630 +               },
17631 +       };
17632 +
17633 +       int devicesfound = 0;
17634 +       int i;
17635 +
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);
17639 +
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");
17644 +                       return -EIO;
17645 +               }
17646 +               simple_map_init(&sbc8240_mtd[i]);
17647 +
17648 +               sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]);
17649 +
17650 +               if (sbc8240_mtd[i]) {
17651 +                       sbc8240_mtd[i]->module = THIS_MODULE;
17652 +                       devicesfound++;
17653 +               }
17654 +       }
17655 +
17656 +       if (!devicesfound) {
17657 +               printk(KERN_NOTICE MSG_PREFIX
17658 +                      "No suppported flash chips found!\n");
17659 +               return -ENXIO;
17660 +       }
17661 +
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);
17669 +
17670 +       for (i = 0; i < NUM_FLASH_BANKS; i++) {
17671 +
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]);
17677 +               } else {
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);
17683 +               }
17684 +       }
17685 +#else
17686 +       printk(KERN_NOTICE MSG_PREFIX
17687 +              "Registering %d flash banks at once\n", devicesfound);
17688 +
17689 +       for (i = 0; i < devicesfound; i++) {
17690 +               add_mtd_device(sbc8240_mtd[i]);
17691 +       }
17692 +#endif /* CONFIG_MTD_PARTITIONS */
17693 +
17694 +       return devicesfound == 0 ? -ENXIO : 0;
17695 +}
17696 +
17697 +static void __exit cleanup_sbc8240_mtd (void)
17698 +{
17699 +       int i;
17700 +
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]);
17705 +               }
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;
17709 +               }
17710 +       }
17711 +}
17712 +
17713 +module_init (init_sbc8240_mtd);
17714 +module_exit (cleanup_sbc8240_mtd);
17715 +
17716 +MODULE_LICENSE ("GPL");
17717 +MODULE_AUTHOR ("Carolyn Smith <carolyn.smith@tektronix.com>");
17718 +MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards");
17719 +
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
17724 @@ -17,7 +17,7 @@
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
17727  
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 $
17730  
17731  The SBC-MediaGX / SBC-GXx has up to 16 MiB of 
17732  Intel StrataFlash (28F320/28F640) in x8 mode.  
17733 @@ -84,7 +84,7 @@
17734  // Globals
17735  
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;
17740  
17741  /* partition_info gives details on the logical partitions that the split the 
17742 @@ -114,32 +114,12 @@
17743  }
17744  
17745  
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)
17748  {
17749 -       __u8 ret;
17750 +       map_word ret;
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);
17755 -       return ret;
17756 -}
17757 -
17758 -static __u16 sbc_gxx_read16(struct map_info *map, unsigned long ofs)
17759 -{
17760 -       __u16 ret;
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);
17765 -       return ret;
17766 -}
17767 -
17768 -static __u32 sbc_gxx_read32(struct map_info *map, unsigned long ofs)
17769 -{
17770 -       __u32 ret;
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);
17776         return ret;
17777  }
17778 @@ -161,27 +141,11 @@
17779         }
17780  }
17781  
17782 -static void sbc_gxx_write8(struct map_info *map, __u8 d, unsigned long adr)
17783 -{
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);
17788 -}
17789 -
17790 -static void sbc_gxx_write16(struct map_info *map, __u16 d, unsigned long adr)
17791 -{
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);
17796 -}
17797 -
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)
17800  {
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);
17806  }
17807  
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
17811                          the chips */
17812 -       .buswidth = 1,
17813 -       .read8 = sbc_gxx_read8,
17814 -       .read16 = sbc_gxx_read16,
17815 -       .read32 = sbc_gxx_read32,
17816 +       .bankwidth = 1,
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
17824  };
17825  
17826 @@ -235,7 +195,7 @@
17827  
17828  int __init init_sbc_gxx(void)
17829  {
17830 -       iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
17831 +       iomapadr = (void __iomem *)ioremap(WINDOW_START, WINDOW_LENGTH);
17832         if (!iomapadr) {
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
17839 @@ -16,7 +16,7 @@
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
17842   *
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 $
17845   *
17846   *
17847   * The SC520CDP is an evaluation board for the Elan SC520 processor available
17848 @@ -90,19 +90,19 @@
17849         {
17850                 .name = "SC520CDP Flash Bank #0",
17851                 .size = WINDOW_SIZE_0,
17852 -               .buswidth = 4,
17853 +               .bankwidth = 4,
17854                 .phys = WINDOW_ADDR_0
17855         },
17856         {
17857                 .name = "SC520CDP Flash Bank #1",
17858                 .size = WINDOW_SIZE_1,
17859 -               .buswidth = 4,
17860 +               .bankwidth = 4,
17861                 .phys = WINDOW_ADDR_1
17862         },
17863         {
17864                 .name = "SC520CDP DIL Flash",
17865                 .size = WINDOW_SIZE_2,
17866 -               .buswidth = 1,
17867 +               .bankwidth = 1,
17868                 .phys = WINDOW_ADDR_2
17869         },
17870  };
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);
17874  
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);
17877  
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
17884 @@ -1,6 +1,6 @@
17885  /*
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>
17891   *
17892 @@ -67,7 +67,7 @@
17893  struct map_info scb2_map = {
17894         .name =      "SCB2 BIOS Flash",
17895         .size =      0,
17896 -       .buswidth =  1,
17897 +       .bankwidth =  1,
17898  };
17899  static int region_fail;
17900  
17901 @@ -163,7 +163,7 @@
17902         }
17903  
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;
17908  
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
17914 @@ -2,7 +2,7 @@
17915  
17916     Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
17917  
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 $ 
17920  
17921     National Semiconductor SCx200 flash mapped with DOCCS
17922  */
17923 @@ -173,14 +173,14 @@
17924  
17925         scx200_docflash_map.size = size;
17926         if (width == 8)
17927 -               scx200_docflash_map.buswidth = 1;
17928 +               scx200_docflash_map.bankwidth = 1;
17929         else
17930 -               scx200_docflash_map.buswidth = 2;
17931 +               scx200_docflash_map.bankwidth = 2;
17932  
17933         simple_map_init(&scx200_docflash_map);
17934  
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
17945 @@ -1,5 +1,5 @@
17946  /*
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 $
17949   *
17950   * Flash and EPROM on Hitachi Solution Engine and similar boards.
17951   *
17952 @@ -17,7 +17,7 @@
17953  #include <linux/mtd/map.h>
17954  #include <linux/mtd/partitions.h>
17955  #include <linux/config.h>
17956 -
17957 +#include <linux/errno.h>
17958  
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",
17964         .size = 0x400000,
17965 -       .buswidth = 4,
17966 +       .bankwidth = 4,
17967  };
17968  
17969  struct map_info soleng_flash_map = {
17970         .name = "Solution Engine FLASH",
17971         .size = 0x400000,
17972 -       .buswidth = 4,
17973 +       .bankwidth = 4,
17974  };
17975  
17976  static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
17977 @@ -62,9 +62,9 @@
17978  
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);
17988         
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
17993 @@ -1,4 +1,4 @@
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 $
17996   *
17997   * sun_uflash - Driver implementation for user-programmable flash
17998   * present on many Sun Microsystems SME boardsets.
17999 @@ -51,7 +51,7 @@
18000  struct map_info uflash_map_templ = {
18001                 .name =         "SUNW,???-????",
18002                 .size =         UFLASH_WINDOW_SIZE,
18003 -               .buswidth =     UFLASH_BUSWIDTH,
18004 +               .bankwidth =    UFLASH_BUSWIDTH,
18005  };
18006  
18007  int uflash_devinit(struct linux_ebus_device* edev)
18008 @@ -97,7 +97,7 @@
18009         }
18010         pdev->map.phys = edev->resource[0].start;
18011         pdev->map.virt = 
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__);
18016                 kfree(pdev->name);
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
18021 @@ -2,7 +2,7 @@
18022   * Handle mapping of the flash memory access routines 
18023   * on TQM8xxL based devices.
18024   *
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 $
18027   *
18028   * based on rpxlite.c
18029   *
18030 @@ -105,7 +105,7 @@
18031           .name = "jffs",
18032           .offset = 0x00200000,
18033           .size = 0x00200000,
18034 -         .//size = MTDPART_SIZ_FULL,
18035 +         //.size = MTDPART_SIZ_FULL,
18036         }
18037  };
18038  #endif
18039 @@ -151,11 +151,11 @@
18040                 sprintf(map_banks[idx]->name, "TQM8xxL%d", idx);
18041  
18042                 map_banks[idx]->size = flash_size;
18043 -               map_banks[idx]->buswidth = 4;
18044 +               map_banks[idx]->bankwidth = 4;
18045  
18046                 simple_map_init(map_banks[idx]);
18047  
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
18057 @@ -2,7 +2,7 @@
18058   * tsunami_flash.c
18059   *
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 $
18063   */
18064  #include <asm/io.h>
18065  #include <asm/core_tsunami.h>
18066 @@ -15,14 +15,16 @@
18067  #define FLASH_DISABLE_BYTE 0x00
18068  
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)
18072  {
18073 -       return tsunami_tig_readb(offset);
18074 +       map_word val;
18075 +       val.x[0] = tsunami_tig_readb(offset);
18076 +       return val;
18077  }
18078  
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)
18081  {
18082 -       tsunami_tig_writeb(value, offset);
18083 +       tsunami_tig_writeb(value.x[0], offset);
18084  }
18085  
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,
18090         .phys = NO_XIP;
18091 -       .buswidth = 1,
18092 -       .read8 = tsunami_flash_read8,
18093 +       .bankwidth = 1,
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,
18099  };
18100  
18101 @@ -84,7 +86,7 @@
18102  
18103  static int __init init_tsunami_flash(void)
18104  {
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 };
18107         char **type;
18108  
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
18114 @@ -5,7 +5,7 @@
18115   *
18116   *     (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
18117   *
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 $
18120   */
18121  
18122  /****************************************************************************/
18123 @@ -17,6 +17,7 @@
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;
18137  
18138         printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
18139                 (int) mapp->map_priv_2, (int) mapp->size);
18140  
18141 -       mapp->virt = (unsigned long)
18142 +       mapp->virt = (void __iomem *)
18143                 ioremap_nocache(mapp->phys, mapp->size);
18144  
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
18150 @@ -1,4 +1,4 @@
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  /* ######################################################################
18154  
18155     Tempustech VMAX SBC301 MTD Driver.
18156 @@ -54,32 +54,12 @@
18157                 __vmax301_page(map, page);
18158  }
18159  
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)
18162  {
18163 -       __u8 ret;
18164 +       map_word ret;
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);
18169 -       return ret;
18170 -}
18171 -
18172 -static __u16 vmax301_read16(struct map_info *map, unsigned long ofs)
18173 -{
18174 -       __u16 ret;
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);
18179 -       return ret;
18180 -}
18181 -
18182 -static __u32 vmax301_read32(struct map_info *map, unsigned long ofs)
18183 -{
18184 -       __u32 ret;
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);
18190         return ret;
18191  }
18192 @@ -100,27 +80,11 @@
18193         }
18194  }
18195  
18196 -static void vmax301_write8(struct map_info *map, __u8 d, unsigned long adr)
18197 -{
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);
18202 -}
18203 -
18204 -static void vmax301_write16(struct map_info *map, __u16 d, unsigned long adr)
18205 -{
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);
18210 -}
18211 -
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)
18214  {
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);
18220  }
18221  
18222 @@ -146,14 +110,10 @@
18223                 .name = "VMAX301 Internal Flash",
18224                 .phys = NO_XIP,
18225                 .size = 3*2*1024*1024,
18226 -               .buswidth = 1,
18227 -               .read8 = vmax301_read8,
18228 -               .read16 = vmax301_read16,
18229 -               .read32 = vmax301_read32,
18230 +               .bankwidth = 1,
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",
18242                 .phys = NO_XIP,
18243                 .size = 0,
18244 -               .buswidth = 1,
18245 -               .read8 = vmax301_read8,
18246 -               .read16 = vmax301_read16,
18247 -               .read32 = vmax301_read32,
18248 +               .bankwidth = 1,
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
18262 @@ -0,0 +1,181 @@
18263 +/*
18264 + * $Id: wr_sbc82xx_flash.c,v 1.6 2004/09/16 23:27:14 gleixner Exp $
18265 + *
18266 + * Map for flash chips on Wind River PowerQUICC II SBC82xx board.
18267 + *
18268 + * Copyright (C) 2004 Red Hat, Inc.
18269 + *
18270 + * Author: David Woodhouse <dwmw2@infradead.org>
18271 + *
18272 + */
18273 +
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>
18284 +
18285 +#include <asm/immap_cpm2.h>
18286 +
18287 +static struct mtd_info *sbcmtd[3];
18288 +static struct mtd_partition *sbcmtd_parts[3];
18289 +
18290 +struct map_info sbc82xx_flash_map[3] = {
18291 +       {.name = "Boot flash"},
18292 +       {.name = "Alternate boot flash"},
18293 +       {.name = "User flash"}
18294 +};
18295 +
18296 +static struct mtd_partition smallflash_parts[] = {
18297 +       {
18298 +               .name =         "space",
18299 +               .size =         0x100000,
18300 +               .offset =       0,
18301 +       }, {
18302 +               .name =         "bootloader",
18303 +               .size =         MTDPART_SIZ_FULL,
18304 +               .offset =       MTDPART_OFS_APPEND,
18305 +       }
18306 +};
18307 +
18308 +static struct mtd_partition bigflash_parts[] = {
18309 +       {
18310 +               .name =         "bootloader",
18311 +               .size =         0x00100000,
18312 +               .offset =       0,
18313 +       }, {
18314 +               .name =         "file system",
18315 +               .size =         0x01f00000,
18316 +               .offset =       MTDPART_OFS_APPEND,
18317 +       }, {
18318 +               .name =         "boot config",
18319 +               .size =         0x00100000,
18320 +               .offset =       MTDPART_OFS_APPEND,
18321 +       }, {
18322 +               .name =         "space",
18323 +               .size =         0x01f00000,
18324 +               .offset =       MTDPART_OFS_APPEND,
18325 +       }
18326 +};
18327 +
18328 +static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
18329 +
18330 +#define init_sbc82xx_one_flash(map, br, or)                    \
18331 +do {                                                           \
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;  \
18339 +       }                                                       \
18340 +} while (0);
18341 +
18342 +int __init init_sbc82xx_flash(void)
18343 +{
18344 +       volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl;
18345 +       int bigflash;
18346 +       int i;
18347 +
18348 +#ifdef CONFIG_SBC8560
18349 +       mc = ioremap(0xff700000 + 0x5000, sizeof(memctl_cpm2_t));
18350 +#else
18351 +       mc = &cpm2_immr->im_memctl;
18352 +#endif
18353 +
18354 +       bigflash = 1;
18355 +       if ((mc->memc_br0 & 0x00001800) == 0x00001800)
18356 +               bigflash = 0;
18357 +
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);
18361 +
18362 +#ifdef CONFIG_SBC8560
18363 +       iounmap((void *) mc);
18364 +#endif
18365 +
18366 +       for (i=0; i<3; i++) {
18367 +               int8_t flashcs[3] = { 0, 6, 1 };
18368 +               int nr_parts;
18369 +
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),
18373 +                      flashcs[i]);
18374 +               if (!sbc82xx_flash_map[i].phys) {
18375 +                       /* We know it can't be at zero. */
18376 +                       printk("): disabled by bootloader.\n");
18377 +                       continue;
18378 +               }
18379 +               printk(" at %08lx)\n",  sbc82xx_flash_map[i].phys);
18380 +
18381 +               sbc82xx_flash_map[i].virt = (void __iomem *)ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size);
18382 +
18383 +               if (!sbc82xx_flash_map[i].virt) {
18384 +                       printk("Failed to ioremap\n");
18385 +                       continue;
18386 +               }
18387 +
18388 +               simple_map_init(&sbc82xx_flash_map[i]);
18389 +
18390 +               sbcmtd[i] = do_map_probe("cfi_probe", &sbc82xx_flash_map[i]);
18391 +
18392 +               if (!sbcmtd[i])
18393 +                       continue;
18394 +
18395 +               sbcmtd[i]->owner = THIS_MODULE;
18396 +
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);
18401 +                       continue;
18402 +               }
18403 +
18404 +               /* No partitioning detected. Use default */
18405 +               if (i == 2) {
18406 +                       add_mtd_device(sbcmtd[i]);
18407 +               } else if (i == bigflash) {
18408 +                       add_mtd_partitions (sbcmtd[i], bigflash_parts, ARRAY_SIZE(bigflash_parts));
18409 +               } else {
18410 +                       add_mtd_partitions (sbcmtd[i], smallflash_parts, ARRAY_SIZE(smallflash_parts));
18411 +               }
18412 +       }
18413 +       return 0;
18414 +}
18415 +
18416 +static void __exit cleanup_sbc82xx_flash(void)
18417 +{
18418 +       int i;
18419 +
18420 +       for (i=0; i<3; i++) {
18421 +               if (!sbcmtd[i])
18422 +                       continue;
18423 +
18424 +               if (i<2 || sbcmtd_parts[i])
18425 +                       del_mtd_partitions(sbcmtd[i]);
18426 +               else
18427 +                       del_mtd_device(sbcmtd[i]);
18428 +                       
18429 +               kfree(sbcmtd_parts[i]);
18430 +               map_destroy(sbcmtd[i]);
18431 +               
18432 +               iounmap((void *)sbc82xx_flash_map[i].virt);
18433 +               sbc82xx_flash_map[i].virt = 0;
18434 +       }
18435 +}
18436 +
18437 +module_init(init_sbc82xx_flash);
18438 +module_exit(cleanup_sbc82xx_flash);
18439 +
18440 +
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
18448 @@ -0,0 +1,692 @@
18449 +/*
18450 + * $Id: mtd_blkdevs-24.c,v 1.16 2004/08/11 15:29:24 dmarlin Exp $
18451 + *
18452 + * (C) 2003 David Woodhouse <dwmw2@infradead.org>
18453 + *
18454 + * Interface to Linux 2.4 block layer for MTD 'translation layers'.
18455 + *
18456 + */
18457 +
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>
18473 +
18474 +static LIST_HEAD(blktrans_majors);
18475 +
18476 +extern struct semaphore mtd_table_mutex;
18477 +extern struct mtd_info *mtd_table[];
18478 +
18479 +struct mtd_blkcore_priv {
18480 +       devfs_handle_t devfs_dir_handle;
18481 +       int blksizes[256];
18482 +       int sizes[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;
18487 +       int exiting;
18488 +       wait_queue_head_t thread_wq;
18489 +};
18490 +
18491 +static inline struct mtd_blktrans_dev *tr_get_dev(struct mtd_blktrans_ops *tr,
18492 +                                          int devnum)
18493 +{
18494 +       struct list_head *this;
18495 +       struct mtd_blktrans_dev *d;
18496 +
18497 +       list_for_each(this, &tr->devs) {
18498 +               d = list_entry(this, struct mtd_blktrans_dev, list);
18499 +
18500 +               if (d->devnum == devnum)
18501 +                       return d;
18502 +       }
18503 +       return NULL;
18504 +}
18505 +
18506 +static inline struct mtd_blktrans_ops *get_tr(int major)
18507 +{
18508 +       struct list_head *this;
18509 +       struct mtd_blktrans_ops *t;
18510 +
18511 +       list_for_each(this, &blktrans_majors) {
18512 +               t = list_entry(this, struct mtd_blktrans_ops, list);
18513 +
18514 +               if (t->major == major)
18515 +                       return t;
18516 +       }
18517 +       return NULL;
18518 +}
18519 +
18520 +static int do_blktrans_request(struct mtd_blktrans_ops *tr,
18521 +                              struct mtd_blktrans_dev *dev,
18522 +                              struct request *req)
18523 +{
18524 +       unsigned long block, nsect;
18525 +       char *buf;
18526 +       int minor;
18527 +
18528 +       minor = MINOR(req->rq_dev);
18529 +       block = req->sector;
18530 +       nsect = req->current_nr_sectors;
18531 +       buf = req->buffer;
18532 +
18533 +       if (block + nsect > tr->blkcore_priv->part_table[minor].nr_sects) {
18534 +               printk(KERN_WARNING "Access beyond end of device.\n");
18535 +               return 0;
18536 +       }
18537 +       block += tr->blkcore_priv->part_table[minor].start_sect;
18538 +
18539 +       switch(req->cmd) {
18540 +       case READ:
18541 +               for (; nsect > 0; nsect--, block++, buf += 512)
18542 +                       if (tr->readsect(dev, block, buf))
18543 +                               return 0;
18544 +               return 1;
18545 +
18546 +       case WRITE:
18547 +               if (!tr->writesect)
18548 +                       return 0;
18549 +
18550 +               for (; nsect > 0; nsect--, block++, buf += 512)
18551 +                       if (tr->writesect(dev, block, buf))
18552 +                               return 0;
18553 +               return 1;
18554 +
18555 +       default:
18556 +               printk(KERN_NOTICE "Unknown request cmd %d\n", req->cmd);
18557 +               return 0;
18558 +       }
18559 +}
18560 +
18561 +static int mtd_blktrans_thread(void *arg)
18562 +{
18563 +       struct mtd_blktrans_ops *tr = arg;
18564 +       struct request_queue *rq = BLK_DEFAULT_QUEUE(tr->major);
18565 +
18566 +       /* we might get involved when memory gets low, so use PF_MEMALLOC */
18567 +       current->flags |= PF_MEMALLOC;
18568 +
18569 +       snprintf(current->comm, sizeof(current->comm), "%sd", tr->name);
18570 +
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
18574 +          do exit. */
18575 +       spin_lock_irq(&current->sigmask_lock);
18576 +       sigfillset(&current->blocked);
18577 +       recalc_sigpending();
18578 +       spin_unlock_irq(&current->sigmask_lock);
18579 +
18580 +       daemonize("%sd", tr->name);
18581 +
18582 +       while (!tr->blkcore_priv->exiting) {
18583 +               struct request *req;
18584 +               struct mtd_blktrans_dev *dev;
18585 +               int devnum;
18586 +               int res = 0;
18587 +               DECLARE_WAITQUEUE(wait, current);
18588 +
18589 +               spin_lock_irq(&io_request_lock);
18590 +
18591 +               if (list_empty(&rq->queue_head)) {
18592 +
18593 +                       add_wait_queue(&tr->blkcore_priv->thread_wq, &wait);
18594 +                       set_current_state(TASK_INTERRUPTIBLE);
18595 +
18596 +                       spin_unlock_irq(&io_request_lock);
18597 +
18598 +                       schedule();
18599 +                       remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait);
18600 +
18601 +                       continue;
18602 +               }
18603 +
18604 +               req = blkdev_entry_next_request(&rq->queue_head);
18605 +
18606 +               devnum = MINOR(req->rq_dev) >> tr->part_bits;
18607 +
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);
18611 +
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
18617 +                  callbacks. */
18618 +               spin_lock(&tr->blkcore_priv->devs_lock);
18619 +               dev = tr_get_dev(tr, devnum);
18620 +               spin_unlock(&tr->blkcore_priv->devs_lock);
18621 +
18622 +               BUG_ON(!dev);
18623 +
18624 +               /* Ensure serialisation of requests */
18625 +               down(&dev->sem);
18626 +
18627 +               res = do_blktrans_request(tr, dev, req);
18628 +               up(&dev->sem);
18629 +
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);
18635 +               }
18636 +       }
18637 +       complete_and_exit(&tr->blkcore_priv->thread_dead, 0);
18638 +}
18639 +
18640 +static void mtd_blktrans_request(struct request_queue *rq)
18641 +{
18642 +       struct mtd_blktrans_ops *tr = rq->queuedata;
18643 +       wake_up(&tr->blkcore_priv->thread_wq);
18644 +}
18645 +
18646 +int blktrans_open(struct inode *i, struct file *f)
18647 +{
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);
18652 +       int devnum;
18653 +       int ret = -ENODEV;
18654 +
18655 +       if (is_read_only(i->i_rdev) && (f->f_mode & FMODE_WRITE))
18656 +               return -EROFS;
18657 +
18658 +       down(&mtd_table_mutex);
18659 +
18660 +       tr = get_tr(major_nr);
18661 +
18662 +       if (!tr)
18663 +               goto out;
18664
18665 +       devnum = minor_nr >> tr->part_bits;
18666 +
18667 +       dev = tr_get_dev(tr, devnum);
18668 +
18669 +       if (!dev)
18670 +               goto out;
18671 +
18672 +       if (!tr->blkcore_priv->part_table[minor_nr].nr_sects) {
18673 +               ret = -ENODEV;
18674 +               goto out;
18675 +       }
18676 +
18677 +       if (!try_inc_mod_count(dev->mtd->owner))
18678 +               goto out;
18679 +
18680 +       if (!try_inc_mod_count(tr->owner))
18681 +               goto out_tr;
18682 +
18683 +       dev->mtd->usecount++;
18684 +
18685 +       ret = 0;
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);
18690 +       out_tr:
18691 +               if (tr->owner)
18692 +                       __MOD_DEC_USE_COUNT(tr->owner);
18693 +       }
18694 + out:
18695 +       up(&mtd_table_mutex);
18696 +
18697 +       return ret;
18698 +}
18699 +
18700 +int blktrans_release(struct inode *i, struct file *f)
18701 +{
18702 +       struct mtd_blktrans_dev *dev;
18703 +       struct mtd_blktrans_ops *tr;
18704 +       int ret = 0;
18705 +       int devnum;
18706 +
18707 +       down(&mtd_table_mutex);
18708 +
18709 +       tr = get_tr(MAJOR(i->i_rdev));
18710 +       if (!tr) {
18711 +               up(&mtd_table_mutex);
18712 +               return -ENODEV;
18713 +       }
18714 +
18715 +       devnum = MINOR(i->i_rdev) >> tr->part_bits;
18716 +       dev = tr_get_dev(tr, devnum);
18717 +
18718 +       if (!dev) {
18719 +               up(&mtd_table_mutex);
18720 +               return -ENODEV;
18721 +       }
18722 +
18723 +       if (tr->release)
18724 +               ret = tr->release(dev);
18725 +
18726 +       if (!ret) {
18727 +               dev->mtd->usecount--;
18728 +               if (dev->mtd->owner)
18729 +                       __MOD_DEC_USE_COUNT(dev->mtd->owner);
18730 +               if (tr->owner)
18731 +                       __MOD_DEC_USE_COUNT(tr->owner);
18732 +       }
18733 +       
18734 +       up(&mtd_table_mutex);
18735 +
18736 +       return ret;
18737 +}
18738 +
18739 +static int mtd_blktrans_rrpart(kdev_t rdev, struct mtd_blktrans_ops *tr,
18740 +                              struct mtd_blktrans_dev *dev)
18741 +{
18742 +       struct gendisk *gd = &(tr->blkcore_priv->gd);
18743 +       int i;
18744 +       int minor = MINOR(rdev);
18745 +
18746 +       if (minor & ((1<<tr->part_bits)-1) || !tr->part_bits) {
18747 +               /* BLKRRPART on a partition. Go away. */
18748 +               return -ENOTTY;
18749 +       }
18750 +
18751 +       if (!capable(CAP_SYS_ADMIN))
18752 +           return -EACCES;
18753 +
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);
18758 +
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;
18763 +       }
18764 +
18765 +       grok_partitions(gd, minor, 1 << tr->part_bits, 
18766 +                       tr->blkcore_priv->sizes[minor]);
18767 +       up(&mtd_table_mutex);
18768 +
18769 +       return 0;
18770 +}
18771 +
18772 +static int blktrans_ioctl(struct inode *inode, struct file *file, 
18773 +                             unsigned int cmd, unsigned long arg)
18774 +{
18775 +       struct mtd_blktrans_dev *dev;
18776 +       struct mtd_blktrans_ops *tr;
18777 +       int devnum;
18778 +
18779 +       switch(cmd) {
18780 +       case BLKGETSIZE:
18781 +        case BLKGETSIZE64:
18782 +        case BLKBSZSET:
18783 +        case BLKBSZGET:
18784 +        case BLKROSET:
18785 +        case BLKROGET:
18786 +        case BLKRASET:
18787 +        case BLKRAGET:
18788 +        case BLKPG:
18789 +        case BLKELVGET:
18790 +        case BLKELVSET:
18791 +               return blk_ioctl(inode->i_rdev, cmd, arg);
18792 +       }
18793 +
18794 +       down(&mtd_table_mutex);
18795 +
18796 +       tr = get_tr(MAJOR(inode->i_rdev));
18797 +       if (!tr) {
18798 +               up(&mtd_table_mutex);
18799 +               return -ENODEV;
18800 +       }
18801 +
18802 +       devnum = MINOR(inode->i_rdev) >> tr->part_bits;
18803 +       dev = tr_get_dev(tr, devnum);
18804 +
18805 +       up(&mtd_table_mutex);
18806 +
18807 +       if (!dev)
18808 +               return -ENODEV;
18809 +
18810 +       switch(cmd) {
18811 +       case BLKRRPART:
18812 +               return mtd_blktrans_rrpart(inode->i_rdev, tr, dev);
18813 +               
18814 +        case BLKFLSBUF:
18815 +               blk_ioctl(inode->i_rdev, cmd, arg);
18816 +               if (tr->flush)
18817 +                       return tr->flush(dev);
18818 +               /* The core code did the work, we had nothing to do. */
18819 +               return 0;
18820 +
18821 +       case HDIO_GETGEO:
18822 +               if (tr->getgeo) {
18823 +                       struct hd_geometry g;
18824 +                       struct gendisk *gd = &(tr->blkcore_priv->gd);
18825 +                       int ret;
18826 +
18827 +                       memset(&g, 0, sizeof(g));
18828 +                       ret = tr->getgeo(dev, &g);
18829 +                       if (ret)
18830 +                               return ret;
18831 +
18832 +                       g.start = gd->part[MINOR(inode->i_rdev)].start_sect;
18833 +                       if (copy_to_user((void *)arg, &g, sizeof(g)))
18834 +                               return -EFAULT;
18835 +                       return 0;
18836 +               } /* else */
18837 +       default:
18838 +               return -ENOTTY;
18839 +       }
18840 +}
18841 +
18842 +struct block_device_operations mtd_blktrans_ops = {
18843 +       .owner          = THIS_MODULE,
18844 +       .open           = blktrans_open,
18845 +       .release        = blktrans_release,
18846 +       .ioctl          = blktrans_ioctl,
18847 +};
18848 +
18849 +int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
18850 +{
18851 +       struct mtd_blktrans_ops *tr = new->tr;
18852 +       struct list_head *this;
18853 +       int last_devnum = -1;
18854 +       int i;
18855 +
18856 +       if (!down_trylock(&mtd_table_mutex)) {
18857 +               up(&mtd_table_mutex);
18858 +               BUG();
18859 +       }
18860 +
18861 +       spin_lock(&tr->blkcore_priv->devs_lock);
18862 +
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);
18871 +                               goto added;
18872 +                       }
18873 +               } else if (d->devnum == new->devnum) {
18874 +                       /* Required number taken */
18875 +                       spin_unlock(&tr->blkcore_priv->devs_lock);
18876 +                       return -EBUSY;
18877 +               } else if (d->devnum > new->devnum) {
18878 +                       /* Required number was free */
18879 +                       list_add_tail(&new->list, &d->list);
18880 +                       goto added;
18881 +               } 
18882 +               last_devnum = d->devnum;
18883 +       }
18884 +       if (new->devnum == -1)
18885 +               new->devnum = last_devnum+1;
18886 +
18887 +       if ((new->devnum << tr->part_bits) > 256) {
18888 +               spin_unlock(&tr->blkcore_priv->devs_lock);
18889 +               return -EBUSY;
18890 +       }
18891 +
18892 +       init_MUTEX(&new->sem);
18893 +       list_add_tail(&new->list, &tr->devs);
18894 + added:
18895 +       spin_unlock(&tr->blkcore_priv->devs_lock);
18896 +
18897 +       if (!tr->writesect)
18898 +               new->readonly = 1;
18899 +
18900 +       for (i = new->devnum << tr->part_bits;
18901 +            i < (new->devnum+1) << tr->part_bits; 
18902 +            i++) {
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;
18908 +       }
18909 +
18910 +       /*
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 */
18914 +
18915 +       tr->blkcore_priv->sizes[new->devnum << tr->part_bits] = 
18916 +               (new->size * new->blksize) >> 10; /* 2.4 and its dumb units */
18917 +
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;
18920 +
18921 +       if (tr->part_bits) {
18922 +               grok_partitions(&tr->blkcore_priv->gd, new->devnum,
18923 +                               1 << tr->part_bits, new->size);
18924 +       }
18925 +#ifdef CONFIG_DEVFS_FS
18926 +       if (!tr->part_bits) {
18927 +               char name[2];
18928 +
18929 +               name[0] = '0' + new->devnum;
18930 +               name[1] = 0;
18931 +
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);
18937 +       }
18938 +#endif
18939 +       return 0;
18940 +}
18941 +
18942 +int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
18943 +{
18944 +       struct mtd_blktrans_ops *tr = old->tr;
18945 +       int i;
18946 +
18947 +       if (!down_trylock(&mtd_table_mutex)) {
18948 +               up(&mtd_table_mutex);
18949 +               BUG();
18950 +       }
18951 +
18952 +#ifdef CONFIG_DEVFS_FS
18953 +       if (!tr->part_bits) {
18954 +               devfs_unregister(old->blkcore_priv);
18955 +               old->blkcore_priv = NULL;
18956 +       } else {
18957 +               devfs_register_partitions(&tr->blkcore_priv->gd,
18958 +                                         old->devnum << tr->part_bits, 1);
18959 +       }
18960 +#endif
18961 +       spin_lock(&tr->blkcore_priv->devs_lock);
18962 +       list_del(&old->list);
18963 +       spin_unlock(&tr->blkcore_priv->devs_lock);
18964 +
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;
18970 +       }
18971 +
18972 +       return 0;
18973 +}
18974 +
18975 +void blktrans_notify_remove(struct mtd_info *mtd)
18976 +{
18977 +       struct list_head *this, *this2, *next;
18978 +
18979 +       list_for_each(this, &blktrans_majors) {
18980 +               struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
18981 +
18982 +               list_for_each_safe(this2, next, &tr->devs) {
18983 +                       struct mtd_blktrans_dev *dev = list_entry(this2, struct mtd_blktrans_dev, list);
18984 +
18985 +                       if (dev->mtd == mtd)
18986 +                               tr->remove_dev(dev);
18987 +               }
18988 +       }
18989 +}
18990 +
18991 +void blktrans_notify_add(struct mtd_info *mtd)
18992 +{
18993 +       struct list_head *this;
18994 +
18995 +       if (mtd->type == MTD_ABSENT)
18996 +               return;
18997 +
18998 +       list_for_each(this, &blktrans_majors) {
18999 +               struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
19000 +
19001 +               tr->add_mtd(tr, mtd);
19002 +       }
19003 +
19004 +}
19005 +
19006 +static struct mtd_notifier blktrans_notifier = {
19007 +       .add = blktrans_notify_add,
19008 +       .remove = blktrans_notify_remove,
19009 +};
19010 +      
19011 +int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
19012 +{
19013 +       int ret, i;
19014 +
19015 +       /* Register the notifier if/when the first device type is 
19016 +          registered, to prevent the link/init ordering from fucking
19017 +          us over. */
19018 +       if (!blktrans_notifier.list.next)
19019 +               register_mtd_user(&blktrans_notifier);
19020 +
19021 +       tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);
19022 +       if (!tr->blkcore_priv)
19023 +               return -ENOMEM;
19024 +
19025 +       memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv));
19026 +
19027 +       down(&mtd_table_mutex);
19028 +
19029 +       ret = devfs_register_blkdev(tr->major, tr->name, &mtd_blktrans_ops);
19030 +       if (ret) {
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);
19035 +               return ret;
19036 +       }
19037 +
19038 +       blk_init_queue(BLK_DEFAULT_QUEUE(tr->major), &mtd_blktrans_request);
19039 +       (BLK_DEFAULT_QUEUE(tr->major))->queuedata = tr;
19040 +       
19041 +       init_completion(&tr->blkcore_priv->thread_dead);
19042 +       init_waitqueue_head(&tr->blkcore_priv->thread_wq);
19043 +
19044 +       ret = kernel_thread(mtd_blktrans_thread, tr, 
19045 +                         CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
19046 +       if (ret < 0) {
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);
19051 +               return ret;
19052 +       } 
19053 +
19054 +       tr->blkcore_priv->devfs_dir_handle = 
19055 +                       devfs_mk_dir(NULL, tr->name, NULL);
19056 +
19057 +       blksize_size[tr->major] = tr->blkcore_priv->blksizes;
19058 +       blk_size[tr->major] = tr->blkcore_priv->sizes;
19059 +
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;
19067 +
19068 +       spin_lock_init(&tr->blkcore_priv->devs_lock);
19069 +
19070 +       add_gendisk(&tr->blkcore_priv->gd);
19071 +
19072 +       INIT_LIST_HEAD(&tr->devs);
19073 +       list_add(&tr->list, &blktrans_majors);
19074 +
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]);
19078 +       }
19079 +       up(&mtd_table_mutex);
19080 +
19081 +       return 0;
19082 +}
19083 +
19084 +int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
19085 +{
19086 +       struct list_head *this, *next;
19087 +
19088 +       down(&mtd_table_mutex);
19089 +
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);
19094 +       
19095 +       /* Remove it from the list of active majors */
19096 +       list_del(&tr->list);
19097 +
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);
19102 +       }
19103 +
19104 +       blksize_size[tr->major] = NULL;
19105 +       blk_size[tr->major] = NULL;
19106 +
19107 +       del_gendisk(&tr->blkcore_priv->gd);
19108 +
19109 +       blk_cleanup_queue(BLK_DEFAULT_QUEUE(tr->major));
19110 +       devfs_unregister_blkdev(tr->major, tr->name);
19111 +
19112 +       devfs_unregister(tr->blkcore_priv->devfs_dir_handle);
19113 +
19114 +       up(&mtd_table_mutex);
19115 +
19116 +       kfree(tr->blkcore_priv);
19117 +
19118 +       if (!list_empty(&tr->devs))
19119 +               BUG();
19120 +       return 0;
19121 +}
19122 +
19123 +static void __exit mtd_blktrans_exit(void)
19124 +{
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);
19129 +}
19130 +
19131 +module_exit(mtd_blktrans_exit);
19132 +
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);
19137 +
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
19145 @@ -1,5 +1,5 @@
19146  /*
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 $
19149   *
19150   * (C) 2003 David Woodhouse <dwmw2@infradead.org>
19151   *
19152 @@ -220,7 +220,7 @@
19153                                 return ret;
19154  
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)))
19158                                 return -EFAULT;
19159                         return 0;
19160                 } /* else */
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);
19164  
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);
19169 +
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
19177 @@ -1,7 +1,7 @@
19178  /* 
19179   * Direct MTD block device access
19180   *
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 $
19183   *
19184   * (C) 2000-2003 Nicolas Pitre <nico@cam.org>
19185   * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
19186 @@ -275,7 +275,7 @@
19187         
19188         /* OK, it's not open. Create cache info for it */
19189         mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
19190 -       if (!mtdblks)
19191 +       if (!mtdblk)
19192                 return -ENOMEM;
19193  
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
19199 @@ -1,5 +1,5 @@
19200  /*
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 $
19203   *
19204   * Character-device access to raw MTD devices.
19205   *
19206 @@ -9,6 +9,7 @@
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 @@
19215  
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);
19220 +
19221 +static void mtd_notify_add(struct mtd_info* mtd)
19222 +{
19223 +       if (!mtd)
19224 +               return;
19225 +
19226 +       devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
19227 +                     S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index);
19228 +               
19229 +       devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
19230 +                     S_IFCHR | S_IRUGO, "mtd/%dro", mtd->index);
19231 +}
19232 +
19233 +static void mtd_notify_remove(struct mtd_info* mtd)
19234 +{
19235 +       if (!mtd)
19236 +               return;
19237 +       devfs_remove("mtd/%d", mtd->index);
19238 +       devfs_remove("mtd/%dro", mtd->index);
19239 +}
19240  
19241  static struct mtd_notifier notifier = {
19242         .add    = mtd_notify_add,
19243         .remove = mtd_notify_remove,
19244  };
19245  
19246 +static inline void mtdchar_devfs_init(void)
19247 +{
19248 +       devfs_mk_dir("mtd");
19249 +       register_mtd_user(&notifier);
19250 +}
19251 +
19252 +static inline void mtdchar_devfs_exit(void)
19253 +{
19254 +       unregister_mtd_user(&notifier);
19255 +       devfs_remove("mtd");
19256 +}
19257 +#else /* !DEVFS */
19258 +#define mtdchar_devfs_init() do { } while(0)
19259 +#define mtdchar_devfs_exit() do { } while(0)
19260  #endif
19261  
19262  static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
19263  {
19264         struct mtd_info *mtd=(struct mtd_info *)file->private_data;
19265  
19266 -
19267 -       down(&mtd->mutex);
19268         switch (orig) {
19269         case 0:
19270                 /* SEEK_SET */
19271 @@ -46,16 +77,14 @@
19272                 file->f_pos =mtd->size + offset;
19273                 break;
19274         default:
19275 -               up(&mtd->mutex);
19276                 return -EINVAL;
19277         }
19278  
19279 -       /* XXX Should return -EINVAL surely ?? */
19280         if (file->f_pos < 0)
19281                 file->f_pos = 0;
19282         else if (file->f_pos >= mtd->size)
19283                 file->f_pos = mtd->size - 1;
19284 -       up(&mtd->mutex);
19285 +
19286         return file->f_pos;
19287  }
19288  
19289 @@ -120,7 +149,7 @@
19290  */
19291  #define MAX_KMALLOC_SIZE 0x20000
19292  
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)
19295  {
19296         struct mtd_info *mtd = (struct mtd_info *)file->private_data;
19297         size_t retlen=0;
19298 @@ -131,16 +160,11 @@
19299         
19300         DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
19301  
19302 -       down(&mtd->mutex);
19303 -       
19304 -       if (count > mtd->size - *ppos)
19305 +       if (*ppos + count > mtd->size)
19306                 count = mtd->size - *ppos;
19307  
19308         if (!count)
19309 -       {
19310 -               up(&mtd->mutex);
19311                 return 0;
19312 -       }
19313         
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 @@
19317  
19318                 kbuf=kmalloc(len,GFP_KERNEL);
19319                 if (!kbuf)
19320 -               {
19321 -                       up(&mtd->mutex);
19322 -                       /* API error - should return I/O done so far if > 0 */
19323                         return -ENOMEM;
19324 -               }               
19325 +               
19326                 ret = MTD_READ(mtd, *ppos, len, &retlen, kbuf);
19327                 if (!ret) {
19328                         *ppos += retlen;
19329                         if (copy_to_user(buf, kbuf, retlen)) {
19330                                 kfree(kbuf);
19331 -                               up(&mtd->mutex);
19332 -                               /* API error - should return I/O done so far if > 0 */
19333                                 return -EFAULT;
19334                         }
19335                         else
19336 @@ -174,17 +193,16 @@
19337                 }
19338                 else {
19339                         kfree(kbuf);
19340 -                       up(&mtd->mutex);
19341                         return ret;
19342                 }
19343                 
19344                 kfree(kbuf);
19345         }
19346 -       up(&mtd->mutex);        
19347 +       
19348         return total_retlen;
19349  } /* mtd_read */
19350  
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)
19353  {
19354         struct mtd_info *mtd = (struct mtd_info *)file->private_data;
19355         char *kbuf;
19356 @@ -194,22 +212,15 @@
19357         int len;
19358  
19359         DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
19360 -
19361 -       down(&mtd->mutex);      
19362 -       if (*ppos >= mtd->size)
19363 -       {
19364 -               up(&mtd->mutex);
19365 +       
19366 +       if (*ppos == mtd->size)
19367                 return -ENOSPC;
19368 -       }
19369         
19370 -       if (count > mtd->size - *ppos)
19371 +       if (*ppos + count > mtd->size)
19372                 count = mtd->size - *ppos;
19373  
19374         if (!count)
19375 -       {
19376 -               up(&mtd->mutex);
19377                 return 0;
19378 -       }
19379  
19380         while (count) {
19381                 if (count > MAX_KMALLOC_SIZE) 
19382 @@ -219,14 +230,11 @@
19383  
19384                 kbuf=kmalloc(len,GFP_KERNEL);
19385                 if (!kbuf) {
19386 -//                     printk("kmalloc is null\n");
19387 -                       /* API bug should report I/O completed */
19388 -                       up(&mtd->mutex);
19389 +                       printk("kmalloc is null\n");
19390                         return -ENOMEM;
19391                 }
19392  
19393                 if (copy_from_user(kbuf, buf, len)) {
19394 -                       up(&mtd->mutex);
19395                         kfree(kbuf);
19396                         return -EFAULT;
19397                 }
19398 @@ -239,15 +247,13 @@
19399                         buf += retlen;
19400                 }
19401                 else {
19402 -                       up(&mtd->mutex);
19403                         kfree(kbuf);
19404 -                       /* API bug ?? */
19405                         return ret;
19406                 }
19407                 
19408                 kfree(kbuf);
19409         }
19410 -       up(&mtd->mutex);
19411 +
19412         return total_retlen;
19413  } /* mtd_write */
19414  
19415 @@ -256,7 +262,7 @@
19416      IOCTL calls for getting device parameters.
19417  
19418  ======================================================================*/
19419 -static void mtd_erase_callback (struct erase_info *instr)
19420 +static void mtdchar_erase_callback (struct erase_info *instr)
19421  {
19422         wake_up((wait_queue_head_t *)instr->priv);
19423  }
19424 @@ -265,6 +271,7 @@
19425                      u_int cmd, u_long arg)
19426  {
19427         struct mtd_info *mtd = (struct mtd_info *)file->private_data;
19428 +       void __user *argp = (void __user *)arg;
19429         int ret = 0;
19430         u_long size;
19431         
19432 @@ -272,17 +279,17 @@
19433  
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;
19439         }
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;
19444         }
19445         
19446         switch (cmd) {
19447         case MEMGETREGIONCOUNT:
19448 -               if (copy_to_user((int *) arg, &(mtd->numeraseregions), sizeof(int)))
19449 +               if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
19450                         return -EFAULT;
19451                 break;
19452  
19453 @@ -290,24 +297,19 @@
19454         {
19455                 struct region_info_user ur;
19456  
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)))
19461                         return -EFAULT;
19462 -               }
19463  
19464                 if (ur.regionindex >= mtd->numeraseregions)
19465                         return -EINVAL;
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)))
19470                         return -EFAULT;
19471                 break;
19472         }
19473  
19474         case MEMGETINFO:
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)))
19478                         return -EFAULT;
19479                 break;
19480  
19481 @@ -328,13 +330,13 @@
19482                         init_waitqueue_head(&waitq);
19483  
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))) {
19489                                 kfree(erase);
19490                                 return -EFAULT;
19491                         }
19492                         erase->mtd = mtd;
19493 -                       erase->callback = mtd_erase_callback;
19494 +                       erase->callback = mtdchar_erase_callback;
19495                         erase->priv = (unsigned long)&waitq;
19496                         
19497                         /*
19498 @@ -372,7 +374,7 @@
19499                 if(!(file->f_mode & 2))
19500                         return -EPERM;
19501  
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)))
19504                         return -EFAULT;
19505                 
19506                 if (buf.length > 0x4096)
19507 @@ -381,7 +383,7 @@
19508                 if (!mtd->write_oob)
19509                         ret = -EOPNOTSUPP;
19510                 else
19511 -                       ret = verify_area(VERIFY_READ, (char *)buf.ptr, buf.length);
19512 +                       ret = verify_area(VERIFY_READ, buf.ptr, buf.length);
19513  
19514                 if (ret)
19515                         return ret;
19516 @@ -397,7 +399,7 @@
19517  
19518                 ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf);
19519  
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)))
19522                         ret = -EFAULT;
19523  
19524                 kfree(databuf);
19525 @@ -411,7 +413,7 @@
19526                 void *databuf;
19527                 ssize_t retlen;
19528  
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)))
19531                         return -EFAULT;
19532                 
19533                 if (buf.length > 0x4096)
19534 @@ -420,7 +422,7 @@
19535                 if (!mtd->read_oob)
19536                         ret = -EOPNOTSUPP;
19537                 else
19538 -                       ret = verify_area(VERIFY_WRITE, (char *)buf.ptr, buf.length);
19539 +                       ret = verify_area(VERIFY_WRITE, buf.ptr, buf.length);
19540  
19541                 if (ret)
19542                         return ret;
19543 @@ -431,7 +433,7 @@
19544                 
19545                 ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf);
19546  
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))
19549                         ret = -EFAULT;
19550                 else if (retlen && copy_to_user(buf.ptr, databuf, retlen))
19551                         ret = -EFAULT;
19552 @@ -442,41 +444,73 @@
19553  
19554         case MEMLOCK:
19555         {
19556 -               unsigned long adrs[2];
19557 +               struct erase_info_user info;
19558  
19559 -               if (copy_from_user(adrs ,(void *)arg, 2* sizeof(unsigned long)))
19560 +               if (copy_from_user(&info, argp, sizeof(info)))
19561                         return -EFAULT;
19562  
19563                 if (!mtd->lock)
19564                         ret = -EOPNOTSUPP;
19565                 else
19566 -                       ret = mtd->lock(mtd, adrs[0], adrs[1]);
19567 +                       ret = mtd->lock(mtd, info.start, info.length);
19568                 break;
19569         }
19570  
19571         case MEMUNLOCK:
19572         {
19573 -               unsigned long adrs[2];
19574 +               struct erase_info_user info;
19575  
19576 -               if (copy_from_user(adrs, (void *)arg, 2* sizeof(unsigned long)))
19577 +               if (copy_from_user(&info, argp, sizeof(info)))
19578                         return -EFAULT;
19579  
19580                 if (!mtd->unlock)
19581                         ret = -EOPNOTSUPP;
19582                 else
19583 -                       ret = mtd->unlock(mtd, adrs[0], adrs[1]);
19584 +                       ret = mtd->unlock(mtd, info.start, info.length);
19585                 break;
19586         }
19587  
19588         case MEMSETOOBSEL:
19589         {
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)))
19592 +                       return -EFAULT;
19593 +               break;
19594 +       }
19595 +
19596 +       case MEMGETOOBSEL:
19597 +       {
19598 +               if (copy_to_user(argp, &(mtd->oobinfo), sizeof(struct nand_oobinfo)))
19599                         return -EFAULT;
19600                 break;
19601         }
19602 +
19603 +       case MEMGETBADBLOCK:
19604 +       {
19605 +               loff_t offs;
19606                 
19607 +               if (copy_from_user(&offs, argp, sizeof(loff_t)))
19608 +                       return -EFAULT;
19609 +               if (!mtd->block_isbad)
19610 +                       ret = -EOPNOTSUPP;
19611 +               else
19612 +                       return mtd->block_isbad(mtd, offs);
19613 +               break;
19614 +       }
19615 +
19616 +       case MEMSETBADBLOCK:
19617 +       {
19618 +               loff_t offs;
19619 +
19620 +               if (copy_from_user(&offs, argp, sizeof(loff_t)))
19621 +                       return -EFAULT;
19622 +               if (!mtd->block_markbad)
19623 +                       ret = -EOPNOTSUPP;
19624 +               else
19625 +                       return mtd->block_markbad(mtd, offs);
19626 +               break;
19627 +       }
19628 +
19629         default:
19630 -               DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %x)\n", cmd, MEMGETINFO);
19631                 ret = -ENOTTY;
19632         }
19633  
19634 @@ -493,30 +527,6 @@
19635         .release        = mtd_close,
19636  };
19637  
19638 -
19639 -#ifdef CONFIG_DEVFS_FS
19640 -/* Notification that a new device has been added. Create the devfs entry for
19641 - * it. */
19642 -
19643 -static void mtd_notify_add(struct mtd_info* mtd)
19644 -{
19645 -       if (!mtd)
19646 -               return;
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);
19651 -}
19652 -
19653 -static void mtd_notify_remove(struct mtd_info* mtd)
19654 -{
19655 -       if (!mtd)
19656 -               return;
19657 -       devfs_remove("mtd/%d", mtd->index);
19658 -       devfs_remove("mtd/%dro", mtd->index);
19659 -}
19660 -#endif
19661 -
19662  static int __init init_mtdchar(void)
19663  {
19664         if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) {
19665 @@ -525,20 +535,13 @@
19666                 return -EAGAIN;
19667         }
19668  
19669 -#ifdef CONFIG_DEVFS_FS
19670 -       devfs_mk_dir("mtd");
19671 -
19672 -       register_mtd_user(&notifier);
19673 -#endif
19674 +       mtdchar_devfs_init();
19675         return 0;
19676  }
19677  
19678  static void __exit cleanup_mtdchar(void)
19679  {
19680 -#ifdef CONFIG_DEVFS_FS
19681 -       unregister_mtd_user(&notifier);
19682 -       devfs_remove("mtd");
19683 -#endif
19684 +       mtdchar_devfs_exit();
19685         unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
19686  }
19687  
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
19692 @@ -7,7 +7,7 @@
19693   *
19694   * This code is GPL
19695   *
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 $
19698   */
19699  
19700  #include <linux/module.h>
19701 @@ -26,7 +26,7 @@
19702   */
19703  struct mtd_concat {
19704         struct mtd_info mtd;
19705 -       int             num_subdev;
19706 +       int num_subdev;
19707         struct mtd_info **subdev;
19708  };
19709  
19710 @@ -37,21 +37,20 @@
19711  #define SIZEOF_STRUCT_MTD_CONCAT(num_subdev)   \
19712         ((sizeof(struct mtd_concat) + (num_subdev) * sizeof(struct mtd_info *)))
19713  
19714 -
19715  /*
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.
19718   */
19719  #define CONCAT(x)  ((struct mtd_concat *)(x))
19720  
19721 -       
19722  /* 
19723   * MTD methods which look up the relevant subdevice, translate the
19724   * effective address and pass through to the subdevice.
19725   */
19726  
19727 -static int concat_read (struct mtd_info *mtd, loff_t from, size_t len, 
19728 -                       size_t *retlen, u_char *buf)
19729 +static int
19730 +concat_read(struct mtd_info *mtd, loff_t from, size_t len,
19731 +           size_t * retlen, u_char * buf)
19732  {
19733         struct mtd_concat *concat = CONCAT(mtd);
19734         int err = -EINVAL;
19735 @@ -59,43 +58,43 @@
19736  
19737         *retlen = 0;
19738  
19739 -       for(i = 0; i < concat->num_subdev; i++)
19740 -       {
19741 +       for (i = 0; i < concat->num_subdev; i++) {
19742                 struct mtd_info *subdev = concat->subdev[i];
19743                 size_t size, retsize;
19744  
19745 -               if (from >= subdev->size)
19746 -               {   /* Not destined for this subdev */
19747 -                       size  = 0;
19748 +               if (from >= subdev->size) {
19749 +                       /* Not destined for this subdev */
19750 +                       size = 0;
19751                         from -= subdev->size;
19752 +                       continue;
19753                 }
19754 +               if (from + len > subdev->size)
19755 +                       /* First part goes into this subdev */
19756 +                       size = subdev->size - from;
19757                 else
19758 -               {
19759 -                       if (from + len > subdev->size)
19760 -                               size = subdev->size - from; /* First part goes into this subdev */
19761 -                       else
19762 -                               size = len; /* Entire transaction goes into this subdev */
19763 -
19764 -                       err = subdev->read(subdev, from, size, &retsize, buf);
19765 -
19766 -                       if(err)
19767 -                               break;
19768 -
19769 -                       *retlen += retsize;
19770 -                       len -= size;
19771 -                       if(len == 0)
19772 -                               break;
19773 +                       /* Entire transaction goes into this subdev */
19774 +                       size = len;
19775  
19776 -                       err = -EINVAL;
19777 -                       buf += size;
19778 -                       from = 0;
19779 -               }
19780 +               err = subdev->read(subdev, from, size, &retsize, buf);
19781 +
19782 +               if (err)
19783 +                       break;
19784 +
19785 +               *retlen += retsize;
19786 +               len -= size;
19787 +               if (len == 0)
19788 +                       break;
19789 +
19790 +               err = -EINVAL;
19791 +               buf += size;
19792 +               from = 0;
19793         }
19794         return err;
19795  }
19796  
19797 -static int concat_write (struct mtd_info *mtd, loff_t to, size_t len,
19798 -                       size_t *retlen, const u_char *buf)
19799 +static int
19800 +concat_write(struct mtd_info *mtd, loff_t to, size_t len,
19801 +            size_t * retlen, const u_char * buf)
19802  {
19803         struct mtd_concat *concat = CONCAT(mtd);
19804         int err = -EINVAL;
19805 @@ -106,46 +105,44 @@
19806  
19807         *retlen = 0;
19808  
19809 -       for(i = 0; i < concat->num_subdev; i++)
19810 -       {
19811 +       for (i = 0; i < concat->num_subdev; i++) {
19812                 struct mtd_info *subdev = concat->subdev[i];
19813                 size_t size, retsize;
19814  
19815 -               if (to >= subdev->size)
19816 -               {
19817 -                       size  = 0;
19818 +               if (to >= subdev->size) {
19819 +                       size = 0;
19820                         to -= subdev->size;
19821 +                       continue;
19822                 }
19823 +               if (to + len > subdev->size)
19824 +                       size = subdev->size - to;
19825                 else
19826 -               {
19827 -                       if (to + len > subdev->size)
19828 -                               size = subdev->size - to;
19829 -                       else
19830 -                               size = len;
19831 -
19832 -                       if (!(subdev->flags & MTD_WRITEABLE))
19833 -                               err = -EROFS;
19834 -                       else
19835 -                               err = subdev->write(subdev, to, size, &retsize, buf);
19836 -
19837 -                       if(err)
19838 -                               break;
19839 -
19840 -                       *retlen += retsize;
19841 -                       len -= size;
19842 -                       if(len == 0)
19843 -                               break;
19844 +                       size = len;
19845  
19846 -                       err = -EINVAL;
19847 -                       buf += size;
19848 -                       to = 0;
19849 -               }
19850 +               if (!(subdev->flags & MTD_WRITEABLE))
19851 +                       err = -EROFS;
19852 +               else
19853 +                       err = subdev->write(subdev, to, size, &retsize, buf);
19854 +
19855 +               if (err)
19856 +                       break;
19857 +
19858 +               *retlen += retsize;
19859 +               len -= size;
19860 +               if (len == 0)
19861 +                       break;
19862 +
19863 +               err = -EINVAL;
19864 +               buf += size;
19865 +               to = 0;
19866         }
19867         return err;
19868  }
19869  
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)
19872 +static int
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)
19876  {
19877         struct mtd_concat *concat = CONCAT(mtd);
19878         int err = -EINVAL;
19879 @@ -153,53 +150,56 @@
19880  
19881         *retlen = 0;
19882  
19883 -       for(i = 0; i < concat->num_subdev; i++)
19884 -       {
19885 +       for (i = 0; i < concat->num_subdev; i++) {
19886                 struct mtd_info *subdev = concat->subdev[i];
19887                 size_t size, retsize;
19888 -        
19889 -               if (from >= subdev->size)
19890 -               {   /* Not destined for this subdev */
19891 -                       size  = 0;
19892 +
19893 +               if (from >= subdev->size) {
19894 +                       /* Not destined for this subdev */
19895 +                       size = 0;
19896                         from -= subdev->size;
19897 +                       continue;
19898                 }
19899 +
19900 +               if (from + len > subdev->size)
19901 +                       /* First part goes into this subdev */
19902 +                       size = subdev->size - from;
19903                 else
19904 -               {
19905 -                       if (from + len > subdev->size)
19906 -                               size = subdev->size - from; /* First part goes into this subdev */
19907 -                       else
19908 -                               size = len; /* Entire transaction goes into this subdev */
19909 -            
19910 -            if (subdev->read_ecc)
19911 -                       err = subdev->read_ecc(subdev, from, size, &retsize, buf, eccbuf, oobsel);
19912 -            else
19913 -                err = -EINVAL;
19914 -
19915 -                       if(err)
19916 -                               break;
19917 -
19918 -                       *retlen += retsize;
19919 -                       len -= size;
19920 -                       if(len == 0)
19921 -                               break;
19922 +                       /* Entire transaction goes into this subdev */
19923 +                       size = len;
19924  
19925 +               if (subdev->read_ecc)
19926 +                       err = subdev->read_ecc(subdev, from, size,
19927 +                                              &retsize, buf, eccbuf, oobsel);
19928 +               else
19929                         err = -EINVAL;
19930 -                       buf += size;
19931 -            if (eccbuf)
19932 -            {
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)); 
19937 -            }
19938 -                       from = 0;
19939 +
19940 +               if (err)
19941 +                       break;
19942 +
19943 +               *retlen += retsize;
19944 +               len -= size;
19945 +               if (len == 0)
19946 +                       break;
19947 +
19948 +               err = -EINVAL;
19949 +               buf += size;
19950 +               if (eccbuf) {
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));
19956                 }
19957 +               from = 0;
19958         }
19959         return err;
19960  }
19961  
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)
19964 +static int
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)
19968  {
19969         struct mtd_concat *concat = CONCAT(mtd);
19970         int err = -EINVAL;
19971 @@ -210,50 +210,48 @@
19972  
19973         *retlen = 0;
19974  
19975 -       for(i = 0; i < concat->num_subdev; i++)
19976 -       {
19977 +       for (i = 0; i < concat->num_subdev; i++) {
19978                 struct mtd_info *subdev = concat->subdev[i];
19979                 size_t size, retsize;
19980 -        
19981 -               if (to >= subdev->size)
19982 -               {
19983 -                       size  = 0;
19984 +
19985 +               if (to >= subdev->size) {
19986 +                       size = 0;
19987                         to -= subdev->size;
19988 +                       continue;
19989                 }
19990 +               if (to + len > subdev->size)
19991 +                       size = subdev->size - to;
19992                 else
19993 -               {
19994 -                       if (to + len > subdev->size)
19995 -                               size = subdev->size - to;
19996 -                       else
19997 -                               size = len;
19998 -
19999 -                       if (!(subdev->flags & MTD_WRITEABLE))
20000 -                               err = -EROFS;
20001 -                       else if (subdev->write_ecc)
20002 -                               err = subdev->write_ecc(subdev, to, size, &retsize, buf, eccbuf, oobsel);
20003 -            else
20004 -                err = -EINVAL;
20005 -
20006 -                       if(err)
20007 -                               break;
20008 -
20009 -                       *retlen += retsize;
20010 -                       len -= size;
20011 -                       if(len == 0)
20012 -                               break;
20013 +                       size = len;
20014  
20015 +               if (!(subdev->flags & MTD_WRITEABLE))
20016 +                       err = -EROFS;
20017 +               else if (subdev->write_ecc)
20018 +                       err = subdev->write_ecc(subdev, to, size,
20019 +                                               &retsize, buf, eccbuf, oobsel);
20020 +               else
20021                         err = -EINVAL;
20022 -                       buf += size;
20023 -            if (eccbuf)
20024 -                eccbuf += subdev->oobsize;
20025 -                       to = 0;
20026 -               }
20027 +
20028 +               if (err)
20029 +                       break;
20030 +
20031 +               *retlen += retsize;
20032 +               len -= size;
20033 +               if (len == 0)
20034 +                       break;
20035 +
20036 +               err = -EINVAL;
20037 +               buf += size;
20038 +               if (eccbuf)
20039 +                       eccbuf += subdev->oobsize;
20040 +               to = 0;
20041         }
20042         return err;
20043  }
20044  
20045 -static int concat_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
20046 -            size_t *retlen, u_char *buf)
20047 +static int
20048 +concat_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
20049 +               size_t * retlen, u_char * buf)
20050  {
20051         struct mtd_concat *concat = CONCAT(mtd);
20052         int err = -EINVAL;
20053 @@ -261,46 +259,47 @@
20054  
20055         *retlen = 0;
20056  
20057 -       for(i = 0; i < concat->num_subdev; i++)
20058 -       {
20059 +       for (i = 0; i < concat->num_subdev; i++) {
20060                 struct mtd_info *subdev = concat->subdev[i];
20061                 size_t size, retsize;
20062 -        
20063 -               if (from >= subdev->size)
20064 -               {   /* Not destined for this subdev */
20065 -                       size  = 0;
20066 +
20067 +               if (from >= subdev->size) {
20068 +                       /* Not destined for this subdev */
20069 +                       size = 0;
20070                         from -= subdev->size;
20071 +                       continue;
20072                 }
20073 +               if (from + len > subdev->size)
20074 +                       /* First part goes into this subdev */
20075 +                       size = subdev->size - from;
20076 +               else
20077 +                       /* Entire transaction goes into this subdev */
20078 +                       size = len;
20079 +
20080 +               if (subdev->read_oob)
20081 +                       err = subdev->read_oob(subdev, from, size,
20082 +                                              &retsize, buf);
20083                 else
20084 -               {
20085 -                       if (from + len > subdev->size)
20086 -                               size = subdev->size - from; /* First part goes into this subdev */
20087 -                       else
20088 -                               size = len; /* Entire transaction goes into this subdev */
20089 -            
20090 -            if (subdev->read_oob)
20091 -                       err = subdev->read_oob(subdev, from, size, &retsize, buf);
20092 -            else
20093 -                err = -EINVAL;
20094 -
20095 -                       if(err)
20096 -                               break;
20097 -
20098 -                       *retlen += retsize;
20099 -                       len -= size;
20100 -                       if(len == 0)
20101 -                               break;
20102 -
20103                         err = -EINVAL;
20104 -                       buf += size;
20105 -                       from = 0;
20106 -               }
20107 +
20108 +               if (err)
20109 +                       break;
20110 +
20111 +               *retlen += retsize;
20112 +               len -= size;
20113 +               if (len == 0)
20114 +                       break;
20115 +
20116 +               err = -EINVAL;
20117 +               buf += size;
20118 +               from = 0;
20119         }
20120         return err;
20121  }
20122  
20123 -static int concat_write_oob (struct mtd_info *mtd, loff_t to, size_t len, 
20124 -            size_t *retlen, const u_char *buf)
20125 +static int
20126 +concat_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
20127 +                size_t * retlen, const u_char * buf)
20128  {
20129         struct mtd_concat *concat = CONCAT(mtd);
20130         int err = -EINVAL;
20131 @@ -311,50 +310,46 @@
20132  
20133         *retlen = 0;
20134  
20135 -       for(i = 0; i < concat->num_subdev; i++)
20136 -       {
20137 +       for (i = 0; i < concat->num_subdev; i++) {
20138                 struct mtd_info *subdev = concat->subdev[i];
20139                 size_t size, retsize;
20140 -        
20141 -               if (to >= subdev->size)
20142 -               {
20143 -                       size  = 0;
20144 +
20145 +               if (to >= subdev->size) {
20146 +                       size = 0;
20147                         to -= subdev->size;
20148 +                       continue;
20149                 }
20150 +               if (to + len > subdev->size)
20151 +                       size = subdev->size - to;
20152                 else
20153 -               {
20154 -                       if (to + len > subdev->size)
20155 -                               size = subdev->size - to;
20156 -                       else
20157 -                               size = len;
20158 -
20159 -                       if (!(subdev->flags & MTD_WRITEABLE))
20160 -                               err = -EROFS;
20161 -                       else if (subdev->write_oob)
20162 -                               err = subdev->write_oob(subdev, to, size, &retsize, buf);
20163 -            else
20164 -                err = -EINVAL;
20165 -
20166 -                       if(err)
20167 -                               break;
20168 -
20169 -                       *retlen += retsize;
20170 -                       len -= size;
20171 -                       if(len == 0)
20172 -                               break;
20173 +                       size = len;
20174  
20175 +               if (!(subdev->flags & MTD_WRITEABLE))
20176 +                       err = -EROFS;
20177 +               else if (subdev->write_oob)
20178 +                       err = subdev->write_oob(subdev, to, size, &retsize,
20179 +                                               buf);
20180 +               else
20181                         err = -EINVAL;
20182 -                       buf += size;
20183 -                       to = 0;
20184 -               }
20185 +
20186 +               if (err)
20187 +                       break;
20188 +
20189 +               *retlen += retsize;
20190 +               len -= size;
20191 +               if (len == 0)
20192 +                       break;
20193 +
20194 +               err = -EINVAL;
20195 +               buf += size;
20196 +               to = 0;
20197         }
20198         return err;
20199  }
20200  
20201 -
20202 -static void concat_erase_callback (struct erase_info *instr)
20203 +static void concat_erase_callback(struct erase_info *instr)
20204  {
20205 -       wake_up((wait_queue_head_t *)instr->priv);
20206 +       wake_up((wait_queue_head_t *) instr->priv);
20207  }
20208  
20209  static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
20210 @@ -370,18 +365,18 @@
20211  
20212         erase->mtd = mtd;
20213         erase->callback = concat_erase_callback;
20214 -       erase->priv = (unsigned long)&waitq;
20215 -                       
20216 +       erase->priv = (unsigned long) &waitq;
20217 +
20218         /*
20219          * FIXME: Allow INTERRUPTIBLE. Which means
20220          * not having the wait_queue head on the stack.
20221          */
20222         err = mtd->erase(mtd, erase);
20223 -       if (!err)
20224 -       {
20225 +       if (!err) {
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)
20231                         schedule();
20232                 remove_wait_queue(&waitq, &wait);
20233                 set_current_state(TASK_RUNNING);
20234 @@ -391,21 +386,21 @@
20235         return err;
20236  }
20237  
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)
20240  {
20241         struct mtd_concat *concat = CONCAT(mtd);
20242         struct mtd_info *subdev;
20243         int i, err;
20244 -       u_int32_t length;
20245 +       u_int32_t length, offset = 0;
20246         struct erase_info *erase;
20247  
20248         if (!(mtd->flags & MTD_WRITEABLE))
20249                 return -EROFS;
20250  
20251 -       if(instr->addr > concat->mtd.size)
20252 +       if (instr->addr > concat->mtd.size)
20253                 return -EINVAL;
20254  
20255 -       if(instr->len + instr->addr > concat->mtd.size)
20256 +       if (instr->len + instr->addr > concat->mtd.size)
20257                 return -EINVAL;
20258  
20259         /*
20260 @@ -414,23 +409,22 @@
20261          * region info rather than looking at each particular sub-device
20262          * in turn.
20263          */
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))
20270                         return -EINVAL;
20271 -               if(instr->len & (concat->mtd.erasesize - 1))
20272 +               if (instr->len & (concat->mtd.erasesize - 1))
20273                         return -EINVAL;
20274 -       }
20275 -       else
20276 -       {       /* device has variable erase size */
20277 -               struct mtd_erase_region_info *erase_regions = concat->mtd.eraseregions;
20278 +       } else {
20279 +               /* device has variable erase size */
20280 +               struct mtd_erase_region_info *erase_regions =
20281 +                   concat->mtd.eraseregions;
20282  
20283                 /*
20284                  * Find the erase region where the to-be-erased area begins:
20285                  */
20286 -               for(i = 0; i < concat->mtd.numeraseregions && 
20287 -                          instr->addr >= erase_regions[i].offset; i++)
20288 -                       ;
20289 +               for (i = 0; i < concat->mtd.numeraseregions &&
20290 +                    instr->addr >= erase_regions[i].offset; i++) ;
20291                 --i;
20292  
20293                 /*
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:
20297                  */
20298 -               if (instr->addr & (erase_regions[i].erasesize-1))
20299 +               if (instr->addr & (erase_regions[i].erasesize - 1))
20300                         return -EINVAL;
20301  
20302                 /*
20303                  * now find the erase region where the to-be-erased area ends:
20304                  */
20305 -               for(; i < concat->mtd.numeraseregions && 
20306 -                     (instr->addr + instr->len) >=  erase_regions[i].offset ; ++i)
20307 -                       ;
20308 +               for (; i < concat->mtd.numeraseregions &&
20309 +                    (instr->addr + instr->len) >= erase_regions[i].offset;
20310 +                    ++i) ;
20311                 --i;
20312                 /*
20313                  * check if the ending offset is aligned to this region's erase size
20314                  */
20315 -               if ((instr->addr + instr->len) & (erase_regions[i].erasesize-1))
20316 +               if ((instr->addr + instr->len) & (erase_regions[i].erasesize -
20317 +                                                 1))
20318                         return -EINVAL;
20319         }
20320  
20321 +       instr->fail_addr = 0xffffffff;
20322 +
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);
20326  
20327         if (!erase)
20328                 return -ENOMEM;
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
20332          */
20333 -       for(i = 0; i < concat->num_subdev; i++)
20334 -       {
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;
20340 -               else
20341 +                       offset += subdev->size;
20342 +               } else {
20343                         break;
20344 -    }
20345 -       if(i >= concat->num_subdev)     /* must never happen since size */
20346 -               BUG();                                  /* limit has been verified above */
20347 +               }
20348 +       }
20349 +
20350 +       /* must never happen since size limit has been verified above */
20351 +       if (i >= concat->num_subdev)
20352 +               BUG();
20353  
20354         /* now do the erase: */
20355         err = 0;
20356 -       for(;length > 0; i++)   /* loop for all subevices affected by this request */
20357 -       {
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 */
20362  
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;
20367                 else
20368                         erase->len = length;
20369  
20370 -               if (!(subdev->flags & MTD_WRITEABLE))
20371 -               {
20372 +               if (!(subdev->flags & MTD_WRITEABLE)) {
20373                         err = -EROFS;
20374                         break;
20375                 }
20376                 length -= erase->len;
20377 -               if ((err = concat_dev_erase(subdev, erase)))
20378 -               {
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)
20385 +                               BUG();
20386 +                       if (erase->fail_addr != 0xffffffff)
20387 +                               instr->fail_addr = erase->fail_addr + offset;
20388                         break;
20389                 }
20390                 /*
20391 @@ -512,96 +514,91 @@
20392                  * current subdevice, i.e. at offset zero.
20393                  */
20394                 erase->addr = 0;
20395 +               offset += subdev->size;
20396         }
20397 +       instr->state = erase->state;
20398         kfree(erase);
20399         if (err)
20400                 return err;
20401  
20402 -       instr->state = MTD_ERASE_DONE;
20403         if (instr->callback)
20404                 instr->callback(instr);
20405         return 0;
20406  }
20407  
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)
20410  {
20411         struct mtd_concat *concat = CONCAT(mtd);
20412         int i, err = -EINVAL;
20413  
20414 -       if ((len + ofs) > mtd->size) 
20415 +       if ((len + ofs) > mtd->size)
20416                 return -EINVAL;
20417  
20418 -       for(i = 0; i < concat->num_subdev; i++)
20419 -       {
20420 +       for (i = 0; i < concat->num_subdev; i++) {
20421                 struct mtd_info *subdev = concat->subdev[i];
20422                 size_t size;
20423  
20424 -               if (ofs >= subdev->size)
20425 -               {
20426 -                       size  = 0;
20427 +               if (ofs >= subdev->size) {
20428 +                       size = 0;
20429                         ofs -= subdev->size;
20430 +                       continue;
20431                 }
20432 +               if (ofs + len > subdev->size)
20433 +                       size = subdev->size - ofs;
20434                 else
20435 -               {
20436 -                       if (ofs + len > subdev->size)
20437 -                               size = subdev->size - ofs;
20438 -                       else
20439 -                               size = len;
20440 -
20441 -                       err = subdev->lock(subdev, ofs, size);
20442 -
20443 -                       if(err)
20444 -                               break;
20445 -
20446 -                       len -= size;
20447 -                       if(len == 0)
20448 -                               break;
20449 +                       size = len;
20450  
20451 -                       err = -EINVAL;
20452 -                       ofs = 0;
20453 -               }
20454 +               err = subdev->lock(subdev, ofs, size);
20455 +
20456 +               if (err)
20457 +                       break;
20458 +
20459 +               len -= size;
20460 +               if (len == 0)
20461 +                       break;
20462 +
20463 +               err = -EINVAL;
20464 +               ofs = 0;
20465         }
20466 +
20467         return err;
20468  }
20469  
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)
20472  {
20473         struct mtd_concat *concat = CONCAT(mtd);
20474         int i, err = 0;
20475  
20476 -       if ((len + ofs) > mtd->size) 
20477 +       if ((len + ofs) > mtd->size)
20478                 return -EINVAL;
20479  
20480 -       for(i = 0; i < concat->num_subdev; i++)
20481 -       {
20482 +       for (i = 0; i < concat->num_subdev; i++) {
20483                 struct mtd_info *subdev = concat->subdev[i];
20484                 size_t size;
20485  
20486 -               if (ofs >= subdev->size)
20487 -               {
20488 -                       size  = 0;
20489 +               if (ofs >= subdev->size) {
20490 +                       size = 0;
20491                         ofs -= subdev->size;
20492 +                       continue;
20493                 }
20494 +               if (ofs + len > subdev->size)
20495 +                       size = subdev->size - ofs;
20496                 else
20497 -               {
20498 -                       if (ofs + len > subdev->size)
20499 -                               size = subdev->size - ofs;
20500 -                       else
20501 -                               size = len;
20502 -
20503 -                       err = subdev->unlock(subdev, ofs, size);
20504 -
20505 -                       if(err)
20506 -                               break;
20507 -
20508 -                       len -= size;
20509 -                       if(len == 0)
20510 -                               break;
20511 +                       size = len;
20512  
20513 -                       err = -EINVAL;
20514 -                       ofs = 0;
20515 -               }
20516 +               err = subdev->unlock(subdev, ofs, size);
20517 +
20518 +               if (err)
20519 +                       break;
20520 +
20521 +               len -= size;
20522 +               if (len == 0)
20523 +                       break;
20524 +
20525 +               err = -EINVAL;
20526 +               ofs = 0;
20527         }
20528 +
20529         return err;
20530  }
20531  
20532 @@ -610,8 +607,7 @@
20533         struct mtd_concat *concat = CONCAT(mtd);
20534         int i;
20535  
20536 -       for(i = 0; i < concat->num_subdev; i++)
20537 -       {
20538 +       for (i = 0; i < concat->num_subdev; i++) {
20539                 struct mtd_info *subdev = concat->subdev[i];
20540                 subdev->sync(subdev);
20541         }
20542 @@ -622,10 +618,9 @@
20543         struct mtd_concat *concat = CONCAT(mtd);
20544         int i, rc = 0;
20545  
20546 -       for(i = 0; i < concat->num_subdev; i++)
20547 -       {
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)
20552                         return rc;
20553         }
20554         return rc;
20555 @@ -636,8 +631,7 @@
20556         struct mtd_concat *concat = CONCAT(mtd);
20557         int i;
20558  
20559 -       for(i = 0; i < concat->num_subdev; i++)
20560 -       {
20561 +       for (i = 0; i < concat->num_subdev; i++) {
20562                 struct mtd_info *subdev = concat->subdev[i];
20563                 subdev->resume(subdev);
20564         }
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.
20568   */
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   */
20573 -{
20574 +struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],  /* subdevices to concatenate */
20575 +                                  int num_devs,        /* number of subdevices      */
20576 +                                  char *name)
20577 +{                              /* name for the new device   */
20578         int i;
20579         size_t size;
20580         struct mtd_concat *concat;
20581 @@ -661,94 +654,103 @@
20582         int num_erase_region;
20583  
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);
20589  
20590         /* allocate the device structure */
20591         size = SIZEOF_STRUCT_MTD_CONCAT(num_devs);
20592 -       concat = kmalloc (size, GFP_KERNEL);
20593 -       if(!concat)
20594 -       {
20595 -               printk ("memory allocation error while creating concatenated device \"%s\"\n",
20596 -                               name);
20597 -                       return NULL;
20598 +       concat = kmalloc(size, GFP_KERNEL);
20599 +       if (!concat) {
20600 +               printk
20601 +                   ("memory allocation error while creating concatenated device \"%s\"\n",
20602 +                    name);
20603 +               return NULL;
20604         }
20605         memset(concat, 0, size);
20606 -       concat->subdev = (struct mtd_info **)(concat + 1);
20607 +       concat->subdev = (struct mtd_info **) (concat + 1);
20608  
20609         /*
20610          * Set up the new "super" device's MTD object structure, check for
20611          * incompatibilites between the subdevices.
20612          */
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;
20624 -
20625 -       concat->subdev[0]   = subdev[0];
20626 -
20627 -       for(i = 1; i < num_devs; i++)
20628 -       {
20629 -               if(concat->mtd.type != subdev[i]->type)
20630 -               {
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;
20643 +
20644 +       concat->subdev[0] = subdev[0];
20645 +
20646 +       for (i = 1; i < num_devs; i++) {
20647 +               if (concat->mtd.type != subdev[i]->type) {
20648                         kfree(concat);
20649 -                       printk ("Incompatible device type on \"%s\"\n", subdev[i]->name);
20650 +                       printk("Incompatible device type on \"%s\"\n",
20651 +                              subdev[i]->name);
20652                         return NULL;
20653                 }
20654 -               if(concat->mtd.flags != subdev[i]->flags)
20655 -               {       /*
20656 -                        * Expect all flags except MTD_WRITEABLE to be equal on
20657 -                        * all subdevices.
20658 +               if (concat->mtd.flags != subdev[i]->flags) {
20659 +                       /*
20660 +                        * Expect all flags except MTD_WRITEABLE to be
20661 +                        * equal on all subdevices.
20662                          */
20663 -                       if((concat->mtd.flags ^ subdev[i]->flags) & ~MTD_WRITEABLE)
20664 -                       {
20665 +                       if ((concat->mtd.flags ^ subdev[i]->
20666 +                            flags) & ~MTD_WRITEABLE) {
20667                                 kfree(concat);
20668 -                               printk ("Incompatible device flags on \"%s\"\n", subdev[i]->name);
20669 +                               printk("Incompatible device flags on \"%s\"\n",
20670 +                                      subdev[i]->name);
20671                                 return NULL;
20672 -                       }
20673 -                       else    /* if writeable attribute differs, make super device writeable */
20674 -                               concat->mtd.flags |= subdev[i]->flags & MTD_WRITEABLE;
20675 +                       } else
20676 +                               /* if writeable attribute differs,
20677 +                                  make super device writeable */
20678 +                               concat->mtd.flags |=
20679 +                                   subdev[i]->flags & MTD_WRITEABLE;
20680                 }
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)
20686 -               {
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) {
20695                         kfree(concat);
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);
20699                         return NULL;
20700                 }
20701                 concat->subdev[i] = subdev[i];
20702 -               
20703 +
20704         }
20705  
20706 -       concat->num_subdev  = num_devs;
20707 -       concat->mtd.name    = name;
20708 +       concat->num_subdev = num_devs;
20709 +       concat->mtd.name = name;
20710  
20711         /*
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.
20715          */
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;
20728 -
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;
20737  
20738         /*
20739          * Combine the erase block size info of the subdevices:
20740 @@ -758,44 +760,44 @@
20741          */
20742         max_erasesize = curr_erasesize = subdev[0]->erasesize;
20743         num_erase_region = 1;
20744 -       for(i = 0; i < num_devs; i++)
20745 -       {
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;
20760                         }
20761 -               }
20762 -               else
20763 -               {       /* current subdevice has variable erase size */
20764 +               } else {
20765 +                       /* current subdevice has variable erase size */
20766                         int j;
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)
20770 -                               {
20771 +                       for (j = 0; j < subdev[i]->numeraseregions; j++) {
20772 +
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)
20779 +                                       curr_erasesize =
20780 +                                           subdev[i]->eraseregions[j].
20781 +                                           erasesize;
20782 +                                       if (curr_erasesize > max_erasesize)
20783                                                 max_erasesize = curr_erasesize;
20784                                 }
20785                         }
20786                 }
20787         }
20788  
20789 -       if(num_erase_region == 1)
20790 -       {       /*
20791 +       if (num_erase_region == 1) {
20792 +               /*
20793                  * All subdevices have the same uniform erase size.
20794                  * This is easy:
20795                  */
20796                 concat->mtd.erasesize = curr_erasesize;
20797                 concat->mtd.numeraseregions = 0;
20798 -       }
20799 -       else
20800 -       {       /*
20801 +       } else {
20802 +               /*
20803                  * erase block size varies across the subdevices: allocate
20804                  * space to store the data describing the variable erase regions
20805                  */
20806 @@ -804,13 +806,14 @@
20807  
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)
20813 -               {
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) {
20818                         kfree(concat);
20819 -                       printk ("memory allocation error while creating erase region list"
20820 -                               " for device \"%s\"\n", name);
20821 +                       printk
20822 +                           ("memory allocation error while creating erase region list"
20823 +                            " for device \"%s\"\n", name);
20824                         return NULL;
20825                 }
20826  
20827 @@ -820,46 +823,53 @@
20828                  */
20829                 curr_erasesize = subdev[0]->erasesize;
20830                 begin = position = 0;
20831 -               for(i = 0; i < num_devs; i++)
20832 -               {
20833 -                       if(subdev[i]->numeraseregions == 0)
20834 -                       {       /* current subdevice has uniform erase size */
20835 -                               if(subdev[i]->erasesize != curr_erasesize)
20836 -                               {       /*
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) {
20841 +                                       /*
20842                                          *  fill in an mtd_erase_region_info structure for the area
20843                                          *  we have walked so far:
20844                                          */
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 =
20850 +                                           curr_erasesize;
20851 +                                       erase_region_p->numblocks =
20852 +                                           (position - begin) / curr_erasesize;
20853                                         begin = position;
20854  
20855                                         curr_erasesize = subdev[i]->erasesize;
20856                                         ++erase_region_p;
20857                                 }
20858                                 position += subdev[i]->size;
20859 -                       }
20860 -                       else
20861 -                       {       /* current subdevice has variable erase size */
20862 +                       } else {
20863 +                               /* current subdevice has variable erase size */
20864                                 int j;
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)
20868 -                                       {
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 =
20878 +                                                   curr_erasesize;
20879 +                                               erase_region_p->numblocks =
20880 +                                                   (position -
20881 +                                                    begin) / curr_erasesize;
20882                                                 begin = position;
20883  
20884 -                                               curr_erasesize = subdev[i]->eraseregions[j].erasesize;
20885 +                                               curr_erasesize =
20886 +                                                   subdev[i]->eraseregions[j].
20887 +                                                   erasesize;
20888                                                 ++erase_region_p;
20889                                         }
20890 -                                       position += subdev[i]->eraseregions[j].numblocks * curr_erasesize;
20891 +                                       position +=
20892 +                                           subdev[i]->eraseregions[j].
20893 +                                           numblocks * curr_erasesize;
20894                                 }
20895                         }
20896                 }
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;
20902         }
20903 @@ -874,16 +884,14 @@
20904  void mtd_concat_destroy(struct mtd_info *mtd)
20905  {
20906         struct mtd_concat *concat = CONCAT(mtd);
20907 -       if(concat->mtd.numeraseregions)
20908 +       if (concat->mtd.numeraseregions)
20909                 kfree(concat->mtd.eraseregions);
20910         kfree(concat);
20911  }
20912  
20913 -
20914  EXPORT_SYMBOL(mtd_concat_create);
20915  EXPORT_SYMBOL(mtd_concat_destroy);
20916  
20917 -
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
20925 @@ -1,12 +1,11 @@
20926  /*
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 $
20929   *
20930   * Core registration and callback routines for MTD
20931   * drivers and users.
20932   *
20933   */
20934  
20935 -#include <linux/version.h>
20936  #include <linux/config.h>
20937  #include <linux/module.h>
20938  #include <linux/kernel.h>
20939 @@ -59,7 +58,6 @@
20940                         mtd_table[i] = mtd;
20941                         mtd->index = i;
20942                         mtd->usecount = 0;
20943 -                       init_MUTEX(&mtd->mutex);
20944  
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
20949   */
20950  
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)
20954  {
20955         unsigned long i;
20956 @@ -263,7 +261,7 @@
20957   *                    implement their own
20958   */
20959  
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)
20963  {
20964         unsigned long i;
20965 @@ -335,10 +333,7 @@
20966  /* Support for /proc/mtd */
20967  
20968  #ifdef CONFIG_PROC_FS
20969 -
20970 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
20971  static struct proc_dir_entry *proc_mtd;
20972 -#endif
20973  
20974  static inline int mtd_proc_info (char *buf, int i)
20975  {
20976 @@ -351,13 +346,8 @@
20977                        this->erasesize, this->name);
20978  }
20979  
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
20983 -#else
20984 -                        ,int unused
20985 -#endif
20986 -                       )
20987 +static int mtd_read_proc (char *page, char **start, off_t off, int count,
20988 +                         int *eof, void *data_unused)
20989  {
20990         int len, l, i;
20991          off_t   begin = 0;
20992 @@ -377,9 +367,7 @@
20993                  }
20994          }
20995  
20996 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
20997          *eof = 1;
20998 -#endif
20999  
21000  done:
21001         up(&mtd_table_mutex);
21002 @@ -389,18 +377,6 @@
21003          return ((count < begin+len-off) ? count : begin+len-off);
21004  }
21005  
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 */
21015 -    };
21016 -#endif
21017 -
21018  #endif /* CONFIG_PROC_FS */
21019  
21020  /*====================================================================*/
21021 @@ -409,16 +385,8 @@
21022  int __init init_mtd(void)
21023  {
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;
21028 -#else
21029 -        proc_register_dynamic(&proc_root,&mtd_proc_entry);
21030 -#endif
21031 -#endif
21032 -
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;
21037  #endif
21038  
21039  #ifdef CONFIG_PM
21040 @@ -437,12 +405,8 @@
21041  #endif
21042  
21043  #ifdef CONFIG_PROC_FS
21044 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
21045          if (proc_mtd)
21046 -          remove_proc_entry( "mtd", 0);
21047 -#else
21048 -        proc_unregister(&proc_root,mtd_proc_entry.low_ino);
21049 -#endif
21050 +               remove_proc_entry( "mtd", NULL);
21051  #endif
21052  }
21053  
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
21058 @@ -5,7 +5,7 @@
21059   *
21060   * This code is GPL
21061   *
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 $
21064   *
21065   *     02-21-2002      Thomas Gleixner <gleixner@autronix.de>
21066   *                     added support for read_oob, write_oob
21067 @@ -182,7 +182,7 @@
21068                                         len, retlen, buf);
21069  }
21070  
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)
21074  {
21075         struct mtd_part *part = PART(mtd);
21076 @@ -197,7 +197,7 @@
21077                                         NULL, &mtd->oobinfo);
21078  }
21079  
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)
21083  {
21084         struct mtd_part *part = PART(mtd);
21085 @@ -210,7 +210,7 @@
21086                                         NULL, &mtd->oobinfo);
21087  }
21088  
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)
21093  {
21094 @@ -224,7 +224,7 @@
21095                                         eccbuf, oobsel);
21096  }
21097  
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)
21102  {
21103 @@ -239,13 +239,29 @@
21104  static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
21105  {
21106         struct mtd_part *part = PART(mtd);
21107 +       int ret;
21108         if (!(mtd->flags & MTD_WRITEABLE))
21109                 return -EROFS;
21110         if (instr->addr >= mtd->size)
21111                 return -EINVAL;
21112         instr->addr += part->offset;
21113 -       return part->master->erase(part->master, instr);
21114 +       ret = part->master->erase(part->master, instr);
21115 +       return ret;
21116 +}
21117 +
21118 +void mtd_erase_callback(struct erase_info *instr)
21119 +{
21120 +       if (instr->mtd->erase == part_erase) {
21121 +               struct mtd_part *part = PART(instr->mtd);
21122 +
21123 +               if (instr->fail_addr != 0xffffffff)
21124 +                       instr->fail_addr -= part->offset;
21125 +               instr->addr -= part->offset;
21126 +       }
21127 +       if (instr->callback)
21128 +               instr->callback(instr);
21129  }
21130 +EXPORT_SYMBOL_GPL(mtd_erase_callback);
21131  
21132  static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
21133  {
21134 @@ -281,6 +297,26 @@
21135         part->master->resume(part->master);
21136  }
21137  
21138 +static int part_block_isbad (struct mtd_info *mtd, loff_t ofs)
21139 +{
21140 +       struct mtd_part *part = PART(mtd);
21141 +       if (ofs >= mtd->size)
21142 +               return -EINVAL;
21143 +       ofs += part->offset;
21144 +       return part->master->block_isbad(part->master, ofs);
21145 +}
21146 +
21147 +static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
21148 +{
21149 +       struct mtd_part *part = PART(mtd);
21150 +       if (!(mtd->flags & MTD_WRITEABLE))
21151 +               return -EROFS;
21152 +       if (ofs >= mtd->size)
21153 +               return -EINVAL;
21154 +       ofs += part->offset;
21155 +       return part->master->block_markbad(part->master, ofs);
21156 +}
21157 +
21158  /* 
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 @@
21162   */
21163  
21164  int add_mtd_partitions(struct mtd_info *master, 
21165 -                      struct mtd_partition *parts,
21166 +                      const struct mtd_partition *parts,
21167                        int nbparts)
21168  {
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 @@
21182                                 parts[i].name);
21183                 }
21184  
21185 +               /* copy oobinfo from master */ 
21186 +               memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo));
21187 +
21188                 if(parts[i].mtdp)
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
21195 @@ -1,5 +1,5 @@
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 $
21199  
21200  menu "NAND Flash Device Drivers"
21201         depends on MTD!=n
21202 @@ -9,8 +9,8 @@
21203         depends on MTD
21204         help
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>.
21210  
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.
21216  
21217 +config MTD_NAND_H1900
21218 +       tristate "iPAQ H1900 flash"
21219 +       depends on ARM && MTD_NAND && ARCH_PXA && MTD_PARTITIONS
21220 +       help
21221 +         This enables the driver for the iPAQ h1900 flash.
21222 +
21223  config MTD_NAND_SPIA
21224         tristate "NAND Flash device on SPIA board"
21225         depends on ARM && ARCH_P720T && MTD_NAND
21226         help
21227           If you had to ask, you don't have one. Say 'N'.
21228  
21229 +config MTD_NAND_TOTO
21230 +       tristate "NAND Flash device on TOTO board"
21231 +       depends on ARM && ARCH_OMAP && MTD_NAND
21232 +       help
21233 +         Support for NAND flash on Texas Instruments Toto platform.
21234 +
21235  config MTD_NAND_IDS
21236         tristate
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
21239 -       
21240 -endmenu
21241  
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
21245 +       help
21246 +         This enables the driver for the NAND flash device found on the
21247 +         Toshiba RBTX4925 reference board, which is a SmartMediaCard.
21248 +
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 
21252 +       help
21253 +         This enables the driver for the NAND flash device found on the
21254 +         Toshiba RBTX4938 reference board.
21255 +
21256 +config MTD_NAND_AU1550
21257 +       tristate "Au1550 NAND support"
21258 +       depends on SOC_AU1550 && MTD_NAND
21259 +       help
21260 +         This enables the driver for the NAND flash controller on the
21261 +         AMD/Alchemy 1550 SOC.
21262 +
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
21266 +       help
21267 +         This enables the driver for the Renesas Technology AG-AND 
21268 +         flash interface board (FROM_BOARD4)
21269 +
21270 +config MTD_NAND_PPCHAMELEONEVB
21271 +       tristate "NAND Flash device on PPChameleonEVB board"
21272 +       depends on PPCHAMELEONEVB && MTD_NAND
21273 +       help
21274 +         This enables the NAND flash driver on the PPChameleon EVB Board.      
21275 +
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
21280 +       help
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
21285 +         these devices.
21286 +
21287 +config MTD_NAND_DISKONCHIP_PROBE_ADVANCED
21288 +        bool "Advanced detection options for DiskOnChip"
21289 +        depends on MTD_NAND_DISKONCHIP
21290 +        help
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.
21294 +          Say 'N'.
21295 +
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
21299 +        default "0"
21300 +        ---help---
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.
21306 +
21307 +        (Note that on PowerPC, the normal probe will only check at
21308 +        0xE4000000.)
21309 +
21310 +        Normally, you should leave this set to zero, to allow the probe at
21311 +        the normal addresses.
21312 +
21313 +config MTD_NAND_DISKONCHIP_PROBE_HIGH
21314 +        bool "Probe high addresses"
21315 +        depends on MTD_NAND_DISKONCHIP_PROBE_ADVANCED
21316 +        help
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'.
21322 +
21323 +config MTD_NAND_DISKONCHIP_BBTWRITE
21324 +       bool "Allow BBT writes on DiskOnChip Millennium and 2000TSOP"
21325 +       depends on MTD_NAND_DISKONCHIP
21326 +       help
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".
21344 +endmenu
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
21349 @@ -1,10 +1,21 @@
21350  #
21351  # linux/drivers/nand/Makefile
21352  #
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 $
21355  
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
21363 +
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
21375 +
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
21381 @@ -0,0 +1,481 @@
21382 +/*
21383 + *  drivers/mtd/nand/au1550nd.c
21384 + *
21385 + *  Copyright (C) 2004 Embedded Edge, LLC
21386 + *
21387 + * $Id: au1550nd.c,v 1.8 2004/09/16 23:27:14 gleixner Exp $
21388 + *
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.
21392 + *
21393 + */
21394 +
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> 
21405 +#endif
21406 +#ifdef CONFIG_MIPS_DB1550
21407 +#include <asm/db1x00.h> 
21408 +#endif
21409 +
21410 +
21411 +/*
21412 + * MTD structure for NAND controller
21413 + */
21414 +static struct mtd_info *au1550_mtd = NULL;
21415 +static void __iomem *p_nand;
21416 +static int nand_width = 1; /* default x8*/
21417 +
21418 +/*
21419 + * Define partitions for flash device
21420 + */
21421 +const static struct mtd_partition partition_info[] = {
21422 +#ifdef CONFIG_MIPS_PB1550
21423 +#define NUM_PARTITIONS            2
21424 +       { 
21425 +               .name = "Pb1550 NAND FS 0",
21426 +               .offset = 0,
21427 +               .size = 8*1024*1024 
21428 +       },
21429 +       { 
21430 +               .name = "Pb1550 NAND FS 1",
21431 +               .offset =  MTDPART_OFS_APPEND,
21432 +               .size =    MTDPART_SIZ_FULL
21433 +       }
21434 +#endif
21435 +#ifdef CONFIG_MIPS_DB1550
21436 +#define NUM_PARTITIONS            2
21437 +       { 
21438 +               .name = "Db1550 NAND FS 0",
21439 +               .offset = 0,
21440 +               .size = 8*1024*1024 
21441 +       },
21442 +       { 
21443 +               .name = "Db1550 NAND FS 1",
21444 +               .offset =  MTDPART_OFS_APPEND,
21445 +               .size =    MTDPART_SIZ_FULL
21446 +       }
21447 +#endif
21448 +};
21449 +
21450 +
21451 +/**
21452 + * au_read_byte -  read one byte from the chip
21453 + * @mtd:       MTD device structure
21454 + *
21455 + *  read function for 8bit buswith
21456 + */
21457 +static u_char au_read_byte(struct mtd_info *mtd)
21458 +{
21459 +       struct nand_chip *this = mtd->priv;
21460 +       u_char ret = readb(this->IO_ADDR_R);
21461 +       au_sync();
21462 +       return ret;
21463 +}
21464 +
21465 +/**
21466 + * au_write_byte -  write one byte to the chip
21467 + * @mtd:       MTD device structure
21468 + * @byte:      pointer to data byte to write
21469 + *
21470 + *  write function for 8it buswith
21471 + */
21472 +static void au_write_byte(struct mtd_info *mtd, u_char byte)
21473 +{
21474 +       struct nand_chip *this = mtd->priv;
21475 +       writeb(byte, this->IO_ADDR_W);
21476 +       au_sync();
21477 +}
21478 +
21479 +/**
21480 + * au_read_byte16 -  read one byte endianess aware from the chip
21481 + * @mtd:       MTD device structure
21482 + *
21483 + *  read function for 16bit buswith with 
21484 + * endianess conversion
21485 + */
21486 +static u_char au_read_byte16(struct mtd_info *mtd)
21487 +{
21488 +       struct nand_chip *this = mtd->priv;
21489 +       u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
21490 +       au_sync();
21491 +       return ret;
21492 +}
21493 +
21494 +/**
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
21498 + *
21499 + *  write function for 16bit buswith with
21500 + * endianess conversion
21501 + */
21502 +static void au_write_byte16(struct mtd_info *mtd, u_char byte)
21503 +{
21504 +       struct nand_chip *this = mtd->priv;
21505 +       writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
21506 +       au_sync();
21507 +}
21508 +
21509 +/**
21510 + * au_read_word -  read one word from the chip
21511 + * @mtd:       MTD device structure
21512 + *
21513 + *  read function for 16bit buswith without 
21514 + * endianess conversion
21515 + */
21516 +static u16 au_read_word(struct mtd_info *mtd)
21517 +{
21518 +       struct nand_chip *this = mtd->priv;
21519 +       u16 ret = readw(this->IO_ADDR_R);
21520 +       au_sync();
21521 +       return ret;
21522 +}
21523 +
21524 +/**
21525 + * au_write_word -  write one word to the chip
21526 + * @mtd:       MTD device structure
21527 + * @word:      data word to write
21528 + *
21529 + *  write function for 16bit buswith without 
21530 + * endianess conversion
21531 + */
21532 +static void au_write_word(struct mtd_info *mtd, u16 word)
21533 +{
21534 +       struct nand_chip *this = mtd->priv;
21535 +       writew(word, this->IO_ADDR_W);
21536 +       au_sync();
21537 +}
21538 +
21539 +/**
21540 + * au_write_buf -  write buffer to chip
21541 + * @mtd:       MTD device structure
21542 + * @buf:       data buffer
21543 + * @len:       number of bytes to write
21544 + *
21545 + *  write function for 8bit buswith
21546 + */
21547 +static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
21548 +{
21549 +       int i;
21550 +       struct nand_chip *this = mtd->priv;
21551 +
21552 +       for (i=0; i<len; i++) {
21553 +               writeb(buf[i], this->IO_ADDR_W);
21554 +               au_sync();
21555 +       }
21556 +}
21557 +
21558 +/**
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
21563 + *
21564 + *  read function for 8bit buswith
21565 + */
21566 +static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
21567 +{
21568 +       int i;
21569 +       struct nand_chip *this = mtd->priv;
21570 +
21571 +       for (i=0; i<len; i++) {
21572 +               buf[i] = readb(this->IO_ADDR_R);
21573 +               au_sync();      
21574 +       }
21575 +}
21576 +
21577 +/**
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
21582 + *
21583 + *  verify function for 8bit buswith
21584 + */
21585 +static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
21586 +{
21587 +       int i;
21588 +       struct nand_chip *this = mtd->priv;
21589 +
21590 +       for (i=0; i<len; i++) {
21591 +               if (buf[i] != readb(this->IO_ADDR_R))
21592 +                       return -EFAULT;
21593 +               au_sync();
21594 +       }
21595 +
21596 +       return 0;
21597 +}
21598 +
21599 +/**
21600 + * au_write_buf16 -  write buffer to chip
21601 + * @mtd:       MTD device structure
21602 + * @buf:       data buffer
21603 + * @len:       number of bytes to write
21604 + *
21605 + *  write function for 16bit buswith
21606 + */
21607 +static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
21608 +{
21609 +       int i;
21610 +       struct nand_chip *this = mtd->priv;
21611 +       u16 *p = (u16 *) buf;
21612 +       len >>= 1;
21613 +       
21614 +       for (i=0; i<len; i++) {
21615 +               writew(p[i], this->IO_ADDR_W);
21616 +               au_sync();
21617 +       }
21618 +               
21619 +}
21620 +
21621 +/**
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
21626 + *
21627 + *  read function for 16bit buswith
21628 + */
21629 +static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
21630 +{
21631 +       int i;
21632 +       struct nand_chip *this = mtd->priv;
21633 +       u16 *p = (u16 *) buf;
21634 +       len >>= 1;
21635 +
21636 +       for (i=0; i<len; i++) {
21637 +               p[i] = readw(this->IO_ADDR_R);
21638 +               au_sync();
21639 +       }
21640 +}
21641 +
21642 +/**
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
21647 + *
21648 + *  verify function for 16bit buswith
21649 + */
21650 +static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
21651 +{
21652 +       int i;
21653 +       struct nand_chip *this = mtd->priv;
21654 +       u16 *p = (u16 *) buf;
21655 +       len >>= 1;
21656 +
21657 +       for (i=0; i<len; i++) {
21658 +               if (p[i] != readw(this->IO_ADDR_R))
21659 +                       return -EFAULT;
21660 +               au_sync();
21661 +       }
21662 +       return 0;
21663 +}
21664 +
21665 +
21666 +static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
21667 +{
21668 +       register struct nand_chip *this = mtd->priv;
21669 +
21670 +       switch(cmd){
21671 +
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;
21674 +
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 */
21680 +               udelay(1); 
21681 +               break;
21682 +
21683 +       case NAND_CTL_SETNCE: 
21684 +               /* assert (force assert) chip enable */
21685 +               au_writel(au_readl(MEM_STNDCTL) | 0x20 , MEM_STNDCTL);
21686 +               break;
21687 +
21688 +       case NAND_CTL_CLRNCE: 
21689 +               /* deassert chip enable */
21690 +               au_writel(au_readl(MEM_STNDCTL) & ~0x20 , MEM_STNDCTL);
21691 +               break;
21692 +       }
21693 +
21694 +       this->IO_ADDR_R = this->IO_ADDR_W;
21695 +       
21696 +       /* Drain the writebuffer */
21697 +       au_sync();
21698 +}
21699 +
21700 +int au1550_device_ready(struct mtd_info *mtd)
21701 +{
21702 +       int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;
21703 +       au_sync();
21704 +       return ret;
21705 +}
21706 +
21707 +/*
21708 + * Main initialization routine
21709 + */
21710 +int __init au1550_init (void)
21711 +{
21712 +       struct nand_chip *this;
21713 +       u16 boot_swapboot = 0; /* default value */
21714 +       u32 mem_time;
21715 +       int retval;
21716 +
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");
21722 +               return -ENOMEM;
21723 +       }
21724 +
21725 +       /* Get pointer to private data */
21726 +       this = (struct nand_chip *) (&au1550_mtd[1]);
21727 +
21728 +       /* Initialize structures */
21729 +       memset((char *) au1550_mtd, 0, sizeof(struct mtd_info));
21730 +       memset((char *) this, 0, sizeof(struct nand_chip));
21731 +
21732 +       /* Link the private data with the MTD structure */
21733 +       au1550_mtd->priv = this;
21734 +
21735 +       /* disable interrupts */
21736 +       au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL);
21737 +
21738 +       /* disable NAND boot */
21739 +       au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL);
21740 +
21741 +#ifdef CONFIG_MIPS_PB1550
21742 +       /* set gpio206 high */
21743 +       au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR);
21744 +
21745 +       boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) | 
21746 +               ((bcsr->status >> 6)  & 0x1);
21747 +       switch (boot_swapboot) {
21748 +               case 0:
21749 +               case 2:
21750 +               case 8:
21751 +               case 0xC:
21752 +               case 0xD:
21753 +                       /* x16 NAND Flash */
21754 +                       nand_width = 0;
21755 +                       break;
21756 +               case 1:
21757 +               case 9:
21758 +               case 3:
21759 +               case 0xE:
21760 +               case 0xF:
21761 +                       /* x8 NAND Flash */
21762 +                       nand_width = 1;
21763 +                       break;
21764 +               default:
21765 +                       printk("Pb1550 NAND: bad boot:swap\n");
21766 +                       retval = -EINVAL;
21767 +                       goto outmem;
21768 +       }
21769 +
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);
21774 +       au_sync();
21775 +
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), 
21780 +                       MEM_STADDR1);
21781 +       au_sync();
21782 +#endif
21783 +
21784 +#ifdef CONFIG_MIPS_DB1550
21785 +       /* FIXME: should be done by the bootloader
21786 +        *  
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
21791 +       */
21792 +       au_writel(0x00400105, MEM_STCFG1);
21793 +       au_writel(0x00007774, MEM_STTIME1);
21794 +       au_writel(0x12003FFF, MEM_STADDR1);
21795 +#endif
21796 +
21797 +       p_nand = (void __iomem *)ioremap(NAND_PHYS_ADDR, 0x1000);
21798 +
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;
21805 +
21806 +       this->options = NAND_NO_AUTOINCR;
21807 +
21808 +       if (!nand_width)
21809 +               this->options |= NAND_BUSWIDTH_16;
21810 +
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;
21818 +
21819 +       /* Scan to find existence of the device */
21820 +       if (nand_scan (au1550_mtd, 1)) {
21821 +               retval = -ENXIO;
21822 +               goto outio;
21823 +       }
21824 +
21825 +       /* Register the partitions */
21826 +       add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS);
21827 +
21828 +       return 0;
21829 +
21830 + outio:
21831 +       iounmap ((void *)p_nand);
21832 +       
21833 + outmem:
21834 +       kfree (au1550_mtd);
21835 +       return retval;
21836 +}
21837 +
21838 +module_init(au1550_init);
21839 +
21840 +/*
21841 + * Clean up routine
21842 + */
21843 +#ifdef MODULE
21844 +static void __exit au1550_cleanup (void)
21845 +{
21846 +       struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1];
21847 +
21848 +       /* Release resources, unregister device */
21849 +       nand_release (au1550_mtd);
21850 +
21851 +       /* Free the MTD device structure */
21852 +       kfree (au1550_mtd);
21853 +
21854 +       /* Unmap */
21855 +       iounmap ((void *)p_nand);
21856 +}
21857 +module_exit(au1550_cleanup);
21858 +#endif
21859 +
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
21867 @@ -6,7 +6,7 @@
21868   *  Derived from drivers/mtd/spia.c
21869   *      Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
21870   * 
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 $
21873   *
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
21876 @@ -15,7 +15,7 @@
21877   *  Overview:
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.
21882   *
21883   *
21884   *     02-12-2002 TG   Cleanup of module params
21885 @@ -44,19 +44,11 @@
21886   */
21887  static struct mtd_info *autcpu12_mtd = NULL;
21888  
21889 -/*
21890 - * Module stuff
21891 - */
21892 -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
21893 -#define autcpu12_init init_module
21894 -#define autcpu12_cleanup cleanup_module
21895 -#endif
21896 -
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;
21903  
21904  #ifdef MODULE
21905  MODULE_PARM(autcpu12_fio_pbase, "i");
21906 @@ -71,42 +63,40 @@
21907  /*
21908   * Define partitions for flash devices
21909   */
21910 -extern struct nand_oobinfo jffs2_oobinfo;
21911 -
21912  static struct mtd_partition partition_info16k[] = {
21913 -       { .name = "AUTCPU12 flash partition 1",
21914 -         .offset  = 0,
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",
21920 +         .offset       = 0,
21921 +         .size         = 8 * SZ_1M },
21922 +       { .name         = "AUTCPU12 flash partition 2",
21923 +         .offset       = 8 * SZ_1M,
21924 +         .size         = 8 * SZ_1M },
21925  };
21926  
21927  static struct mtd_partition partition_info32k[] = {
21928 -       { .name = "AUTCPU12 flash partition 1",
21929 -         .offset  = 0,
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",
21935 +         .offset       = 0,
21936 +         .size         = 8 * SZ_1M },
21937 +       { .name         = "AUTCPU12 flash partition 2",
21938 +         .offset       = 8 * SZ_1M,
21939 +         .size         = 24 * SZ_1M },
21940  };
21941  
21942  static struct mtd_partition partition_info64k[] = {
21943 -       { .name = "AUTCPU12 flash partition 1",
21944 -         .offset  = 0,
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",
21950 +         .offset       = 0,
21951 +         .size         = 16 * SZ_1M },
21952 +       { .name         = "AUTCPU12 flash partition 2",
21953 +         .offset       = 16 * SZ_1M,
21954 +         .size         = 48 * SZ_1M },
21955  };
21956  
21957  static struct mtd_partition partition_info128k[] = {
21958 -       { .name = "AUTCPU12 flash partition 1",
21959 -         .offset  = 0,
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",
21965 +         .offset       = 0,
21966 +         .size         = 16 * SZ_1M },
21967 +       { .name         = "AUTCPU12 flash partition 2",
21968 +         .offset       = 16 * SZ_1M,
21969 +         .size         = 112 * SZ_1M },
21970  };
21971  
21972  #define NUM_PARTITIONS16K 2
21973 @@ -116,7 +106,7 @@
21974  /* 
21975   *     hardware specific access to control-lines
21976  */
21977 -void autcpu12_hwcontrol(int cmd)
21978 +static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd)
21979  {
21980  
21981         switch(cmd){
21982 @@ -135,12 +125,13 @@
21983  /*
21984  *      read device ready pin
21985  */
21986 -int autcpu12_device_ready(void)
21987 +int autcpu12_device_ready(struct mtd_info *mtd)
21988  {
21989  
21990         return ( (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0;
21991  
21992  }
21993 +
21994  /*
21995   * Main initialization routine
21996   */
21997 @@ -159,7 +150,7 @@
21998         }
21999  
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");
22005                 err = -EIO;
22006 @@ -185,20 +176,18 @@
22007         this->chip_delay = 20;          
22008         this->eccmode = NAND_ECC_SOFT;
22009  
22010 +       /* Enable the following for a flash based bad block table */
22011 +       /*
22012 +       this->options = NAND_USE_FLASH_BBT;
22013 +       */
22014 +       this->options = NAND_USE_FLASH_BBT;
22015 +       
22016         /* Scan to find existance of the device */
22017 -       if (nand_scan (autcpu12_mtd)) {
22018 +       if (nand_scan (autcpu12_mtd, 1)) {
22019                 err = -ENXIO;
22020                 goto out_ior;
22021         }
22022 -
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");
22027 -               err = -ENOMEM;
22028 -               goto out_ior;
22029 -       }
22030 -
22031 +       
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 @@
22036                 default: {
22037                         printk ("Unsupported SmartMedia device\n"); 
22038                         err = -ENXIO;
22039 -                       goto out_buf;
22040 +                       goto out_ior;
22041                 }
22042         }
22043         goto out;
22044  
22045 -out_buf:
22046 -       kfree (this->data_buf);    
22047  out_ior:
22048         iounmap((void *)autcpu12_fio_base);
22049  out_mtd:
22050 @@ -231,20 +218,12 @@
22051  #ifdef MODULE
22052  static void __exit autcpu12_cleanup (void)
22053  {
22054 -       struct nand_chip *this = (struct nand_chip *) &autcpu12_mtd[1];
22055 -
22056 -       /* Unregister partitions */
22057 -       del_mtd_partitions(autcpu12_mtd);
22058 -       
22059 -       /* Unregister the device */
22060 -       del_mtd_device (autcpu12_mtd);
22061 -
22062 -       /* Free internal data buffers */
22063 -       kfree (this->data_buf);
22064 +       /* Release resources, unregister device */
22065 +       nand_release (autcpu12_mtd);
22066  
22067         /* unmap physical adress */
22068         iounmap((void *)autcpu12_fio_base);
22069 -
22070 +       
22071         /* Free the MTD device structure */
22072         kfree (autcpu12_mtd);
22073  }
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
22078 @@ -0,0 +1,1637 @@
22079 +/* 
22080 + * drivers/mtd/nand/diskonchip.c
22081 + *
22082 + * (C) 2003 Red Hat, Inc.
22083 + * (C) 2004 Dan Brown <dan_brown@ieee.org>
22084 + * (C) 2004 Kalev Lember <kalev@smartlink.ee>
22085 + *
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>
22089 + *
22090 + * Interface to generic NAND code for M-Systems DiskOnChip devices
22091 + *
22092 + * $Id: diskonchip.c,v 1.35 2004/09/16 23:27:14 gleixner Exp $
22093 + */
22094 +
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>
22100 +
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>
22107 +
22108 +/* Where to look for the devices? */
22109 +#ifndef CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS
22110 +#define CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 0
22111 +#endif
22112 +
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__)
22129 +       0xe4000000,
22130 +#elif defined(CONFIG_MOMENCO_OCELOT)
22131 +       0x2f000000,
22132 +        0xff000000,
22133 +#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
22134 +        0xff000000,
22135 +##else
22136 +#warning Unknown architecture for DiskOnChip. No default probe locations defined
22137 +#endif
22138 +       0xffffffff };
22139 +
22140 +static struct mtd_info *doclist = NULL;
22141 +
22142 +struct doc_priv {
22143 +       void __iomem *virtadr;
22144 +       unsigned long physadr;
22145 +       u_char ChipID;
22146 +       u_char CDSNControl;
22147 +       int chips_per_floor; /* The number of chips detected on each floor */
22148 +       int curfloor;
22149 +       int curchip;
22150 +       int mh0_page;
22151 +       int mh1_page;
22152 +       struct mtd_info *nextdoc;
22153 +};
22154 +
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
22157 +   silly. */
22158 +#define MAX_MEDIAHEADER_SCAN 8
22159 +
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 };
22166 +
22167 +#define INFTL_BBT_RESERVED_BLOCKS 4
22168 +
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)
22172 +
22173 +static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd);
22174 +static void doc200x_select_chip(struct mtd_info *mtd, int chip);
22175 +
22176 +static int debug=0;
22177 +MODULE_PARM(debug, "i");
22178 +
22179 +static int try_dword=1;
22180 +MODULE_PARM(try_dword, "i");
22181 +
22182 +static int no_ecc_failures=0;
22183 +MODULE_PARM(no_ecc_failures, "i");
22184 +
22185 +#ifdef CONFIG_MTD_PARTITIONS
22186 +static int no_autopart=0;
22187 +MODULE_PARM(no_autopart, "i");
22188 +#endif
22189 +
22190 +#ifdef MTD_NAND_DISKONCHIP_BBTWRITE
22191 +static int inftl_bbt_write=1;
22192 +#else
22193 +static int inftl_bbt_write=0;
22194 +#endif
22195 +MODULE_PARM(inftl_bbt_write, "i");
22196 +
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");
22200 +
22201 +static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
22202 +{
22203 +       volatile char dummy;
22204 +       int i;
22205 +       
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);
22211 +               else
22212 +                       dummy = ReadDOC(doc->virtadr, DOCStatus);
22213 +       }
22214 +       
22215 +}
22216 +
22217 +#define CDSN_CTRL_FR_B_MASK    (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)
22218 +
22219 +/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
22220 +static int _DoC_WaitReady(struct doc_priv *doc)
22221 +{
22222 +        void __iomem *docptr = doc->virtadr;
22223 +       unsigned long timeo = jiffies + (HZ * 10);
22224 +
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");
22231 +                               return -EIO;
22232 +                       }
22233 +                       udelay(1);
22234 +                       cond_resched();
22235 +               }
22236 +       } else {
22237 +               while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
22238 +                       if (time_after(jiffies, timeo)) {
22239 +                               printk("_DoC_WaitReady timed out.\n");
22240 +                               return -EIO;
22241 +                       }
22242 +                       udelay(1);
22243 +                       cond_resched();
22244 +               }
22245 +       }
22246 +
22247 +       return 0;
22248 +}
22249 +
22250 +static inline int DoC_WaitReady(struct doc_priv *doc)
22251 +{
22252 +        void __iomem *docptr = doc->virtadr;
22253 +       int ret = 0;
22254 +
22255 +       if (DoC_is_MillenniumPlus(doc)) {
22256 +               DoC_Delay(doc, 4);
22257 +
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);
22261 +       } else {
22262 +               DoC_Delay(doc, 4);
22263 +
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);
22268 +       }
22269 +
22270 +       if(debug) printk("DoC_WaitReady OK\n");
22271 +       return ret;
22272 +}
22273 +
22274 +static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
22275 +{
22276 +       struct nand_chip *this = mtd->priv;
22277 +       struct doc_priv *doc = (void *)this->priv;
22278 +        void __iomem *docptr = doc->virtadr;
22279 +
22280 +       if(debug)printk("write_byte %02x\n", datum);
22281 +       WriteDOC(datum, docptr, CDSNSlowIO);
22282 +       WriteDOC(datum, docptr, 2k_CDSN_IO);
22283 +}
22284 +
22285 +static u_char doc2000_read_byte(struct mtd_info *mtd)
22286 +{
22287 +       struct nand_chip *this = mtd->priv;
22288 +       struct doc_priv *doc = (void *)this->priv;
22289 +        void __iomem *docptr = doc->virtadr;
22290 +       u_char ret;
22291 +
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);
22296 +       return ret;
22297 +}
22298 +
22299 +static void doc2000_writebuf(struct mtd_info *mtd, 
22300 +                            const u_char *buf, int len)
22301 +{
22302 +       struct nand_chip *this = mtd->priv;
22303 +       struct doc_priv *doc = (void *)this->priv;
22304 +        void __iomem *docptr = doc->virtadr;
22305 +       int i;
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]);
22311 +       }
22312 +       if (debug) printk("\n");
22313 +}
22314 +
22315 +static void doc2000_readbuf(struct mtd_info *mtd, 
22316 +                           u_char *buf, int len)
22317 +{
22318 +       struct nand_chip *this = mtd->priv;
22319 +       struct doc_priv *doc = (void *)this->priv;
22320 +        void __iomem *docptr = doc->virtadr;
22321 +       int i;
22322 +
22323 +       if (debug)printk("readbuf of %d bytes: ", len);
22324 +
22325 +       for (i=0; i < len; i++) {
22326 +               buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i);
22327 +       }
22328 +}
22329 +
22330 +static void doc2000_readbuf_dword(struct mtd_info *mtd, 
22331 +                           u_char *buf, int len)
22332 +{
22333 +       struct nand_chip *this = mtd->priv;
22334 +       struct doc_priv *doc = (void *)this->priv;
22335 +        void __iomem *docptr = doc->virtadr;
22336 +       int i;
22337 +
22338 +       if (debug) printk("readbuf_dword of %d bytes: ", len);
22339 +
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);
22343 +               }
22344 +       } else {
22345 +               for (i=0; i < len; i+=4) {
22346 +                       *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i);
22347 +               }
22348 +       }
22349 +}
22350 +
22351 +static int doc2000_verifybuf(struct mtd_info *mtd, 
22352 +                             const u_char *buf, int len)
22353 +{
22354 +       struct nand_chip *this = mtd->priv;
22355 +       struct doc_priv *doc = (void *)this->priv;
22356 +        void __iomem *docptr = doc->virtadr;
22357 +       int i;
22358 +
22359 +       for (i=0; i < len; i++)
22360 +               if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO))
22361 +                       return -EFAULT;
22362 +       return 0;
22363 +}
22364 +
22365 +static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
22366 +{
22367 +       struct nand_chip *this = mtd->priv;
22368 +       struct doc_priv *doc = (void *)this->priv;
22369 +       uint16_t ret;
22370 +
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);
22378 +
22379 +       ret = this->read_byte(mtd) << 8;
22380 +       ret |= this->read_byte(mtd);
22381 +
22382 +       if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) {
22383 +               /* First chip probe. See if we get same results by 32-bit access */
22384 +               union {
22385 +                       uint32_t dword;
22386 +                       uint8_t byte[4];
22387 +               } ident;
22388 +               void __iomem *docptr = doc->virtadr;
22389 +
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);
22396 +
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;
22401 +               }
22402 +       }
22403 +               
22404 +       return ret;
22405 +}
22406 +
22407 +static void __init doc2000_count_chips(struct mtd_info *mtd)
22408 +{
22409 +       struct nand_chip *this = mtd->priv;
22410 +       struct doc_priv *doc = (void *)this->priv;
22411 +       uint16_t mfrid;
22412 +       int i;
22413 +
22414 +       /* Max 4 chips per floor on DiskOnChip 2000 */
22415 +       doc->chips_per_floor = 4;
22416 +
22417 +       /* Find out what the first chip is */
22418 +       mfrid = doc200x_ident_chip(mtd, 0);
22419 +
22420 +       /* Find how many chips in each floor. */
22421 +       for (i = 1; i < 4; i++) {
22422 +               if (doc200x_ident_chip(mtd, i) != mfrid)
22423 +                       break;
22424 +       }
22425 +       doc->chips_per_floor = i;
22426 +       printk(KERN_DEBUG "Detected %d chips per floor.\n", i);
22427 +}
22428 +
22429 +static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
22430 +{
22431 +       struct doc_priv *doc = (void *)this->priv;
22432 +
22433 +       int status;
22434 +       
22435 +       DoC_WaitReady(doc);
22436 +       this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
22437 +       DoC_WaitReady(doc);
22438 +       status = (int)this->read_byte(mtd);
22439 +
22440 +       return status;
22441 +}
22442 +
22443 +static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
22444 +{
22445 +       struct nand_chip *this = mtd->priv;
22446 +       struct doc_priv *doc = (void *)this->priv;
22447 +        void __iomem *docptr = doc->virtadr;
22448 +
22449 +       WriteDOC(datum, docptr, CDSNSlowIO);
22450 +       WriteDOC(datum, docptr, Mil_CDSN_IO);
22451 +       WriteDOC(datum, docptr, WritePipeTerm);
22452 +}
22453 +
22454 +static u_char doc2001_read_byte(struct mtd_info *mtd)
22455 +{
22456 +       struct nand_chip *this = mtd->priv;
22457 +       struct doc_priv *doc = (void *)this->priv;
22458 +        void __iomem *docptr = doc->virtadr;
22459 +
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);
22466 +}
22467 +
22468 +static void doc2001_writebuf(struct mtd_info *mtd, 
22469 +                            const u_char *buf, int len)
22470 +{
22471 +       struct nand_chip *this = mtd->priv;
22472 +       struct doc_priv *doc = (void *)this->priv;
22473 +        void __iomem *docptr = doc->virtadr;
22474 +       int i;
22475 +
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);
22480 +}
22481 +
22482 +static void doc2001_readbuf(struct mtd_info *mtd, 
22483 +                           u_char *buf, int len)
22484 +{
22485 +       struct nand_chip *this = mtd->priv;
22486 +       struct doc_priv *doc = (void *)this->priv;
22487 +        void __iomem *docptr = doc->virtadr;
22488 +       int i;
22489 +
22490 +       /* Start read pipeline */
22491 +       ReadDOC(docptr, ReadPipeInit);
22492 +
22493 +       for (i=0; i < len-1; i++)
22494 +               buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff));
22495 +
22496 +       /* Terminate read pipeline */
22497 +       buf[i] = ReadDOC(docptr, LastDataRead);
22498 +}
22499 +
22500 +static int doc2001_verifybuf(struct mtd_info *mtd, 
22501 +                            const u_char *buf, int len)
22502 +{
22503 +       struct nand_chip *this = mtd->priv;
22504 +       struct doc_priv *doc = (void *)this->priv;
22505 +        void __iomem *docptr = doc->virtadr;
22506 +       int i;
22507 +
22508 +       /* Start read pipeline */
22509 +       ReadDOC(docptr, ReadPipeInit);
22510 +
22511 +       for (i=0; i < len-1; i++)
22512 +               if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
22513 +                       ReadDOC(docptr, LastDataRead);
22514 +                       return i;
22515 +               }
22516 +       if (buf[i] != ReadDOC(docptr, LastDataRead))
22517 +               return i;
22518 +       return 0;
22519 +}
22520 +
22521 +static u_char doc2001plus_read_byte(struct mtd_info *mtd)
22522 +{
22523 +       struct nand_chip *this = mtd->priv;
22524 +       struct doc_priv *doc = (void *)this->priv;
22525 +        void __iomem *docptr = doc->virtadr;
22526 +       u_char ret;
22527 +
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);
22532 +       return ret;
22533 +}
22534 +
22535 +static void doc2001plus_writebuf(struct mtd_info *mtd, 
22536 +                            const u_char *buf, int len)
22537 +{
22538 +       struct nand_chip *this = mtd->priv;
22539 +       struct doc_priv *doc = (void *)this->priv;
22540 +        void __iomem *docptr = doc->virtadr;
22541 +       int i;
22542 +
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]);
22548 +       }
22549 +       if (debug) printk("\n");
22550 +}
22551 +
22552 +static void doc2001plus_readbuf(struct mtd_info *mtd, 
22553 +                           u_char *buf, int len)
22554 +{
22555 +       struct nand_chip *this = mtd->priv;
22556 +       struct doc_priv *doc = (void *)this->priv;
22557 +        void __iomem *docptr = doc->virtadr;
22558 +       int i;
22559 +
22560 +       if (debug)printk("readbuf of %d bytes: ", len);
22561 +
22562 +       /* Start read pipeline */
22563 +       ReadDOC(docptr, Mplus_ReadPipeInit);
22564 +       ReadDOC(docptr, Mplus_ReadPipeInit);
22565 +
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]);
22570 +       }
22571 +
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");
22580 +}
22581 +
22582 +static int doc2001plus_verifybuf(struct mtd_info *mtd, 
22583 +                            const u_char *buf, int len)
22584 +{
22585 +       struct nand_chip *this = mtd->priv;
22586 +       struct doc_priv *doc = (void *)this->priv;
22587 +        void __iomem *docptr = doc->virtadr;
22588 +       int i;
22589 +
22590 +       if (debug)printk("verifybuf of %d bytes: ", len);
22591 +
22592 +       /* Start read pipeline */
22593 +       ReadDOC(docptr, Mplus_ReadPipeInit);
22594 +       ReadDOC(docptr, Mplus_ReadPipeInit);
22595 +
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);
22600 +                       return i;
22601 +               }
22602 +       if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead))
22603 +               return len-2;
22604 +       if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead))
22605 +               return len-1;
22606 +       return 0;
22607 +}
22608 +
22609 +static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
22610 +{
22611 +       struct nand_chip *this = mtd->priv;
22612 +       struct doc_priv *doc = (void *)this->priv;
22613 +        void __iomem *docptr = doc->virtadr;
22614 +       int floor = 0;
22615 +
22616 +       if(debug)printk("select chip (%d)\n", chip);
22617 +
22618 +       if (chip == -1) {
22619 +               /* Disable flash internally */
22620 +               WriteDOC(0, docptr, Mplus_FlashSelect);
22621 +               return;
22622 +       }
22623 +
22624 +       floor = chip / doc->chips_per_floor;
22625 +       chip -= (floor *  doc->chips_per_floor);
22626 +
22627 +       /* Assert ChipEnable and deassert WriteProtect */
22628 +       WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect);
22629 +       this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
22630 +
22631 +       doc->curchip = chip;
22632 +       doc->curfloor = floor;
22633 +}
22634 +
22635 +static void doc200x_select_chip(struct mtd_info *mtd, int chip)
22636 +{
22637 +       struct nand_chip *this = mtd->priv;
22638 +       struct doc_priv *doc = (void *)this->priv;
22639 +        void __iomem *docptr = doc->virtadr;
22640 +       int floor = 0;
22641 +
22642 +       if(debug)printk("select chip (%d)\n", chip);
22643 +
22644 +       if (chip == -1)
22645 +               return;
22646 +
22647 +       floor = chip / doc->chips_per_floor;
22648 +       chip -= (floor *  doc->chips_per_floor);
22649 +
22650 +       /* 11.4.4 -- deassert CE before changing chip */
22651 +       doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE);
22652 +
22653 +       WriteDOC(floor, docptr, FloorSelect);
22654 +       WriteDOC(chip, docptr, CDSNDeviceSelect);
22655 +
22656 +       doc200x_hwcontrol(mtd, NAND_CTL_SETNCE);
22657 +
22658 +       doc->curchip = chip;
22659 +       doc->curfloor = floor;
22660 +}
22661 +
22662 +static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd)
22663 +{
22664 +       struct nand_chip *this = mtd->priv;
22665 +       struct doc_priv *doc = (void *)this->priv;
22666 +        void __iomem *docptr = doc->virtadr;
22667 +
22668 +       switch(cmd) {
22669 +       case NAND_CTL_SETNCE:
22670 +               doc->CDSNControl |= CDSN_CTRL_CE;
22671 +               break;
22672 +       case NAND_CTL_CLRNCE:
22673 +               doc->CDSNControl &= ~CDSN_CTRL_CE;
22674 +               break;
22675 +       case NAND_CTL_SETCLE:
22676 +               doc->CDSNControl |= CDSN_CTRL_CLE;
22677 +               break;
22678 +       case NAND_CTL_CLRCLE:
22679 +               doc->CDSNControl &= ~CDSN_CTRL_CLE;
22680 +               break;
22681 +       case NAND_CTL_SETALE:
22682 +               doc->CDSNControl |= CDSN_CTRL_ALE;
22683 +               break;
22684 +       case NAND_CTL_CLRALE:
22685 +               doc->CDSNControl &= ~CDSN_CTRL_ALE;
22686 +               break;
22687 +       case NAND_CTL_SETWP:
22688 +               doc->CDSNControl |= CDSN_CTRL_WP;
22689 +               break;
22690 +       case NAND_CTL_CLRWP:
22691 +               doc->CDSNControl &= ~CDSN_CTRL_WP;
22692 +               break;
22693 +       }
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);
22698 +}
22699 +
22700 +static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
22701 +{
22702 +       struct nand_chip *this = mtd->priv;
22703 +       struct doc_priv *doc = (void *)this->priv;
22704 +        void __iomem *docptr = doc->virtadr;
22705 +
22706 +       /*
22707 +        * Must terminate write pipeline before sending any commands
22708 +        * to the device.
22709 +        */
22710 +       if (command == NAND_CMD_PAGEPROG) {
22711 +               WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
22712 +               WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
22713 +       }
22714 +
22715 +       /*
22716 +        * Write out the command to the device.
22717 +        */
22718 +       if (command == NAND_CMD_SEQIN) {
22719 +               int readcmd;
22720 +
22721 +               if (column >= mtd->oobblock) {
22722 +                       /* OOB area */
22723 +                       column -= mtd->oobblock;
22724 +                       readcmd = NAND_CMD_READOOB;
22725 +               } else if (column < 256) {
22726 +                       /* First 256 bytes --> READ0 */
22727 +                       readcmd = NAND_CMD_READ0;
22728 +               } else {
22729 +                       column -= 256;
22730 +                       readcmd = NAND_CMD_READ1;
22731 +               }
22732 +               WriteDOC(readcmd, docptr, Mplus_FlashCmd);
22733 +       }
22734 +       WriteDOC(command, docptr, Mplus_FlashCmd);
22735 +       WriteDOC(0, docptr, Mplus_WritePipeTerm);
22736 +       WriteDOC(0, docptr, Mplus_WritePipeTerm);
22737 +
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)
22743 +                               column >>= 1;
22744 +                       WriteDOC(column, docptr, Mplus_FlashAddress);
22745 +               }
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");
22753 +                       }
22754 +               }
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);
22760 +       }
22761 +
22762 +       /* 
22763 +        * program and erase have their own busy handlers
22764 +        * status and sequential in needs no delay
22765 +       */
22766 +       switch (command) {
22767 +
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:
22773 +               return;
22774 +
22775 +       case NAND_CMD_RESET:
22776 +               if (this->dev_ready)
22777 +                       break;
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));
22783 +               return;
22784 +
22785 +       /* This applies to read commands */
22786 +       default:
22787 +               /* 
22788 +                * If we don't have access to the busy pin, we apply the given
22789 +                * command delay
22790 +               */
22791 +               if (!this->dev_ready) {
22792 +                       udelay (this->chip_delay);
22793 +                       return;
22794 +               }
22795 +       }
22796 +
22797 +       /* Apply this short delay always to ensure that we do wait tWB in
22798 +        * any case on any machine. */
22799 +       ndelay (100);
22800 +       /* wait until command is processed */
22801 +       while (!this->dev_ready(mtd));
22802 +}
22803 +
22804 +static int doc200x_dev_ready(struct mtd_info *mtd)
22805 +{
22806 +       struct nand_chip *this = mtd->priv;
22807 +       struct doc_priv *doc = (void *)this->priv;
22808 +        void __iomem *docptr = doc->virtadr;
22809 +
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) {
22814 +                       if(debug)
22815 +                               printk("not ready\n");
22816 +                       return 0;
22817 +               }
22818 +               if (debug)printk("was ready\n");
22819 +               return 1;
22820 +       } else {
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)) {
22824 +                       if(debug)
22825 +                               printk("not ready\n");
22826 +                       return 0;
22827 +               }
22828 +               /* 11.4.2 -- Must NOP twice if it's ready */
22829 +               DoC_Delay(doc, 2);
22830 +               if (debug)printk("was ready\n");
22831 +               return 1;
22832 +       }
22833 +}
22834 +
22835 +static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
22836 +{
22837 +       /* This is our last resort if we couldn't find or create a BBT.  Just
22838 +          pretend all blocks are good. */
22839 +       return 0;
22840 +}
22841 +
22842 +static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
22843 +{
22844 +       struct nand_chip *this = mtd->priv;
22845 +       struct doc_priv *doc = (void *)this->priv;
22846 +        void __iomem *docptr = doc->virtadr;
22847 +
22848 +       /* Prime the ECC engine */
22849 +       switch(mode) {
22850 +       case NAND_ECC_READ:
22851 +               WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
22852 +               WriteDOC(DOC_ECC_EN, docptr, ECCConf);
22853 +               break;
22854 +       case NAND_ECC_WRITE:
22855 +               WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
22856 +               WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
22857 +               break;
22858 +       }
22859 +}
22860 +
22861 +static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
22862 +{
22863 +       struct nand_chip *this = mtd->priv;
22864 +       struct doc_priv *doc = (void *)this->priv;
22865 +        void __iomem *docptr = doc->virtadr;
22866 +
22867 +       /* Prime the ECC engine */
22868 +       switch(mode) {
22869 +       case NAND_ECC_READ:
22870 +               WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
22871 +               WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
22872 +               break;
22873 +       case NAND_ECC_WRITE:
22874 +               WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
22875 +               WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
22876 +               break;
22877 +       }
22878 +}
22879 +
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)
22883 +{
22884 +       struct nand_chip *this = mtd->priv;
22885 +       struct doc_priv *doc = (void *)this->priv;
22886 +        void __iomem *docptr = doc->virtadr;
22887 +       int i;
22888 +       int emptymatch = 1;
22889 +
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);
22901 +       } else {
22902 +               WriteDOC(0, docptr, NOP);
22903 +               WriteDOC(0, docptr, NOP);
22904 +               WriteDOC(0, docptr, NOP);
22905 +       }
22906 +
22907 +       for (i = 0; i < 6; i++) {
22908 +               if (DoC_is_MillenniumPlus(doc))
22909 +                       ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i);
22910 +               else 
22911 +                       ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
22912 +               if (ecc_code[i] != empty_write_ecc[i])
22913 +                       emptymatch = 0;
22914 +       }
22915 +       if (DoC_is_MillenniumPlus(doc))
22916 +               WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
22917 +       else
22918 +               WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
22919 +#if 0
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;
22927 +                       emptymatch = 0;
22928 +                       break;
22929 +               }
22930 +       }
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);
22935 +#endif
22936 +       return 0;
22937 +}
22938 +
22939 +static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
22940 +{
22941 +       int i, ret = 0;
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;
22947 +       
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);
22957 +       } else {
22958 +               dummy = ReadDOC(docptr, ECCConf);
22959 +               dummy = ReadDOC(docptr, ECCConf);
22960 +               dummy = ReadDOC(docptr, ECCConf);
22961 +       }
22962 +       
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);
22968 +                       else
22969 +                               calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
22970 +                       if (calc_ecc[i] != empty_read_syndrome[i])
22971 +                               emptymatch = 0;
22972 +               }
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;
22978 +                               emptymatch = 0;
22979 +                               break;
22980 +                       }
22981 +               }
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;
22989 +                               emptymatch = 0;
22990 +                               break;
22991 +                       }
22992 +               }
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);
22998 +               if (ret > 0)
22999 +                       printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
23000 +       }       
23001 +       if (DoC_is_MillenniumPlus(doc))
23002 +               WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
23003 +       else
23004 +               WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
23005 +       if (no_ecc_failures && (ret == -1)) {
23006 +               printk(KERN_ERR "suppressing ECC failure\n");
23007 +               ret = 0;
23008 +       }
23009 +       return ret;
23010 +}
23011 +               
23012 +//u_char mydatabuf[528];
23013 +
23014 +static struct nand_oobinfo doc200x_oobinfo = {
23015 +        .useecc = MTD_NANDECC_AUTOPLACE,
23016 +        .eccbytes = 6,
23017 +        .eccpos = {0, 1, 2, 3, 4, 5},
23018 +        .oobfree = { {8, 8} }
23019 +};
23020
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)
23029 +{
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);
23033 +       int ret;
23034 +       size_t retlen;
23035 +
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;
23040 +               if (ret) {
23041 +                       printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n",
23042 +                               offs);
23043 +               }
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;
23049 +                       continue;
23050 +               }
23051 +               doc->mh1_page = offs >> this->page_shift;
23052 +               return 2;
23053 +       }
23054 +       if (doc->mh0_page == -1) {
23055 +               printk(KERN_WARNING "DiskOnChip %s Media Header not found.\n", id);
23056 +               return 0;
23057 +       }
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");
23065 +               return 0;
23066 +       }
23067 +       return 1;
23068 +}
23069 +
23070 +static inline int __init nftl_partscan(struct mtd_info *mtd,
23071 +                               struct mtd_partition *parts)
23072 +{
23073 +       struct nand_chip *this = mtd->priv;
23074 +       struct doc_priv *doc = (void *)this->priv;
23075 +       int ret = 0;
23076 +       u_char *buf;
23077 +       struct NFTLMediaHeader *mh;
23078 +       const unsigned psize = 1 << this->page_shift;
23079 +       unsigned blocks, maxblocks;
23080 +       int offs, numheaders;
23081 +
23082 +       buf = (u_char *) kmalloc(mtd->oobblock, GFP_KERNEL);
23083 +       if (!buf) {
23084 +               printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
23085 +               return 0;
23086 +       }
23087 +       if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out;
23088 +       mh = (struct NFTLMediaHeader *) buf;
23089 +
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);
23100 +//#endif
23101 +
23102 +       blocks = mtd->size >> this->phys_erase_shift;
23103 +       maxblocks = min(32768U, mtd->erasesize - psize);
23104 +
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).
23110 +               */
23111 +               mh->UnitSizeFactor = 0xff;
23112 +               while (blocks > maxblocks) {
23113 +                       blocks >>= 1;
23114 +                       maxblocks = min(32768U, (maxblocks << 1) + psize);
23115 +                       mh->UnitSizeFactor--;
23116 +               }
23117 +               printk(KERN_WARNING "UnitSizeFactor=0x00 detected.  Correct value is assumed to be 0x%02x.\n", mh->UnitSizeFactor);
23118 +       }
23119 +
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);
23131 +       }
23132 +
23133 +       if (blocks > maxblocks) {
23134 +               printk(KERN_ERR "UnitSizeFactor of 0x%02x is inconsistent with device size.  Aborting.\n", mh->UnitSizeFactor);
23135 +               goto out;
23136 +       }
23137 +
23138 +       /* Skip past the media headers. */
23139 +       offs = max(doc->mh0_page, doc->mh1_page);
23140 +       offs <<= this->page_shift;
23141 +       offs += mtd->erasesize;
23142 +
23143 +       //parts[0].name = " DiskOnChip Boot / Media Header partition";
23144 +       //parts[0].offset = 0;
23145 +       //parts[0].size = offs;
23146 +
23147 +       parts[0].name = " DiskOnChip BDTL partition";
23148 +       parts[0].offset = offs;
23149 +       parts[0].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift;
23150 +
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;
23156 +               ret = 2;
23157 +               goto out;
23158 +       }
23159 +       ret = 1;
23160 +out:
23161 +       kfree(buf);
23162 +       return ret;
23163 +}
23164 +
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)
23168 +{
23169 +       struct nand_chip *this = mtd->priv;
23170 +       struct doc_priv *doc = (void *)this->priv;
23171 +       int ret = 0;
23172 +       u_char *buf;
23173 +       struct INFTLMediaHeader *mh;
23174 +       struct INFTLPartition *ip;
23175 +       int numparts = 0;
23176 +       int blocks;
23177 +       int vshift, lastvunit = 0;
23178 +       int i;
23179 +       int end = mtd->size;
23180 +
23181 +       if (inftl_bbt_write)
23182 +               end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift);
23183 +
23184 +       buf = (u_char *) kmalloc(mtd->oobblock, GFP_KERNEL);
23185 +       if (!buf) {
23186 +               printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
23187 +               return 0;
23188 +       }
23189 +
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;
23193 +
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);
23200
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);
23220 +//#endif
23221 +
23222 +       vshift = this->phys_erase_shift + mh->BlockMultiplierBits;
23223 +
23224 +       blocks = mtd->size >> vshift;
23225 +       if (blocks > 32768) {
23226 +               printk(KERN_ERR "BlockMultiplierBits=%d is inconsistent with device size.  Aborting.\n", mh->BlockMultiplierBits);
23227 +               goto out;
23228 +       }
23229 +
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");
23233 +               goto out;
23234 +       }
23235 +
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);
23245 +
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,
23256 +                       ip->spareUnits);
23257 +//#endif
23258 +
23259 +/*
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;
23264 +                       numparts = 1;
23265 +               }
23266 +*/
23267 +
23268 +               if (ip->flags & INFTL_BINARY)
23269 +                       parts[numparts].name = " DiskOnChip BDK partition";
23270 +               else
23271 +                       parts[numparts].name = " DiskOnChip BDTL partition";
23272 +               parts[numparts].offset = ip->firstUnit << vshift;
23273 +               parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift;
23274 +               numparts++;
23275 +               if (ip->lastUnit > lastvunit) lastvunit = ip->lastUnit;
23276 +               if (ip->flags & INFTL_LAST) break;
23277 +       }
23278 +       lastvunit++;
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;
23283 +               numparts++;
23284 +       }
23285 +       ret = numparts;
23286 +out:
23287 +       kfree(buf);
23288 +       return ret;
23289 +}
23290 +
23291 +static int __init nftl_scan_bbt(struct mtd_info *mtd)
23292 +{
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];
23297 +
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;
23314 +       } else {
23315 +               this->bbt_md = NULL;
23316 +       }
23317 +
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)))
23321 +               return ret;
23322 +       add_mtd_device(mtd);
23323 +#ifdef CONFIG_MTD_PARTITIONS
23324 +       if (!no_autopart)
23325 +               add_mtd_partitions(mtd, parts, numparts);
23326 +#endif
23327 +       return 0;
23328 +}
23329 +
23330 +static int __init inftl_scan_bbt(struct mtd_info *mtd)
23331 +{
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];
23336 +
23337 +       if (this->numchips > doc->chips_per_floor) {
23338 +               printk(KERN_ERR "Multi-floor INFTL devices not yet supported.\n");
23339 +               return -EIO;
23340 +       }
23341 +
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;
23348 +       } else {
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";
23359 +
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";
23370 +       }
23371 +
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)))
23375 +               return ret;
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);
23386 +#endif
23387 +       return 0;
23388 +}
23389 +
23390 +static inline int __init doc2000_init(struct mtd_info *mtd)
23391 +{
23392 +       struct nand_chip *this = mtd->priv;
23393 +       struct doc_priv *doc = (void *)this->priv;
23394 +
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;
23401 +
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);
23406 +}
23407 +
23408 +static inline int __init doc2001_init(struct mtd_info *mtd)
23409 +{
23410 +       struct nand_chip *this = mtd->priv;
23411 +       struct doc_priv *doc = (void *)this->priv;
23412 +
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;
23418 +
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);
23431 +       } else {
23432 +               /* Bog-standard Millennium */
23433 +               doc->chips_per_floor = 1;
23434 +               mtd->name = "DiskOnChip Millennium";
23435 +               this->scan_bbt = nftl_scan_bbt;
23436 +               return 1;
23437 +       }
23438 +}
23439 +
23440 +static inline int __init doc2001plus_init(struct mtd_info *mtd)
23441 +{
23442 +       struct nand_chip *this = mtd->priv;
23443 +       struct doc_priv *doc = (void *)this->priv;
23444 +
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;
23455 +
23456 +       doc->chips_per_floor = 1;
23457 +       mtd->name = "DiskOnChip Millennium Plus";
23458 +
23459 +       return 1;
23460 +}
23461 +
23462 +static inline int __init doc_probe(unsigned long physadr)
23463 +{
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;
23472 +       int ret = 0;
23473 +
23474 +       virtadr = (void __iomem *)ioremap(physadr, DOC_IOREMAP_LEN);
23475 +       if (!virtadr) {
23476 +               printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr);
23477 +               return -EIO;
23478 +       }
23479 +
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
23486 +        * found it. 
23487 +        */
23488 +       save_control = ReadDOC(virtadr, DOCControl);
23489 +
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);
23495 +
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);
23501 +
23502 +       ChipID = ReadDOC(virtadr, ChipID);
23503 +
23504 +       switch(ChipID) {
23505 +       case DOC_ChipID_Doc2k:
23506 +               reg = DoC_2k_ECCStatus;
23507 +               break;
23508 +       case DOC_ChipID_DocMil:
23509 +               reg = DoC_ECCConf;
23510 +               break;
23511 +       case DOC_ChipID_DocMilPlus16:
23512 +       case DOC_ChipID_DocMilPlus32:
23513 +       case 0:
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);
23518 +
23519 +               /* Reset the Millennium Plus ASIC */
23520 +               tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
23521 +                       DOC_MODE_BDECT;
23522 +               WriteDOC(tmp, virtadr, Mplus_DOCControl);
23523 +               WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
23524 +
23525 +               mdelay(1);
23526 +               /* Enable the Millennium Plus ASIC */
23527 +               tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
23528 +                       DOC_MODE_BDECT;
23529 +               WriteDOC(tmp, virtadr, Mplus_DOCControl);
23530 +               WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
23531 +               mdelay(1);
23532 +
23533 +               ChipID = ReadDOC(virtadr, ChipID);
23534 +
23535 +               switch (ChipID) {
23536 +               case DOC_ChipID_DocMilPlus16:
23537 +                       reg = DoC_Mplus_Toggle;
23538 +                       break;
23539 +               case DOC_ChipID_DocMilPlus32:
23540 +                       printk(KERN_ERR "DiskOnChip Millennium Plus 32MB is not supported, ignoring.\n");
23541 +               default:
23542 +                       ret = -ENODEV;
23543 +                       goto notfound;
23544 +               }
23545 +               break;
23546 +
23547 +       default:
23548 +               ret = -ENODEV;
23549 +               goto notfound;
23550 +       }
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);
23557 +               ret = -ENODEV;
23558 +               goto notfound;
23559 +       }
23560 +
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);
23573 +               } else {
23574 +                       oldval = ReadDOC(doc->virtadr, AliasResolution);
23575 +                       newval = ReadDOC(virtadr, AliasResolution);
23576 +               }
23577 +               if (oldval != newval)
23578 +                       continue;
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
23583 +               } else {
23584 +                       WriteDOC(~newval, virtadr, AliasResolution);
23585 +                       oldval = ReadDOC(doc->virtadr, AliasResolution);
23586 +                       WriteDOC(newval, virtadr, AliasResolution); // restore it
23587 +               }
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);
23591 +                       goto notfound;
23592 +               }
23593 +       }
23594 +
23595 +       printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr);
23596 +
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);
23602 +       if (!mtd) {
23603 +               printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
23604 +               ret = -ENOMEM;
23605 +               goto fail;
23606 +       }
23607 +       memset(mtd, 0, len);
23608 +
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;
23613 +
23614 +       mtd->priv               = (void *) nand;
23615 +       mtd->owner              = THIS_MODULE;
23616 +
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;
23626 +
23627 +       nand->autooob           = &doc200x_oobinfo;
23628 +       nand->eccmode           = NAND_ECC_HW6_512;
23629 +       nand->options           = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME;
23630 +
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;
23639 +
23640 +       if (ChipID == DOC_ChipID_Doc2k)
23641 +               numchips = doc2000_init(mtd);
23642 +       else if (ChipID == DOC_ChipID_DocMilPlus16)
23643 +               numchips = doc2001plus_init(mtd);
23644 +       else
23645 +               numchips = doc2001_init(mtd);
23646 +
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);
23655 +               kfree(mtd);
23656 +               goto fail;
23657 +       }
23658 +
23659 +       /* Success! */
23660 +       doclist = mtd;
23661 +       return 0;
23662 +
23663 +notfound:
23664 +       /* Put back the contents of the DOCControl register, in case it's not
23665 +          actually a DiskOnChip.  */
23666 +       WriteDOC(save_control, virtadr, DOCControl);
23667 +fail:
23668 +       iounmap((void *)virtadr);
23669 +       return ret;
23670 +}
23671 +
23672 +int __init init_nanddoc(void)
23673 +{
23674 +       int i;
23675 +
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);
23679 +       } else {
23680 +               for (i=0; (doc_locations[i] != 0xffffffff); i++) {
23681 +                       doc_probe(doc_locations[i]);
23682 +               }
23683 +       }
23684 +       /* No banner message any more. Print a message if no DiskOnChip
23685 +          found, so the user knows we at least tried. */
23686 +       if (!doclist) {
23687 +               printk(KERN_INFO "No valid DiskOnChip devices found\n");
23688 +               return -ENODEV;
23689 +       }
23690 +       return 0;
23691 +}
23692 +
23693 +void __exit cleanup_nanddoc(void)
23694 +{
23695 +       struct mtd_info *mtd, *nextmtd;
23696 +       struct nand_chip *nand;
23697 +       struct doc_priv *doc;
23698 +
23699 +       for (mtd = doclist; mtd; mtd = nextmtd) {
23700 +               nand = mtd->priv;
23701 +               doc = (void *)nand->priv;
23702 +
23703 +               nextmtd = doc->nextdoc;
23704 +               nand_release(mtd);
23705 +               iounmap((void *)doc->virtadr);
23706 +               kfree(mtd);
23707 +       }
23708 +}
23709 +
23710 +module_init(init_nanddoc);
23711 +module_exit(cleanup_nanddoc);
23712 +
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
23720 @@ -6,7 +6,7 @@
23721   *  Derived from drivers/mtd/nand/autcpu12.c
23722   *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
23723   *
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 $
23726   *
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
23729 @@ -20,6 +20,7 @@
23730  
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>
23737 @@ -52,9 +53,9 @@
23738   * Module stuff
23739   */
23740  
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;
23747  
23748  #ifdef MODULE
23749  MODULE_PARM(ep7312_fio_pbase, "i");
23750 @@ -83,7 +84,7 @@
23751  /* 
23752   *     hardware specific access to control-lines
23753   */
23754 -static void ep7312_hwcontrol(int cmd) 
23755 +static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) 
23756  {
23757         switch(cmd) {
23758                 
23759 @@ -113,10 +114,13 @@
23760  /*
23761   *     read device ready pin
23762   */
23763 -static int ep7312_device_ready(void)
23764 +static int ep7312_device_ready(struct mtd_info *mtd)
23765  {
23766         return 1;
23767  }
23768 +#ifdef CONFIG_MTD_PARTITIONS
23769 +const char *part_probes[] = { "cmdlinepart", NULL };
23770 +#endif
23771  
23772  /*
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;
23780         
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),
23785                              GFP_KERNEL);
23786         if (!ep7312_mtd) {
23787 @@ -139,7 +143,7 @@
23788         }
23789         
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");
23795                 kfree(ep7312_mtd);
23796 @@ -171,31 +175,22 @@
23797         this->chip_delay = 15;
23798         
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);
23804                 return -ENXIO;
23805         }
23806         
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);
23813 -               return -ENOMEM;
23814 -       }
23815 -       
23816 -#ifdef CONFIG_MTD_CMDLINE_PARTS
23817 -       mtd_parts_nb = parse_cmdline_partitions(ep7312_mtd, &mtd_parts, 
23818 -                                               "edb7312-nand");
23819 +#ifdef CONFIG_MTD_PARTITIONS
23820 +       ep7312_mtd->name = "edb7312-nand";
23821 +       mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes,
23822 +                                           &mtd_parts, 0);
23823         if (mtd_parts_nb > 0)
23824 -         part_type = "command line";
23825 +               part_type = "command line";
23826         else
23827 -         mtd_parts_nb = 0;
23828 +               mtd_parts_nb = 0;
23829  #endif
23830 -       if (mtd_parts_nb == 0)
23831 -       {
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 @@
23837  {
23838         struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1];
23839         
23840 -       /* Unregister the device */
23841 -       del_mtd_device (ep7312_mtd);
23842 +       /* Release resources, unregister device */
23843 +       nand_release (ap7312_mtd);
23844         
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
23851 @@ -0,0 +1,208 @@
23852 +/*
23853 + *  drivers/mtd/nand/h1910.c
23854 + *
23855 + *  Copyright (C) 2003 Joshua Wise (joshua@joshuawise.com)
23856 + *
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)
23860 + *
23861 + * $Id: h1910.c,v 1.3 2004/09/16 23:27:14 gleixner Exp $
23862 + *
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.
23866 + *
23867 + *  Overview:
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.
23871 + */
23872 +
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>
23884 +
23885 +/*
23886 + * MTD structure for EDB7312 board
23887 + */
23888 +static struct mtd_info *h1910_nand_mtd = NULL;
23889 +
23890 +/*
23891 + * Module stuff
23892 + */
23893 +
23894 +#ifdef CONFIG_MTD_PARTITIONS
23895 +/*
23896 + * Define static partitions for flash device
23897 + */
23898 +static struct mtd_partition partition_info[] = {
23899 +       { name: "h1910 NAND Flash",
23900 +                 offset: 0,
23901 +                 size: 16*1024*1024 }
23902 +};
23903 +#define NUM_PARTITIONS 1
23904 +
23905 +#endif
23906 +
23907 +
23908 +/* 
23909 + *     hardware specific access to control-lines
23910 + */
23911 +static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) 
23912 +{
23913 +       struct nand_chip* this = (struct nand_chip *) (mtd->priv);
23914 +       
23915 +       switch(cmd) {
23916 +               
23917 +       case NAND_CTL_SETCLE: 
23918 +               this->IO_ADDR_R |= (1 << 2);
23919 +               this->IO_ADDR_W |= (1 << 2);
23920 +               break;
23921 +       case NAND_CTL_CLRCLE: 
23922 +               this->IO_ADDR_R &= ~(1 << 2);
23923 +               this->IO_ADDR_W &= ~(1 << 2);
23924 +               break;
23925 +               
23926 +       case NAND_CTL_SETALE:
23927 +               this->IO_ADDR_R |= (1 << 3);
23928 +               this->IO_ADDR_W |= (1 << 3);
23929 +               break;
23930 +       case NAND_CTL_CLRALE:
23931 +               this->IO_ADDR_R &= ~(1 << 3);
23932 +               this->IO_ADDR_W &= ~(1 << 3);
23933 +               break;
23934 +               
23935 +       case NAND_CTL_SETNCE:
23936 +               break;
23937 +       case NAND_CTL_CLRNCE:
23938 +               break;
23939 +       }
23940 +}
23941 +
23942 +/*
23943 + *     read device ready pin
23944 + */
23945 +#if 0
23946 +static int h1910_device_ready(struct mtd_info *mtd)
23947 +{
23948 +       return (GPLR(55) & GPIO_bit(55));
23949 +}
23950 +#endif
23951 +
23952 +/*
23953 + * Main initialization routine
23954 + */
23955 +static int __init h1910_init (void)
23956 +{
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;
23962 +       
23963 +       if (!machine_is_h1900())
23964 +               return -ENODEV;
23965 +               
23966 +       nandaddr = (void __iomem *)__ioremap(0x08000000, 0x1000, 0, 1);
23967 +       if (!nandaddr) {
23968 +               printk("Failed to ioremap nand flash.\n");
23969 +               return -ENOMEM;
23970 +       }
23971 +       
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),
23975 +                            GFP_KERNEL);
23976 +       if (!h1910_nand_mtd) {
23977 +               printk("Unable to allocate h1910 NAND MTD device structure.\n");
23978 +               iounmap ((void *) nandaddr);
23979 +               return -ENOMEM;
23980 +       }
23981 +       
23982 +       /* Get pointer to private data */
23983 +       this = (struct nand_chip *) (&h1910_nand_mtd[1]);
23984 +       
23985 +       /* Initialize structures */
23986 +       memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info));
23987 +       memset((char *) this, 0, sizeof(struct nand_chip));
23988 +       
23989 +       /* Link the private data with the MTD structure */
23990 +       h1910_nand_mtd->priv = this;
23991 +       
23992 +       /*
23993 +        * Enable VPEN
23994 +        */
23995 +       GPSR(37) = GPIO_bit(37);
23996 +       
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;
24006 +       
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);
24012 +               return -ENXIO;
24013 +       }
24014 +       
24015 +#ifdef CONFIG_MTD_CMDLINE_PARTS
24016 +       mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, 
24017 +                                               "h1910-nand");
24018 +       if (mtd_parts_nb > 0)
24019 +         part_type = "command line";
24020 +       else
24021 +         mtd_parts_nb = 0;
24022 +#endif
24023 +       if (mtd_parts_nb == 0)
24024 +       {
24025 +               mtd_parts = partition_info;
24026 +               mtd_parts_nb = NUM_PARTITIONS;
24027 +               part_type = "static";
24028 +       }
24029 +       
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);
24033 +       
24034 +       /* Return happy */
24035 +       return 0;
24036 +}
24037 +module_init(h1910_init);
24038 +
24039 +/*
24040 + * Clean up routine
24041 + */
24042 +static void __exit h1910_cleanup (void)
24043 +{
24044 +       struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1];
24045 +       
24046 +       /* Release resources, unregister device */
24047 +       nand_release (h1910_nand_mtd);
24048 +
24049 +       /* Release io resource */
24050 +       iounmap ((void *) this->IO_ADDR_W);
24051 +
24052 +       /* Free the MTD device structure */
24053 +       kfree (h1910_nand_mtd);
24054 +}
24055 +module_exit(h1910_cleanup);
24056 +
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
24064 @@ -0,0 +1,2581 @@
24065 +/*
24066 + *  drivers/mtd/nand.c
24067 + *
24068 + *  Overview:
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.
24072 + *   
24073 + *     Additional technical information is available on
24074 + *     http://www.linux-mtd.infradead.org/tech/nand.html
24075 + *     
24076 + *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
24077 + *               2002 Thomas Gleixner (tglx@linutronix.de)
24078 + *
24079 + *  02-08-2004  tglx: support for strange chips, which cannot auto increment 
24080 + *             pages on read / read_oob
24081 + *
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
24086 + *
24087 + *  04-14-2004 tglx: first working version for 2k page size chips
24088 + *  
24089 + *  05-19-2004  tglx: Basic support for Renesas AG-AND chips
24090 + *
24091 + * Credits:
24092 + *     David Woodhouse for adding multichip support  
24093 + *     
24094 + *     Aleph One Ltd. and Toby Churchill Ltd. for supporting the
24095 + *     rework for 2K page size chips
24096 + *
24097 + * TODO:
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.
24103 + *
24104 + * $Id: nand_base.c,v 1.116 2004/08/30 18:00:45 gleixner Exp $
24105 + *
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.
24109 + *
24110 + */
24111 +
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>
24124 +
24125 +#ifdef CONFIG_MTD_PARTITIONS
24126 +#include <linux/mtd/partitions.h>
24127 +#endif
24128 +
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,
24132 +       .eccbytes = 3,
24133 +       .eccpos = {0, 1, 2},
24134 +       .oobfree = { {3, 2}, {6, 2} }
24135 +};
24136 +
24137 +static struct nand_oobinfo nand_oob_16 = {
24138 +       .useecc = MTD_NANDECC_AUTOPLACE,
24139 +       .eccbytes = 6,
24140 +       .eccpos = {0, 1, 2, 3, 6, 7},
24141 +       .oobfree = { {8, 8} }
24142 +};
24143 +
24144 +static struct nand_oobinfo nand_oob_64 = {
24145 +       .useecc = MTD_NANDECC_AUTOPLACE,
24146 +       .eccbytes = 24,
24147 +       .eccpos = {
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} }
24152 +};
24153 +
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,
24164 +};
24165 +
24166 +/*
24167 + * NAND low-level MTD interface functions
24168 + */
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);
24172 +
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);
24187 +
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);
24194 +#else
24195 +#define nand_verify_pages(...) (0)
24196 +#endif
24197 +               
24198 +static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state);
24199 +
24200 +/**
24201 + * nand_release_chip - [GENERIC] release chip
24202 + * @mtd:       MTD device structure
24203 + * 
24204 + * Deselect, release chip lock and wake up anyone waiting on the device 
24205 + */
24206 +static void nand_release_chip (struct mtd_info *mtd)
24207 +{
24208 +       struct nand_chip *this = mtd->priv;
24209 +
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);
24217 +}
24218 +
24219 +/**
24220 + * nand_read_byte - [DEFAULT] read one byte from the chip
24221 + * @mtd:       MTD device structure
24222 + *
24223 + * Default read function for 8bit buswith
24224 + */
24225 +static u_char nand_read_byte(struct mtd_info *mtd)
24226 +{
24227 +       struct nand_chip *this = mtd->priv;
24228 +       return readb(this->IO_ADDR_R);
24229 +}
24230 +
24231 +/**
24232 + * nand_write_byte - [DEFAULT] write one byte to the chip
24233 + * @mtd:       MTD device structure
24234 + * @byte:      pointer to data byte to write
24235 + *
24236 + * Default write function for 8it buswith
24237 + */
24238 +static void nand_write_byte(struct mtd_info *mtd, u_char byte)
24239 +{
24240 +       struct nand_chip *this = mtd->priv;
24241 +       writeb(byte, this->IO_ADDR_W);
24242 +}
24243 +
24244 +/**
24245 + * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
24246 + * @mtd:       MTD device structure
24247 + *
24248 + * Default read function for 16bit buswith with 
24249 + * endianess conversion
24250 + */
24251 +static u_char nand_read_byte16(struct mtd_info *mtd)
24252 +{
24253 +       struct nand_chip *this = mtd->priv;
24254 +       return (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
24255 +}
24256 +
24257 +/**
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
24261 + *
24262 + * Default write function for 16bit buswith with
24263 + * endianess conversion
24264 + */
24265 +static void nand_write_byte16(struct mtd_info *mtd, u_char byte)
24266 +{
24267 +       struct nand_chip *this = mtd->priv;
24268 +       writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
24269 +}
24270 +
24271 +/**
24272 + * nand_read_word - [DEFAULT] read one word from the chip
24273 + * @mtd:       MTD device structure
24274 + *
24275 + * Default read function for 16bit buswith without 
24276 + * endianess conversion
24277 + */
24278 +static u16 nand_read_word(struct mtd_info *mtd)
24279 +{
24280 +       struct nand_chip *this = mtd->priv;
24281 +       return readw(this->IO_ADDR_R);
24282 +}
24283 +
24284 +/**
24285 + * nand_write_word - [DEFAULT] write one word to the chip
24286 + * @mtd:       MTD device structure
24287 + * @word:      data word to write
24288 + *
24289 + * Default write function for 16bit buswith without 
24290 + * endianess conversion
24291 + */
24292 +static void nand_write_word(struct mtd_info *mtd, u16 word)
24293 +{
24294 +       struct nand_chip *this = mtd->priv;
24295 +       writew(word, this->IO_ADDR_W);
24296 +}
24297 +
24298 +/**
24299 + * nand_select_chip - [DEFAULT] control CE line
24300 + * @mtd:       MTD device structure
24301 + * @chip:      chipnumber to select, -1 for deselect
24302 + *
24303 + * Default select function for 1 chip devices.
24304 + */
24305 +static void nand_select_chip(struct mtd_info *mtd, int chip)
24306 +{
24307 +       struct nand_chip *this = mtd->priv;
24308 +       switch(chip) {
24309 +       case -1:
24310 +               this->hwcontrol(mtd, NAND_CTL_CLRNCE);  
24311 +               break;
24312 +       case 0:
24313 +               this->hwcontrol(mtd, NAND_CTL_SETNCE);
24314 +               break;
24315 +
24316 +       default:
24317 +               BUG();
24318 +       }
24319 +}
24320 +
24321 +/**
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
24326 + *
24327 + * Default write function for 8bit buswith
24328 + */
24329 +static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
24330 +{
24331 +       int i;
24332 +       struct nand_chip *this = mtd->priv;
24333 +
24334 +       for (i=0; i<len; i++)
24335 +               writeb(buf[i], this->IO_ADDR_W);
24336 +}
24337 +
24338 +/**
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
24343 + *
24344 + * Default read function for 8bit buswith
24345 + */
24346 +static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
24347 +{
24348 +       int i;
24349 +       struct nand_chip *this = mtd->priv;
24350 +
24351 +       for (i=0; i<len; i++)
24352 +               buf[i] = readb(this->IO_ADDR_R);
24353 +}
24354 +
24355 +/**
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
24360 + *
24361 + * Default verify function for 8bit buswith
24362 + */
24363 +static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
24364 +{
24365 +       int i;
24366 +       struct nand_chip *this = mtd->priv;
24367 +
24368 +       for (i=0; i<len; i++)
24369 +               if (buf[i] != readb(this->IO_ADDR_R))
24370 +                       return -EFAULT;
24371 +
24372 +       return 0;
24373 +}
24374 +
24375 +/**
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
24380 + *
24381 + * Default write function for 16bit buswith
24382 + */
24383 +static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
24384 +{
24385 +       int i;
24386 +       struct nand_chip *this = mtd->priv;
24387 +       u16 *p = (u16 *) buf;
24388 +       len >>= 1;
24389 +       
24390 +       for (i=0; i<len; i++)
24391 +               writew(p[i], this->IO_ADDR_W);
24392 +               
24393 +}
24394 +
24395 +/**
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
24400 + *
24401 + * Default read function for 16bit buswith
24402 + */
24403 +static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
24404 +{
24405 +       int i;
24406 +       struct nand_chip *this = mtd->priv;
24407 +       u16 *p = (u16 *) buf;
24408 +       len >>= 1;
24409 +
24410 +       for (i=0; i<len; i++)
24411 +               p[i] = readw(this->IO_ADDR_R);
24412 +}
24413 +
24414 +/**
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
24419 + *
24420 + * Default verify function for 16bit buswith
24421 + */
24422 +static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
24423 +{
24424 +       int i;
24425 +       struct nand_chip *this = mtd->priv;
24426 +       u16 *p = (u16 *) buf;
24427 +       len >>= 1;
24428 +
24429 +       for (i=0; i<len; i++)
24430 +               if (p[i] != readw(this->IO_ADDR_R))
24431 +                       return -EFAULT;
24432 +
24433 +       return 0;
24434 +}
24435 +
24436 +/**
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
24441 + *
24442 + * Check, if the block is bad. 
24443 + */
24444 +static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
24445 +{
24446 +       int page, chipnr, res = 0;
24447 +       struct nand_chip *this = mtd->priv;
24448 +       u16 bad;
24449 +
24450 +       if (getchip) {
24451 +               page = (int)(ofs >> this->page_shift);
24452 +               chipnr = (int)(ofs >> this->chip_shift);
24453 +
24454 +               /* Grab the lock and see if the device is available */
24455 +               nand_get_chip (this, mtd, FL_READING);
24456 +
24457 +               /* Select the NAND device */
24458 +               this->select_chip(mtd, chipnr);
24459 +       } else 
24460 +               page = (int) ofs;       
24461 +
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)
24466 +                       bad >>= 1;
24467 +               if ((bad & 0xFF) != 0xff)
24468 +                       res = 1;
24469 +       } else {
24470 +               this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask);
24471 +               if (this->read_byte(mtd) != 0xff)
24472 +                       res = 1;
24473 +       }
24474 +               
24475 +       if (getchip) {
24476 +               /* Deselect and wake up anyone waiting on the device */
24477 +               nand_release_chip(mtd);
24478 +       }       
24479 +       
24480 +       return res;
24481 +}
24482 +
24483 +/**
24484 + * nand_default_block_markbad - [DEFAULT] mark a block bad
24485 + * @mtd:       MTD device structure
24486 + * @ofs:       offset from device start
24487 + *
24488 + * This is the default implementation, which can be overridden by
24489 + * a hardware specific driver.
24490 +*/
24491 +static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
24492 +{
24493 +       struct nand_chip *this = mtd->priv;
24494 +       u_char buf[2] = {0, 0};
24495 +       size_t  retlen;
24496 +       int block;
24497 +       
24498 +       /* Get block number */
24499 +       block = ((int) ofs) >> this->bbt_erase_shift;
24500 +       this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
24501 +
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);
24505 +               
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);
24509 +}
24510 +
24511 +/** 
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 
24515 + *
24516 + * The function expects, that the device is already selected 
24517 + */
24518 +static int nand_check_wp (struct mtd_info *mtd)
24519 +{
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; 
24524 +}
24525 +
24526 +/**
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
24532 + *
24533 + * Check, if the block is bad. Either by reading the bad block table or
24534 + * calling of the scan function.
24535 + */
24536 +static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt)
24537 +{
24538 +       struct nand_chip *this = mtd->priv;
24539 +       
24540 +       if (!this->bbt)
24541 +               return this->block_bad(mtd, ofs, getchip);
24542 +       
24543 +       /* Return info from the table */
24544 +       return nand_isbad_bbt (mtd, ofs, allowbbt);
24545 +}
24546 +
24547 +/**
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
24553 + *
24554 + * Send command to NAND device. This function is used for small page
24555 + * devices (256/512 Bytes per page)
24556 + */
24557 +static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
24558 +{
24559 +       register struct nand_chip *this = mtd->priv;
24560 +
24561 +       /* Begin command latch cycle */
24562 +       this->hwcontrol(mtd, NAND_CTL_SETCLE);
24563 +       /*
24564 +        * Write out the command to the device.
24565 +        */
24566 +       if (command == NAND_CMD_SEQIN) {
24567 +               int readcmd;
24568 +
24569 +               if (column >= mtd->oobblock) {
24570 +                       /* OOB area */
24571 +                       column -= mtd->oobblock;
24572 +                       readcmd = NAND_CMD_READOOB;
24573 +               } else if (column < 256) {
24574 +                       /* First 256 bytes --> READ0 */
24575 +                       readcmd = NAND_CMD_READ0;
24576 +               } else {
24577 +                       column -= 256;
24578 +                       readcmd = NAND_CMD_READ1;
24579 +               }
24580 +               this->write_byte(mtd, readcmd);
24581 +       }
24582 +       this->write_byte(mtd, command);
24583 +
24584 +       /* Set ALE and clear CLE to start address cycle */
24585 +       this->hwcontrol(mtd, NAND_CTL_CLRCLE);
24586 +
24587 +       if (column != -1 || page_addr != -1) {
24588 +               this->hwcontrol(mtd, NAND_CTL_SETALE);
24589 +
24590 +               /* Serially input address */
24591 +               if (column != -1) {
24592 +                       /* Adjust columns for 16 bit buswidth */
24593 +                       if (this->options & NAND_BUSWIDTH_16)
24594 +                               column >>= 1;
24595 +                       this->write_byte(mtd, column);
24596 +               }
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));
24603 +               }
24604 +               /* Latch in address */
24605 +               this->hwcontrol(mtd, NAND_CTL_CLRALE);
24606 +       }
24607 +       
24608 +       /* 
24609 +        * program and erase have their own busy handlers 
24610 +        * status and sequential in needs no delay
24611 +       */
24612 +       switch (command) {
24613 +                       
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:
24619 +               return;
24620 +
24621 +       case NAND_CMD_RESET:
24622 +               if (this->dev_ready)    
24623 +                       break;
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));
24629 +               return;
24630 +
24631 +       /* This applies to read commands */     
24632 +       default:
24633 +               /* 
24634 +                * If we don't have access to the busy pin, we apply the given
24635 +                * command delay
24636 +               */
24637 +               if (!this->dev_ready) {
24638 +                       udelay (this->chip_delay);
24639 +                       return;
24640 +               }       
24641 +       }
24642 +       
24643 +       /* Apply this short delay always to ensure that we do wait tWB in
24644 +        * any case on any machine. */
24645 +       ndelay (100);
24646 +       /* wait until command is processed */
24647 +       while (!this->dev_ready(mtd));
24648 +}
24649 +
24650 +/**
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
24656 + *
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.
24660 + *
24661 + */
24662 +static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, int page_addr)
24663 +{
24664 +       register struct nand_chip *this = mtd->priv;
24665 +
24666 +       /* Emulate NAND_CMD_READOOB */
24667 +       if (command == NAND_CMD_READOOB) {
24668 +               column += mtd->oobblock;
24669 +               command = NAND_CMD_READ0;
24670 +       }
24671 +       
24672 +               
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);
24679 +
24680 +       if (column != -1 || page_addr != -1) {
24681 +               this->hwcontrol(mtd, NAND_CTL_SETALE);
24682 +
24683 +               /* Serially input address */
24684 +               if (column != -1) {
24685 +                       /* Adjust columns for 16 bit buswidth */
24686 +                       if (this->options & NAND_BUSWIDTH_16)
24687 +                               column >>= 1;
24688 +                       this->write_byte(mtd, column & 0xff);
24689 +                       this->write_byte(mtd, column >> 8);
24690 +               }       
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));
24697 +               }
24698 +               /* Latch in address */
24699 +               this->hwcontrol(mtd, NAND_CTL_CLRALE);
24700 +       }
24701 +       
24702 +       /* 
24703 +        * program and erase have their own busy handlers 
24704 +        * status and sequential in needs no delay
24705 +       */
24706 +       switch (command) {
24707 +                       
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:
24714 +               return;
24715 +
24716 +
24717 +       case NAND_CMD_RESET:
24718 +               if (this->dev_ready)    
24719 +                       break;
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));
24725 +               return;
24726 +
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 */
24735 +               
24736 +       /* This applies to read commands */     
24737 +       default:
24738 +               /* 
24739 +                * If we don't have access to the busy pin, we apply the given
24740 +                * command delay
24741 +               */
24742 +               if (!this->dev_ready) {
24743 +                       udelay (this->chip_delay);
24744 +                       return;
24745 +               }       
24746 +       }
24747 +       
24748 +       /* Apply this short delay always to ensure that we do wait tWB in
24749 +        * any case on any machine. */
24750 +       ndelay (100);
24751 +       /* wait until command is processed */
24752 +       while (!this->dev_ready(mtd));
24753 +}
24754 +
24755 +/**
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 
24760 + *
24761 + * Get the device and lock it for exclusive access
24762 + */
24763 +static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state)
24764 +{
24765 +
24766 +       DECLARE_WAITQUEUE (wait, current);
24767 +
24768 +       /* 
24769 +        * Grab the lock and see if the device is available 
24770 +       */
24771 +retry:
24772 +       spin_lock_bh (&this->chip_lock);
24773 +
24774 +       if (this->state == FL_READY) {
24775 +               this->state = new_state;
24776 +               spin_unlock_bh (&this->chip_lock);
24777 +               return;
24778 +       }
24779 +
24780 +       set_current_state (TASK_UNINTERRUPTIBLE);
24781 +       add_wait_queue (&this->wq, &wait);
24782 +       spin_unlock_bh (&this->chip_lock);
24783 +       schedule ();
24784 +       remove_wait_queue (&this->wq, &wait);
24785 +       goto retry;
24786 +}
24787 +
24788 +/**
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
24793 + *
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
24797 + *
24798 +*/
24799 +static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
24800 +{
24801 +
24802 +       unsigned long   timeo = jiffies;
24803 +       int     status;
24804 +       
24805 +       if (state == FL_ERASING)
24806 +                timeo += (HZ * 400) / 1000;
24807 +       else
24808 +                timeo += (HZ * 20) / 1000;
24809 +
24810 +       /* Apply this short delay always to ensure that we do wait tWB in
24811 +        * any case on any machine. */
24812 +       ndelay (100);
24813 +
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);
24817 +       else    
24818 +               this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);
24819 +
24820 +       while (time_before(jiffies, timeo)) {           
24821 +               /* Check, if we were interrupted */
24822 +               if (this->state != state) {
24823 +                       spin_unlock_bh (&this->chip_lock);
24824 +                       return 0;
24825 +               }
24826 +               if (this->dev_ready) {
24827 +                       if (this->dev_ready(mtd))
24828 +                               break;  
24829 +               } else {
24830 +                       if (this->read_byte(mtd) & NAND_STATUS_READY)
24831 +                               break;
24832 +               }
24833 +               spin_unlock_bh (&this->chip_lock);
24834 +               yield ();
24835 +               spin_lock_bh (&this->chip_lock);
24836 +       }
24837 +       status = (int) this->read_byte(mtd);
24838 +       spin_unlock_bh (&this->chip_lock);
24839 +
24840 +       return status;
24841 +}
24842 +
24843 +/**
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
24851 + *
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 :)
24855 + *
24856 + * Cached programming is not supported yet.
24857 + */
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)
24860 +{
24861 +       int     i, status;
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;
24867 +       
24868 +       /* FIXME: Enable cached programming */
24869 +       cached = 0;
24870 +       
24871 +       /* Send command to begin auto page programming */
24872 +       this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page);
24873 +
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);
24880 +               break;
24881 +               
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;
24889 +               }
24890 +               this->write_buf(mtd, this->data_poi, mtd->oobblock);
24891 +               break;
24892 +               
24893 +       /* Hardware ecc 8 byte / 512 byte data */       
24894 +       case NAND_ECC_HW8_512:  
24895 +               eccbytes += 2;
24896 +       /* Hardware ecc 6 byte / 512 byte data */       
24897 +       case NAND_ECC_HW6_512:  
24898 +               eccbytes += 3;
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:
24903 +               eccbytes += 3;
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);
24916 +
24917 +                       datidx += this->eccsize;
24918 +               }
24919 +               break;
24920 +
24921 +       default:
24922 +               printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
24923 +               BUG();  
24924 +       }
24925 +                                                                               
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);
24929 +       else 
24930 +               this->write_buf(mtd, oob_buf, mtd->oobsize);
24931 +
24932 +       /* Send command to actually program the data */
24933 +       this->cmdfunc (mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
24934 +
24935 +       if (!cached) {
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);
24941 +                       return -EIO;
24942 +               }
24943 +       } else {
24944 +               /* FIXME: Implement cached programming ! */
24945 +               /* wait until cache is ready*/
24946 +               // status = this->waitfunc (mtd, this, FL_CACHEDRPG);
24947 +       }
24948 +       return 0;       
24949 +}
24950 +
24951 +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
24952 +/**
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
24962 + *
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.
24970 + */
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)
24973 +{
24974 +       int     i, j, datidx = 0, oobofs = 0, res = -EIO;
24975 +       int     eccsteps = this->eccsteps;
24976 +       int     hweccbytes; 
24977 +       u_char  oobdata[64];
24978 +
24979 +       hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
24980 +
24981 +       /* Send command to read back the first page */
24982 +       this->cmdfunc (mtd, NAND_CMD_READ0, 0, page);
24983 +
24984 +       for(;;) {
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);
24989 +                               goto out;
24990 +                       }
24991 +                       datidx += mtd->eccsize;
24992 +                       /* Have we a hw generator layout ? */
24993 +                       if (!hweccbytes)
24994 +                               continue;
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);
24997 +                               goto out;
24998 +                       }
24999 +                       oobofs += hweccbytes;
25000 +               }
25001 +
25002 +               /* check, if we must compare all data or if we just have to
25003 +                * compare the ecc bytes
25004 +                */
25005 +               if (oobmode) {
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);
25008 +                               goto out;
25009 +                       }
25010 +               } else {
25011 +                       /* Read always, else autoincrement fails */
25012 +                       this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
25013 +
25014 +                       if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
25015 +                               int ecccnt = oobsel->eccbytes;
25016 +               
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);
25023 +                                               goto out;
25024 +                                       }
25025 +                               }
25026 +                       }       
25027 +               }
25028 +               oobofs += mtd->oobsize - hweccbytes * eccsteps;
25029 +               page++;
25030 +               numpages--;
25031 +
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.
25038 +               */
25039 +               if (!this->dev_ready) 
25040 +                       udelay (this->chip_delay);
25041 +               else
25042 +                       while (!this->dev_ready(mtd));  
25043 +
25044 +               /* All done, return happy */
25045 +               if (!numpages)
25046 +                       return 0;
25047 +               
25048 +                       
25049 +               /* Check, if the chip supports auto page increment */ 
25050 +               if (!NAND_CANAUTOINCR(this))
25051 +                       this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
25052 +       }
25053 +       /* 
25054 +        * Terminate the read command. We come here in case of an error
25055 +        * So we must issue a reset command.
25056 +        */
25057 +out:    
25058 +       this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1);
25059 +       return res;
25060 +}
25061 +#endif
25062 +
25063 +/**
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
25070 + *
25071 + * This function simply calls nand_read_ecc with oob buffer and oobsel = NULL
25072 +*/
25073 +static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
25074 +{
25075 +       return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL);
25076 +}                         
25077 +
25078 +
25079 +/**
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
25088 + *
25089 + * NAND read with ECC
25090 + */
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)
25093 +{
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;
25105 +       int     oobreadlen;
25106 +
25107 +
25108 +       DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
25109 +
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");
25113 +               *retlen = 0;
25114 +               return -EINVAL;
25115 +       }
25116 +
25117 +       /* Grab the lock and see if the device is available */
25118 +       nand_get_chip (this, mtd ,FL_READING);
25119 +
25120 +       /* use userspace supplied oobinfo, if zero */
25121 +       if (oobsel == NULL)
25122 +               oobsel = &mtd->oobinfo;
25123 +       
25124 +       /* Autoplace of oob data ? Use the default placement scheme */
25125 +       if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
25126 +               oobsel = this->autooob;
25127 +               
25128 +       eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
25129 +       oob_config = oobsel->eccpos;
25130 +
25131 +       /* Select the NAND device */
25132 +       chipnr = (int)(from >> this->chip_shift);
25133 +       this->select_chip(mtd, chipnr);
25134 +
25135 +       /* First we calculate the starting page */
25136 +       realpage = (int) (from >> this->page_shift);
25137 +       page = realpage & this->pagemask;
25138 +
25139 +       /* Get raw starting column */
25140 +       col = from & (mtd->oobblock - 1);
25141 +
25142 +       end = mtd->oobblock;
25143 +       ecc = this->eccsize;
25144 +       switch (eccmode) {
25145 +       case NAND_ECC_HW6_512: /* Hardware ECC 6 byte / 512 byte data  */
25146 +               eccbytes = 6;
25147 +               break;                                          
25148 +       case NAND_ECC_HW8_512: /* Hardware ECC 8 byte / 512 byte data  */
25149 +               eccbytes = 8;
25150 +               break;
25151 +       case NAND_ECC_NONE:
25152 +               compareecc = 0;
25153 +               break;                                          
25154 +       }        
25155 +
25156 +       if (this->options & NAND_HWECC_SYNDROME)
25157 +               compareecc = 0;
25158 +
25159 +       oobreadlen = mtd->oobsize;
25160 +       if (this->options & NAND_HWECC_SYNDROME) 
25161 +               oobreadlen -= oobsel->eccbytes;
25162 +
25163 +       /* Loop until all data read */
25164 +       while (read < len) {
25165 +               
25166 +               int aligned = (!col && (len - read) >= end);
25167 +               /* 
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
25170 +                */
25171 +               if (aligned)
25172 +                       data_poi = &buf[read];
25173 +               else 
25174 +                       data_poi = this->data_buf;
25175 +               
25176 +               /* Check, if we have this page in the buffer 
25177 +                *
25178 +                * FIXME: Make it work when we must provide oob data too,
25179 +                * check the usage of data_buf oob field
25180 +                */
25181 +               if (realpage == this->pagebuf && !oob_buf) {
25182 +                       /* aligned read ? */
25183 +                       if (aligned)
25184 +                               memcpy (data_poi, this->data_buf, end);
25185 +                       goto readdata;
25186 +               }
25187 +
25188 +               /* Check, if we must send the read command */
25189 +               if (sndcmd) {
25190 +                       this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
25191 +                       sndcmd = 0;
25192 +               }       
25193 +
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];
25197 +
25198 +               eccsteps = this->eccsteps;
25199 +               
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;
25206 +                       }
25207 +                       this->read_buf(mtd, data_poi, end);
25208 +                       break;
25209 +               }
25210 +                       
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]);
25215 +                       break;  
25216 +                       
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);
25224 +
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);
25238 +                                               ecc_failed++;
25239 +                                       }
25240 +                               } else {
25241 +                                       this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
25242 +                               }       
25243 +                       }
25244 +                       break;                                          
25245 +
25246 +               default:
25247 +                       printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
25248 +                       BUG();  
25249 +               }
25250 +
25251 +               /* read oobdata */
25252 +               this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
25253 +
25254 +               /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
25255 +               if (!compareecc)
25256 +                       goto readoob;   
25257 +               
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]];
25261 +
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]);
25265 +                       
25266 +                       /* Get next chunk of ecc bytes */
25267 +                       j += eccbytes;
25268 +                       
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
25272 +                        */
25273 +                       if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) { 
25274 +                               int *p = (int *)(&oob_data[mtd->oobsize]);
25275 +                               p[i] = ecc_status;
25276 +                       }
25277 +                       
25278 +                       if (ecc_status == -1) { 
25279 +                               DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);
25280 +                               ecc_failed++;
25281 +                       }
25282 +               }               
25283 +
25284 +       readoob:
25285 +               /* check, if we have a fs supplied oob-buffer */
25286 +               if (oob_buf) {
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);
25295 +                                       j+= num;
25296 +                               }
25297 +                               oob += mtd->oobavail;
25298 +                               break;
25299 +                       case MTD_NANDECC_PLACE:
25300 +                               /* YAFFS1 legacy mode */
25301 +                               oob_data += this->eccsteps * sizeof (int);
25302 +                       default:
25303 +                               oob_data += mtd->oobsize;
25304 +                       }
25305 +               }
25306 +       readdata:
25307 +               /* Partial page read, transfer data into fs buffer */
25308 +               if (!aligned) { 
25309 +                       for (j = col; j < end && read < len; j++)
25310 +                               buf[read++] = data_poi[j];
25311 +                       this->pagebuf = realpage;       
25312 +               } else          
25313 +                       read += mtd->oobblock;
25314 +
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.
25319 +               */
25320 +               if (!this->dev_ready) 
25321 +                       udelay (this->chip_delay);
25322 +               else
25323 +                       while (!this->dev_ready(mtd));  
25324 +                       
25325 +               if (read == len)
25326 +                       break;  
25327 +
25328 +               /* For subsequent reads align to page boundary. */
25329 +               col = 0;
25330 +               /* Increment page address */
25331 +               realpage++;
25332 +
25333 +               page = realpage & this->pagemask;
25334 +               /* Check, if we cross a chip boundary */
25335 +               if (!page) {
25336 +                       chipnr++;
25337 +                       this->select_chip(mtd, -1);
25338 +                       this->select_chip(mtd, chipnr);
25339 +               }
25340 +               /* Check, if the chip supports auto page increment 
25341 +                * or if we have hit a block boundary. 
25342 +               */ 
25343 +               if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
25344 +                       sndcmd = 1;                             
25345 +       }
25346 +
25347 +       /* Deselect and wake up anyone waiting on the device */
25348 +       nand_release_chip(mtd);
25349 +
25350 +       /*
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
25354 +        */
25355 +       *retlen = read;
25356 +       return ecc_failed ? -EBADMSG : 0;
25357 +}
25358 +
25359 +/**
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
25366 + *
25367 + * NAND read out-of-band data from the spare area
25368 + */
25369 +static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
25370 +{
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;
25374 +
25375 +       DEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
25376 +
25377 +       /* Shift to get page */
25378 +       page = (int)(from >> this->page_shift);
25379 +       chipnr = (int)(from >> this->chip_shift);
25380 +       
25381 +       /* Mask to get column */
25382 +       col = from & (mtd->oobsize - 1);
25383 +
25384 +       /* Initialize return length value */
25385 +       *retlen = 0;
25386 +
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");
25390 +               *retlen = 0;
25391 +               return -EINVAL;
25392 +       }
25393 +
25394 +       /* Grab the lock and see if the device is available */
25395 +       nand_get_chip (this, mtd , FL_READING);
25396 +
25397 +       /* Select the NAND device */
25398 +       this->select_chip(mtd, chipnr);
25399 +
25400 +       /* Send the read command */
25401 +       this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask);
25402 +       /* 
25403 +        * Read the data, if we read more than one page
25404 +        * oob data, let the device transfer the data !
25405 +        */
25406 +       i = 0;
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);
25411 +               i += thislen;
25412 +               
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.
25417 +               */
25418 +               if (!this->dev_ready) 
25419 +                       udelay (this->chip_delay);
25420 +               else
25421 +                       while (!this->dev_ready(mtd));  
25422 +
25423 +               /* Read more ? */
25424 +               if (i < len) {
25425 +                       page++;
25426 +                       col = 0;
25427 +
25428 +                       /* Check, if we cross a chip boundary */
25429 +                       if (!(page & this->pagemask)) {
25430 +                               chipnr++;
25431 +                               this->select_chip(mtd, -1);
25432 +                               this->select_chip(mtd, chipnr);
25433 +                       }
25434 +                               
25435 +                       /* Check, if the chip supports auto page increment 
25436 +                        * or if we have hit a block boundary. 
25437 +                       */ 
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);
25441 +                       }
25442 +               }
25443 +       }
25444 +
25445 +       /* Deselect and wake up anyone waiting on the device */
25446 +       nand_release_chip(mtd);
25447 +
25448 +       /* Return happy */
25449 +       *retlen = len;
25450 +       return 0;
25451 +}
25452 +
25453 +/**
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
25460 + *
25461 + * Read raw data including oob into buffer
25462 + */
25463 +int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen)
25464 +{
25465 +       struct nand_chip *this = mtd->priv;
25466 +       int page = (int) (from >> this->page_shift);
25467 +       int chip = (int) (from >> this->chip_shift);
25468 +       int sndcmd = 1;
25469 +       int cnt = 0;
25470 +       int pagesize = mtd->oobblock + mtd->oobsize;
25471 +       int     blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
25472 +
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");
25476 +               return -EINVAL;
25477 +       }
25478 +
25479 +       /* Grab the lock and see if the device is available */
25480 +       nand_get_chip (this, mtd , FL_READING);
25481 +
25482 +       this->select_chip (mtd, chip);
25483 +       
25484 +       /* Add requested oob length */
25485 +       len += ooblen;
25486 +       
25487 +       while (len) {
25488 +               if (sndcmd)
25489 +                       this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask);
25490 +               sndcmd = 0;     
25491 +
25492 +               this->read_buf (mtd, &buf[cnt], pagesize);
25493 +
25494 +               len -= pagesize;
25495 +               cnt += pagesize;
25496 +               page++;
25497 +               
25498 +               if (!this->dev_ready) 
25499 +                       udelay (this->chip_delay);
25500 +               else
25501 +                       while (!this->dev_ready(mtd));  
25502 +                       
25503 +               /* Check, if the chip supports auto page increment */ 
25504 +               if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
25505 +                       sndcmd = 1;
25506 +       }
25507 +
25508 +       /* Deselect and wake up anyone waiting on the device */
25509 +       nand_release_chip(mtd);
25510 +       return 0;
25511 +}
25512 +
25513 +
25514 +/** 
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
25521 + *
25522 + * Return:
25523 + * 1. Filesystem buffer available and autoplacement is off,
25524 + *    return filesystem buffer
25525 + * 2. No filesystem buffer or autoplace is off, return internal
25526 + *    buffer
25527 + * 3. Filesystem buffer is given and autoplace selected
25528 + *    put data from fs buffer into internal buffer and
25529 + *    retrun internal buffer
25530 + *
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.
25535 + *
25536 +*/
25537 +static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct nand_oobinfo *oobsel,
25538 +               int autoplace, int numpages)
25539 +{
25540 +       struct nand_chip *this = mtd->priv;
25541 +       int i, len, ofs;
25542 +
25543 +       /* Zero copy fs supplied buffer */
25544 +       if (fsbuf && !autoplace) 
25545 +               return fsbuf;
25546 +
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;
25552 +       }       
25553 +       
25554 +       /* If we have no autoplacement or no fs buffer use the internal one */
25555 +       if (!autoplace || !fsbuf)
25556 +               return this->oob_buf;
25557 +       
25558 +       /* Walk through the pages and place the data */
25559 +       this->oobdirty = 1;
25560 +       ofs = 0;
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);
25566 +                       len += num;
25567 +                       fsbuf += num;
25568 +               }
25569 +               ofs += mtd->oobavail;
25570 +       }
25571 +       return this->oob_buf;
25572 +}
25573 +
25574 +#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0
25575 +
25576 +/**
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
25583 + *
25584 + * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
25585 + *
25586 +*/
25587 +static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
25588 +{
25589 +       return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL));
25590 +}
25591 +                          
25592 +/**
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
25601 + *
25602 + * NAND write with ECC
25603 + */
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)
25606 +{
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));
25612 +
25613 +       DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
25614 +
25615 +       /* Initialize retlen, in case of early exit */
25616 +       *retlen = 0;
25617 +
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");
25621 +               return -EINVAL;
25622 +       }
25623 +
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");
25627 +               return -EINVAL;
25628 +       }
25629 +
25630 +       /* Grab the lock and see if the device is available */
25631 +       nand_get_chip (this, mtd, FL_WRITING);
25632 +
25633 +       /* Calculate chipnr */
25634 +       chipnr = (int)(to >> this->chip_shift);
25635 +       /* Select the NAND device */
25636 +       this->select_chip(mtd, chipnr);
25637 +
25638 +       /* Check, if it is write protected */
25639 +       if (nand_check_wp(mtd))
25640 +               goto out;
25641 +
25642 +       /* if oobsel is NULL, use chip defaults */
25643 +       if (oobsel == NULL) 
25644 +               oobsel = &mtd->oobinfo;         
25645 +               
25646 +       /* Autoplace of oob data ? Use the default placement scheme */
25647 +       if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
25648 +               oobsel = this->autooob;
25649 +               autoplace = 1;
25650 +       }       
25651 +
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;
25658 +       
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;
25666 +
25667 +       /* Loop until all data is written */
25668 +       while (written < len) {
25669 +
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.
25675 +                */
25676 +               ret = nand_write_page (mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
25677 +               if (ret) {
25678 +                       DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret);
25679 +                       goto out;
25680 +               }       
25681 +               /* Next oob page */
25682 +               oob += mtd->oobsize;
25683 +               /* Update written bytes count */
25684 +               written += mtd->oobblock;
25685 +               if (written == len) 
25686 +                       goto cmp;
25687 +               
25688 +               /* Increment page address */
25689 +               page++;
25690 +
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.
25694 +               */
25695 +               if (!(page & (ppblock - 1))){
25696 +                       int ofs;
25697 +                       this->data_poi = bufstart;
25698 +                       ret = nand_verify_pages (mtd, this, startpage, 
25699 +                               page - startpage,
25700 +                               oobbuf, oobsel, chipnr, (eccbuf != NULL));
25701 +                       if (ret) {
25702 +                               DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
25703 +                               goto out;
25704 +                       }       
25705 +                       *retlen = written;
25706 +
25707 +                       ofs = autoplace ? mtd->oobavail : mtd->oobsize;
25708 +                       if (eccbuf)
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 */
25717 +                       if (!page) {
25718 +                               chipnr++;
25719 +                               this->select_chip(mtd, -1);
25720 +                               this->select_chip(mtd, chipnr);
25721 +                       }
25722 +               }
25723 +       }
25724 +       /* Verify the remaining pages */
25725 +cmp:
25726 +       this->data_poi = bufstart;
25727 +       ret = nand_verify_pages (mtd, this, startpage, totalpages,
25728 +               oobbuf, oobsel, chipnr, (eccbuf != NULL));
25729 +       if (!ret)
25730 +               *retlen = written;
25731 +       else    
25732 +               DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
25733 +
25734 +out:
25735 +       /* Deselect and wake up anyone waiting on the device */
25736 +       nand_release_chip(mtd);
25737 +
25738 +       return ret;
25739 +}
25740 +
25741 +
25742 +/**
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
25749 + *
25750 + * NAND write out-of-band
25751 + */
25752 +static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
25753 +{
25754 +       int column, page, status, ret = -EIO, chipnr;
25755 +       struct nand_chip *this = mtd->priv;
25756 +
25757 +       DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
25758 +
25759 +       /* Shift to get page */
25760 +       page = (int) (to >> this->page_shift);
25761 +       chipnr = (int) (to >> this->chip_shift);
25762 +
25763 +       /* Mask to get column */
25764 +       column = to & (mtd->oobsize - 1);
25765 +
25766 +       /* Initialize return length value */
25767 +       *retlen = 0;
25768 +
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");
25772 +               return -EINVAL;
25773 +       }
25774 +
25775 +       /* Grab the lock and see if the device is available */
25776 +       nand_get_chip (this, mtd, FL_WRITING);
25777 +
25778 +       /* Select the NAND device */
25779 +       this->select_chip(mtd, chipnr);
25780 +
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);
25787 +
25788 +       /* Check, if it is write protected */
25789 +       if (nand_check_wp(mtd))
25790 +               goto out;
25791 +       
25792 +       /* Invalidate the page cache, if we write to the cached page */
25793 +       if (page == this->pagebuf)
25794 +               this->pagebuf = -1;
25795 +
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);
25801 +               /* write data */
25802 +               this->write_buf(mtd, buf, len);
25803 +               /* postpad 0xff for partial programming */
25804 +               this->write_buf(mtd, ffchars, mtd->oobsize - (len+column));
25805 +       } else {
25806 +               /* Write out desired data */
25807 +               this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock + column, page & this->pagemask);
25808 +               /* write data */
25809 +               this->write_buf(mtd, buf, len);
25810 +       }
25811 +       /* Send command to program the OOB data */
25812 +       this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1);
25813 +
25814 +       status = this->waitfunc (mtd, this, FL_WRITING);
25815 +
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);
25819 +               ret = -EIO;
25820 +               goto out;
25821 +       }
25822 +       /* Return happy */
25823 +       *retlen = len;
25824 +
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);
25828 +
25829 +       if (this->verify_buf(mtd, buf, len)) {
25830 +               DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page);
25831 +               ret = -EIO;
25832 +               goto out;
25833 +       }
25834 +#endif
25835 +       ret = 0;
25836 +out:
25837 +       /* Deselect and wake up anyone waiting on the device */
25838 +       nand_release_chip(mtd);
25839 +
25840 +       return ret;
25841 +}
25842 +
25843 +
25844 +/**
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
25851 + *
25852 + * NAND write with kvec. This just calls the ecc function
25853 + */
25854 +static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, 
25855 +               loff_t to, size_t * retlen)
25856 +{
25857 +       return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL));    
25858 +}
25859 +
25860 +/**
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
25869 + *
25870 + * NAND write with iovec with ecc
25871 + */
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)
25874 +{
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;
25880 +
25881 +       /* Preset written len for early exit */
25882 +       *retlen = 0;
25883 +
25884 +       /* Calculate total length of data */
25885 +       total_len = 0;
25886 +       for (i = 0; i < count; i++)
25887 +               total_len += (int) vecs[i].iov_len;
25888 +
25889 +       DEBUG (MTD_DEBUG_LEVEL3,
25890 +              "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count);
25891 +
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");
25895 +               return -EINVAL;
25896 +       }
25897 +
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");
25901 +               return -EINVAL;
25902 +       }
25903 +
25904 +       /* Grab the lock and see if the device is available */
25905 +       nand_get_chip (this, mtd, FL_WRITING);
25906 +
25907 +       /* Get the current chip-nr */
25908 +       chipnr = (int) (to >> this->chip_shift);
25909 +       /* Select the NAND device */
25910 +       this->select_chip(mtd, chipnr);
25911 +
25912 +       /* Check, if it is write protected */
25913 +       if (nand_check_wp(mtd))
25914 +               goto out;
25915 +
25916 +       /* if oobsel is NULL, use chip defaults */
25917 +       if (oobsel == NULL) 
25918 +               oobsel = &mtd->oobinfo;         
25919 +
25920 +       /* Autoplace of oob data ? Use the default placement scheme */
25921 +       if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
25922 +               oobsel = this->autooob;
25923 +               autoplace = 1;
25924 +       }       
25925 +
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;
25931 +
25932 +       startpage = page & this->pagemask;
25933 +
25934 +       /* Loop until all kvec' data has been written */
25935 +       len = 0;
25936 +       while (count) {
25937 +               /* If the given tuple is >= pagesize then
25938 +                * write it out from the iov
25939 +                */
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;
25948 +                       bufstart += len;
25949 +                       this->data_poi = bufstart;
25950 +                       oob = 0;
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.
25955 +                                */
25956 +                               ret = nand_write_page (mtd, this, page & this->pagemask, 
25957 +                                       &oobbuf[oob], oobsel, i != numpages);
25958 +                               if (ret)
25959 +                                       goto out;
25960 +                               this->data_poi += mtd->oobblock;
25961 +                               len += mtd->oobblock;
25962 +                               oob += mtd->oobsize;
25963 +                               page++;
25964 +                       }
25965 +                       /* Check, if we have to switch to the next tuple */
25966 +                       if (len >= (int) vecs->iov_len) {
25967 +                               vecs++;
25968 +                               len = 0;
25969 +                               count--;
25970 +                       }
25971 +               } else {
25972 +                       /* We must use the internal buffer, read data out of each 
25973 +                        * tuple until we have a full page to write
25974 +                        */
25975 +                       int cnt = 0;
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) {
25981 +                                       vecs++;
25982 +                                       len = 0;
25983 +                                       count--;
25984 +                               }
25985 +                       }
25986 +                       this->pagebuf = page;   
25987 +                       this->data_poi = this->data_buf;        
25988 +                       bufstart = this->data_poi;
25989 +                       numpages = 1;           
25990 +                       oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);
25991 +                       ret = nand_write_page (mtd, this, page & this->pagemask,
25992 +                               oobbuf, oobsel, 0);
25993 +                       if (ret)
25994 +                               goto out;
25995 +                       page++;
25996 +               }
25997 +
25998 +               this->data_poi = bufstart;
25999 +               ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0);
26000 +               if (ret)
26001 +                       goto out;
26002 +                       
26003 +               written += mtd->oobblock * numpages;
26004 +               /* All done ? */
26005 +               if (!count)
26006 +                       break;
26007 +
26008 +               startpage = page & this->pagemask;
26009 +               /* Check, if we cross a chip boundary */
26010 +               if (!startpage) {
26011 +                       chipnr++;
26012 +                       this->select_chip(mtd, -1);
26013 +                       this->select_chip(mtd, chipnr);
26014 +               }
26015 +       }
26016 +       ret = 0;
26017 +out:
26018 +       /* Deselect and wake up anyone waiting on the device */
26019 +       nand_release_chip(mtd);
26020 +
26021 +       *retlen = written;
26022 +       return ret;
26023 +}
26024 +
26025 +/**
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
26029 + *
26030 + * Standard erase command for NAND chips
26031 + */
26032 +static void single_erase_cmd (struct mtd_info *mtd, int page)
26033 +{
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);
26038 +}
26039 +
26040 +/**
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
26044 + *
26045 + * AND multi block erase command function
26046 + * Erase 4 consecutive blocks
26047 + */
26048 +static void multi_erase_cmd (struct mtd_info *mtd, int page)
26049 +{
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);
26057 +}
26058 +
26059 +/**
26060 + * nand_erase - [MTD Interface] erase block(s)
26061 + * @mtd:       MTD device structure
26062 + * @instr:     erase instruction
26063 + *
26064 + * Erase one ore more blocks
26065 + */
26066 +static int nand_erase (struct mtd_info *mtd, struct erase_info *instr)
26067 +{
26068 +       return nand_erase_nand (mtd, instr, 0);
26069 +}
26070
26071 +/**
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
26076 + *
26077 + * Erase one ore more blocks
26078 + */
26079 +int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
26080 +{
26081 +       int page, len, status, pages_per_block, ret, chipnr;
26082 +       struct nand_chip *this = mtd->priv;
26083 +
26084 +       DEBUG (MTD_DEBUG_LEVEL3,
26085 +              "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len);
26086 +
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");
26090 +               return -EINVAL;
26091 +       }
26092 +
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");
26096 +               return -EINVAL;
26097 +       }
26098 +
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");
26102 +               return -EINVAL;
26103 +       }
26104 +
26105 +       instr->fail_addr = 0xffffffff;
26106 +
26107 +       /* Grab the lock and see if the device is available */
26108 +       nand_get_chip (this, mtd, FL_ERASING);
26109 +
26110 +       /* Shift to get first page */
26111 +       page = (int) (instr->addr >> this->page_shift);
26112 +       chipnr = (int) (instr->addr >> this->chip_shift);
26113 +
26114 +       /* Calculate pages in each block */
26115 +       pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
26116 +
26117 +       /* Select the NAND device */
26118 +       this->select_chip(mtd, chipnr);
26119 +
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;
26125 +               goto erase_exit;
26126 +       }
26127 +
26128 +       /* Loop through the pages */
26129 +       len = instr->len;
26130 +
26131 +       instr->state = MTD_ERASING;
26132 +
26133 +       while (len) {
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;
26138 +                       goto erase_exit;
26139 +               }
26140 +               
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;
26145 +
26146 +               this->erase_cmd (mtd, page & this->pagemask);
26147 +               
26148 +               status = this->waitfunc (mtd, this, FL_ERASING);
26149 +
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);
26155 +                       goto erase_exit;
26156 +               }
26157 +               
26158 +               /* Increment page address and decrement length */
26159 +               len -= (1 << this->phys_erase_shift);
26160 +               page += pages_per_block;
26161 +
26162 +               /* Check, if we cross a chip boundary */
26163 +               if (len && !(page & this->pagemask)) {
26164 +                       chipnr++;
26165 +                       this->select_chip(mtd, -1);
26166 +                       this->select_chip(mtd, chipnr);
26167 +               }
26168 +       }
26169 +       instr->state = MTD_ERASE_DONE;
26170 +
26171 +erase_exit:
26172 +
26173 +       ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
26174 +       /* Do call back function */
26175 +       if (!ret)
26176 +               mtd_erase_callback(instr);
26177 +
26178 +       /* Deselect and wake up anyone waiting on the device */
26179 +       nand_release_chip(mtd);
26180 +
26181 +       /* Return more or less happy */
26182 +       return ret;
26183 +}
26184 +
26185 +/**
26186 + * nand_sync - [MTD Interface] sync
26187 + * @mtd:       MTD device structure
26188 + *
26189 + * Sync is actually a wait for chip ready function
26190 + */
26191 +static void nand_sync (struct mtd_info *mtd)
26192 +{
26193 +       struct nand_chip *this = mtd->priv;
26194 +       DECLARE_WAITQUEUE (wait, current);
26195 +
26196 +       DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n");
26197 +
26198 +retry:
26199 +       /* Grab the spinlock */
26200 +       spin_lock_bh (&this->chip_lock);
26201 +
26202 +       /* See what's going on */
26203 +       switch (this->state) {
26204 +       case FL_READY:
26205 +       case FL_SYNCING:
26206 +               this->state = FL_SYNCING;
26207 +               spin_unlock_bh (&this->chip_lock);
26208 +               break;
26209 +
26210 +       default:
26211 +               /* Not an idle state */
26212 +               add_wait_queue (&this->wq, &wait);
26213 +               spin_unlock_bh (&this->chip_lock);
26214 +               schedule ();
26215 +
26216 +               remove_wait_queue (&this->wq, &wait);
26217 +               goto retry;
26218 +       }
26219 +
26220 +       /* Lock the device */
26221 +       spin_lock_bh (&this->chip_lock);
26222 +
26223 +       /* Set the device to be ready again */
26224 +       if (this->state == FL_SYNCING) {
26225 +               this->state = FL_READY;
26226 +               wake_up (&this->wq);
26227 +       }
26228 +
26229 +       /* Unlock the device */
26230 +       spin_unlock_bh (&this->chip_lock);
26231 +}
26232 +
26233 +
26234 +/**
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
26238 + */
26239 +static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs)
26240 +{
26241 +       /* Check for invalid offset */
26242 +       if (ofs > mtd->size) 
26243 +               return -EINVAL;
26244 +       
26245 +       return nand_block_checkbad (mtd, ofs, 1, 0);
26246 +}
26247 +
26248 +/**
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
26252 + */
26253 +static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs)
26254 +{
26255 +       struct nand_chip *this = mtd->priv;
26256 +       int ret;
26257 +
26258 +        if ((ret = nand_block_isbad(mtd, ofs))) {
26259 +               /* If it was bad already, return success and do nothing. */
26260 +               if (ret > 0)
26261 +                       return 0;
26262 +               return ret;
26263 +        }
26264 +
26265 +       return this->block_markbad(mtd, ofs);
26266 +}
26267 +
26268 +/**
26269 + * nand_scan - [NAND Interface] Scan for the NAND device
26270 + * @mtd:       MTD device structure
26271 + * @maxchips:  Number of chips to scan for
26272 + *
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
26278 + *
26279 + */
26280 +int nand_scan (struct mtd_info *mtd, int maxchips)
26281 +{
26282 +       int i, j, nand_maf_id, nand_dev_id, busw;
26283 +       struct nand_chip *this = mtd->priv;
26284 +
26285 +       /* Get buswidth to select the correct functions*/
26286 +       busw = this->options & NAND_BUSWIDTH_16;
26287 +
26288 +       /* check for proper chip_delay setup, set 20us if not */
26289 +       if (!this->chip_delay)
26290 +               this->chip_delay = 20;
26291 +
26292 +       /* check, if a user supplied command function given */
26293 +       if (this->cmdfunc == NULL)
26294 +               this->cmdfunc = nand_command;
26295 +
26296 +       /* check, if a user supplied wait function given */
26297 +       if (this->waitfunc == NULL)
26298 +               this->waitfunc = nand_wait;
26299 +
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;
26322 +
26323 +       /* Select the device */
26324 +       this->select_chip(mtd, 0);
26325 +
26326 +       /* Send the command for reading device ID */
26327 +       this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
26328 +
26329 +       /* Read manufacturer and device IDs */
26330 +       nand_maf_id = this->read_byte(mtd);
26331 +       nand_dev_id = this->read_byte(mtd);
26332 +
26333 +       /* Print and store flash device information */
26334 +       for (i = 0; nand_flash_ids[i].name != NULL; i++) {
26335 +                               
26336 +               if (nand_dev_id != nand_flash_ids[i].id) 
26337 +                       continue;
26338 +
26339 +               if (!mtd->name) mtd->name = nand_flash_ids[i].name;
26340 +               this->chipsize = nand_flash_ids[i].chipsize << 20;
26341 +               
26342 +               /* New devices have all the information in additional id bytes */
26343 +               if (!nand_flash_ids[i].pagesize) {
26344 +                       int extid;
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);
26351 +                       extid >>= 2;
26352 +                       /* Calc oobsize */
26353 +                       mtd->oobsize = (8 << (extid & 0x03)) * (mtd->oobblock / 512);
26354 +                       extid >>= 2;
26355 +                       /* Calc blocksize. Blocksize is multiples of 64KiB */
26356 +                       mtd->erasesize = (64 * 1024)  << (extid & 0x03);
26357 +                       extid >>= 2;
26358 +                       /* Get buswidth information */
26359 +                       busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
26360 +               
26361 +               } else {
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;
26368 +               }
26369 +
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,
26379 +                                       busw ? 16 : 8);
26380 +                       this->select_chip(mtd, -1);
26381 +                       return 1;       
26382 +               }
26383 +               
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;
26388 +
26389 +               /* Set the bad block position */
26390 +               this->badblockpos = mtd->oobblock > 512 ? 
26391 +                       NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
26392 +
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.
26400 +                */     
26401 +               if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
26402 +                       this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
26403 +               
26404 +               /* Check for AND chips with 4 page planes */
26405 +               if (this->options & NAND_4PAGE_ARRAY)
26406 +                       this->erase_cmd = multi_erase_cmd;
26407 +               else
26408 +                       this->erase_cmd = single_erase_cmd;
26409 +
26410 +               /* Do not replace user supplied command function ! */
26411 +               if (mtd->oobblock > 512 && this->cmdfunc == nand_command)
26412 +                       this->cmdfunc = nand_command_lp;
26413 +                               
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)
26417 +                               break;
26418 +               }
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);
26422 +               break;
26423 +       }
26424 +
26425 +       if (!nand_flash_ids[i].name) {
26426 +               printk (KERN_WARNING "No NAND device found!!!\n");
26427 +               this->select_chip(mtd, -1);
26428 +               return 1;
26429 +       }
26430 +
26431 +       for (i=1; i < maxchips; i++) {
26432 +               this->select_chip(mtd, i);
26433 +
26434 +               /* Send the command for reading device ID */
26435 +               this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
26436 +
26437 +               /* Read manufacturer and device IDs */
26438 +               if (nand_maf_id != this->read_byte(mtd) ||
26439 +                   nand_dev_id != this->read_byte(mtd))
26440 +                       break;
26441 +       }
26442 +       if (i > 1)
26443 +               printk(KERN_INFO "%d NAND chips detected\n", i);
26444 +       
26445 +       /* Allocate buffers, if neccecary */
26446 +       if (!this->oob_buf) {
26447 +               size_t len;
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");
26452 +                       return -ENOMEM;
26453 +               }
26454 +               this->options |= NAND_OOBBUF_ALLOC;
26455 +       }
26456 +       
26457 +       if (!this->data_buf) {
26458 +               size_t len;
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");
26465 +                       return -ENOMEM;
26466 +               }
26467 +               this->options |= NAND_DATABUF_ALLOC;
26468 +       }
26469 +
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));
26477 +
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) { 
26484 +               case 8:
26485 +                       this->autooob = &nand_oob_8;
26486 +                       break;
26487 +               case 16:
26488 +                       this->autooob = &nand_oob_16;
26489 +                       break;
26490 +               case 64:
26491 +                       this->autooob = &nand_oob_64;
26492 +                       break;
26493 +               default:
26494 +                       printk (KERN_WARNING "No oob scheme defined for oobsize %d\n",
26495 +                               mtd->oobsize);
26496 +                       BUG();
26497 +               }
26498 +       }
26499 +       
26500 +       /* The number of bytes available for the filesystem to place fs dependend
26501 +        * oob data */
26502 +       if (this->options & NAND_BUSWIDTH_16) {
26503 +               mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 2);
26504 +               if (this->autooob->eccbytes & 0x01)
26505 +                       mtd->oobavail--;
26506 +       } else
26507 +               mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1);
26508 +
26509 +       /* 
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 
26513 +       */
26514 +       this->eccsize = 256;    /* set default eccsize */       
26515 +
26516 +       switch (this->eccmode) {
26517 +
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;
26526 +                       break;          
26527 +               } else 
26528 +                       this->eccsize = 512; /* set eccsize to 512 and fall through for function check */
26529 +
26530 +       case NAND_ECC_HW3_256:
26531 +               if (this->calculate_ecc && this->correct_data && this->enable_hwecc)
26532 +                       break;
26533 +               printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n");
26534 +               BUG();  
26535 +
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;
26539 +               break;
26540 +
26541 +       case NAND_ECC_SOFT:     
26542 +               this->calculate_ecc = nand_calculate_ecc;
26543 +               this->correct_data = nand_correct_data;
26544 +               break;
26545 +
26546 +       default:
26547 +               printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
26548 +               BUG();  
26549 +       }       
26550 +       
26551 +       mtd->eccsize = this->eccsize;
26552 +       
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;
26559 +               break;
26560 +       case NAND_ECC_HW3_256:
26561 +       case NAND_ECC_SOFT:     
26562 +               this->eccsteps = mtd->oobblock / 256;
26563 +               break;
26564 +               
26565 +       case NAND_ECC_NONE: 
26566 +               this->eccsteps = 1;
26567 +               break;
26568 +       }
26569 +       
26570 +       /* Initialize state, waitqueue and spinlock */
26571 +       this->state = FL_READY;
26572 +       init_waitqueue_head (&this->wq);
26573 +       spin_lock_init (&this->chip_lock);
26574 +
26575 +       /* De-select the device */
26576 +       this->select_chip(mtd, -1);
26577 +
26578 +       /* Invalidate the pagebuffer reference */
26579 +       this->pagebuf = -1;
26580 +
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;
26604 +
26605 +       /* and make the autooob the default one */
26606 +       memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
26607 +
26608 +       mtd->owner = THIS_MODULE;
26609 +
26610 +       /* Build bad block table */
26611 +       return this->scan_bbt (mtd);
26612 +}
26613 +
26614 +/**
26615 + * nand_release - [NAND Interface] Free resources held by the NAND device 
26616 + * @mtd:       MTD device structure
26617 +*/
26618 +void nand_release (struct mtd_info *mtd)
26619 +{
26620 +       struct nand_chip *this = mtd->priv;
26621 +
26622 +#ifdef CONFIG_MTD_PARTITIONS
26623 +       /* Deregister partitions */
26624 +       del_mtd_partitions (mtd);
26625 +#endif
26626 +       /* Deregister the device */
26627 +       del_mtd_device (mtd);
26628 +
26629 +       /* Free bad block table memory, if allocated */
26630 +       if (this->bbt)
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);
26638 +}
26639 +
26640 +EXPORT_SYMBOL (nand_scan);
26641 +EXPORT_SYMBOL (nand_release);
26642 +
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
26650 @@ -0,0 +1,1053 @@
26651 +/*
26652 + *  drivers/mtd/nand_bbt.c
26653 + *
26654 + *  Overview:
26655 + *   Bad block table support for the NAND driver
26656 + *   
26657 + *  Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
26658 + *
26659 + * $Id: nand_bbt.c,v 1.24 2004/06/28 08:25:35 gleixner Exp $
26660 + *
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.
26664 + *
26665 + * Description:
26666 + *
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. 
26677 + *
26678 + * For manufacturer created bbts like the one found on M-SYS DOC devices 
26679 + * the bbt is searched and read but never created
26680 + *
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.
26685 + *
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
26690 + *
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
26696 + * 
26697 + * Multichip devices like DOC store the bad block info per floor.
26698 + *
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
26702 + * 
26703 + */
26704 +
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>
26713 +
26714 +
26715 +/** 
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
26721 + *
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
26726 + *
26727 +*/
26728 +static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
26729 +{
26730 +       int i, end;
26731 +       uint8_t *p = buf;
26732 +
26733 +       end = paglen + td->offs;
26734 +       if (td->options & NAND_BBT_SCANEMPTY) {
26735 +               for (i = 0; i < end; i++) {
26736 +                       if (p[i] != 0xff)
26737 +                               return -1;
26738 +               }
26739 +       }       
26740 +       p += end;
26741 +       
26742 +       /* Compare the pattern */
26743 +       for (i = 0; i < td->len; i++) {
26744 +               if (p[i] != td->pattern[i])
26745 +                       return -1;
26746 +       }
26747 +
26748 +       p += td->len;
26749 +       end += td->len;
26750 +       if (td->options & NAND_BBT_SCANEMPTY) {
26751 +               for (i = end; i < len; i++) {
26752 +                       if (*p++ != 0xff)
26753 +                               return -1;
26754 +               }
26755 +       }
26756 +       return 0;
26757 +}
26758 +
26759 +/**
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
26767 + *
26768 + * Read the bad block table starting from page.
26769 + *
26770 + */
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)
26773 +{
26774 +       int res, i, j, act = 0;
26775 +       struct nand_chip *this = mtd->priv;
26776 +       size_t retlen, len, totlen;
26777 +       loff_t from;
26778 +       uint8_t msk = (uint8_t) ((1 << bits) - 1);
26779 +
26780 +       totlen = (num * bits) >> 3;
26781 +       from = ((loff_t)page) << this->page_shift;
26782 +       
26783 +       while (totlen) {
26784 +               len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
26785 +               res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
26786 +               if (res < 0) {
26787 +                       if (retlen != len) {
26788 +                               printk (KERN_INFO "nand_bbt: Error reading bad block table\n");
26789 +                               return res;
26790 +                       }
26791 +                       printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
26792 +               }       
26793 +
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;
26799 +                               if (tmp == msk)
26800 +                                       continue;
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);
26806 +                                       continue;
26807 +                               }
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 ? */  
26813 +                               if (tmp == 0)
26814 +                                       this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
26815 +                               else
26816 +                                       this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
26817 +                       }       
26818 +               }
26819 +               totlen -= len;
26820 +               from += len;
26821 +       }
26822 +       return 0;
26823 +}
26824 +
26825 +/**
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
26832 + *
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.
26835 +*/
26836 +static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
26837 +{
26838 +       struct nand_chip *this = mtd->priv;
26839 +       int res = 0, i;
26840 +       int bits;
26841 +
26842 +       bits = td->options & NAND_BBT_NRBITS_MSK;
26843 +       if (td->options & NAND_BBT_PERCHIP) {
26844 +               int offs = 0;
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);
26848 +                       if (res)
26849 +                               return res;
26850 +                       offs += this->chipsize >> (this->bbt_erase_shift + 2);
26851 +               }
26852 +       } else {
26853 +               res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code);
26854 +               if (res)
26855 +                       return res;
26856 +       }
26857 +       return 0;
26858 +}
26859 +
26860 +/**
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
26866 + *
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.
26869 + *
26870 +*/
26871 +static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td,
26872 +       struct nand_bbt_descr *md)
26873 +{
26874 +       struct nand_chip *this = mtd->priv;
26875 +
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]);
26881 +       }
26882 +
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]);
26888 +       }
26889 +
26890 +       return 1;
26891 +}
26892 +
26893 +/**
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
26900 + *
26901 + * Create a bad block table by scanning the device
26902 + * for the given good/bad block identify pattern
26903 + */
26904 +static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
26905 +{
26906 +       struct nand_chip *this = mtd->priv;
26907 +       int i, j, numblocks, len, scanlen;
26908 +       int startblock;
26909 +       loff_t from;
26910 +       size_t readlen, ooblen;
26911 +
26912 +       printk (KERN_INFO "Scanning device for bad blocks\n");
26913 +
26914 +       if (bd->options & NAND_BBT_SCANALLPAGES)
26915 +               len = 1 << (this->bbt_erase_shift - this->page_shift);
26916 +       else {
26917 +               if (bd->options & NAND_BBT_SCAN2NDPAGE)
26918 +                       len = 2;
26919 +               else    
26920 +                       len = 1;
26921 +       }
26922 +       scanlen = mtd->oobblock + mtd->oobsize;
26923 +       readlen = len * mtd->oobblock;
26924 +       ooblen = len * mtd->oobsize;
26925 +
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);
26930 +               startblock = 0;
26931 +               from = 0;
26932 +       } else {
26933 +               if (chip >= this->numchips) {
26934 +                       printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
26935 +                               chip + 1, this->numchips);
26936 +                       return; 
26937 +               }
26938 +               numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
26939 +               startblock = chip * numblocks;
26940 +               numblocks += startblock;
26941 +               from = startblock << (this->bbt_erase_shift - 1);
26942 +       }
26943 +       
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);
26951 +                               break;
26952 +                       }
26953 +               }
26954 +               i += 2;
26955 +               from += (1 << this->bbt_erase_shift);
26956 +       }
26957 +}
26958 +
26959 +/**
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
26964 + *
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
26968 + * block.
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.
26972 + *
26973 + * The bbt ident pattern resides in the oob area of the first page 
26974 + * in a block. 
26975 + */
26976 +static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
26977 +{
26978 +       struct nand_chip *this = mtd->priv;
26979 +       int i, chips;
26980 +       int bits, startblock, block, dir;
26981 +       int scanlen = mtd->oobblock + mtd->oobsize;
26982 +       int bbtblocks;
26983 +
26984 +       /* Search direction top -> down ? */
26985 +       if (td->options & NAND_BBT_LASTBLOCK) {
26986 +               startblock = (mtd->size >> this->bbt_erase_shift) -1;
26987 +               dir = -1;
26988 +       } else {
26989 +               startblock = 0; 
26990 +               dir = 1;
26991 +       }       
26992 +       
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;
26998 +       } else {
26999 +               chips = 1;
27000 +               bbtblocks = mtd->size >> this->bbt_erase_shift;
27001 +       }
27002 +       
27003 +       /* Number of bits for each erase block in the bbt */
27004 +       bits = td->options & NAND_BBT_NRBITS_MSK;
27005 +       
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];
27019 +                               }
27020 +                               break;
27021 +                       }
27022 +               }
27023 +               startblock += this->chipsize >> this->bbt_erase_shift;
27024 +       }
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);
27029 +               else
27030 +                       printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]);
27031 +       }
27032 +       return 0;       
27033 +}
27034 +
27035 +/**
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
27041 + *
27042 + * Search and read the bad block table(s)
27043 +*/
27044 +static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, 
27045 +       struct nand_bbt_descr *td, struct nand_bbt_descr *md)
27046 +{
27047 +       /* Search the primary table */
27048 +       search_bbt (mtd, buf, td);
27049 +               
27050 +       /* Search the mirror table */
27051 +       if (md)
27052 +               search_bbt (mtd, buf, md);
27053 +       
27054 +       /* Force result check */
27055 +       return 1;       
27056 +}
27057 +       
27058 +
27059 +/** 
27060 + * write_bbt - [GENERIC] (Re)write the bad block table
27061 + *
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
27067 + *
27068 + * (Re)write the bad block table
27069 + *
27070 +*/
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)
27073 +{
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;
27080 +       uint8_t msk[4];
27081 +       uint8_t rcode = td->reserved_block_code;
27082 +       size_t retlen, len = 0;
27083 +       loff_t to;
27084 +
27085 +       if (!rcode)
27086 +               rcode = 0xff;
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;
27093 +               } else {
27094 +                       nrchips = chipsel + 1;
27095 +                       chip = chipsel;
27096 +               }
27097 +       } else {
27098 +               numblocks = (int) (mtd->size >> this->bbt_erase_shift);
27099 +               nrchips = 1;
27100 +       }       
27101 +       
27102 +       /* Loop through the chips */
27103 +       for (; chip < nrchips; chip++) {
27104 +               
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.
27108 +                */
27109 +               if (td->pages[chip] != -1) {
27110 +                       page = td->pages[chip];
27111 +                       goto write;
27112 +               }       
27113 +
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;
27118 +                       dir = -1;
27119 +               } else {
27120 +                       startblock = chip * numblocks;
27121 +                       dir = 1;
27122 +               }       
27123 +
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) {
27128 +                       case 0x01:
27129 +                       case 0x03:
27130 +                               continue;
27131 +                       }
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)
27135 +                               goto write;
27136 +               }
27137 +               printk (KERN_ERR "No space left to write bad block table\n");
27138 +               return -ENOSPC;
27139 +write: 
27140 +
27141 +               /* Set up shift count and masks for the flash table */
27142 +               bits = td->options & NAND_BBT_NRBITS_MSK;
27143 +               switch (bits) {
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;
27149 +               }
27150 +               
27151 +               bbtoffs = chip * (numblocks >> 2);
27152 +               
27153 +               to = ((loff_t) page) << this->page_shift;
27154 +
27155 +               memcpy (&oobinfo, this->autooob, sizeof(oobinfo));
27156 +               oobinfo.useecc = MTD_NANDECC_PLACEONLY;
27157 +               
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);
27164 +                       if (res < 0) {
27165 +                               if (retlen != len) {
27166 +                                       printk (KERN_INFO "nand_bbt: Error reading block for writing the bad block table\n");
27167 +                                       return res;
27168 +                               }
27169 +                               printk (KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n");
27170 +                       }
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];
27181 +                       }
27182 +               } else {
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);
27189 +                       offs = 0;
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];
27194 +                       }
27195 +               }
27196 +       
27197 +               /* walk through the memory table */
27198 +               for (i = 0; i < numblocks; ) {
27199 +                       uint8_t dat;
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);
27205 +                               dat >>= 2;
27206 +                       }
27207 +               }
27208 +               
27209 +               memset (&einfo, 0, sizeof (einfo));
27210 +               einfo.mtd = mtd;
27211 +               einfo.addr = (unsigned long) to;
27212 +               einfo.len = 1 << this->bbt_erase_shift;
27213 +               res = nand_erase_nand (mtd, &einfo, 1);
27214 +               if (res < 0) {
27215 +                       printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
27216 +                       return res;
27217 +               }
27218 +       
27219 +               res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
27220 +               if (res < 0) {
27221 +                       printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
27222 +                       return res;
27223 +               }
27224 +               printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", 
27225 +                       (unsigned int) to, td->version[chip]);
27226 +       
27227 +               /* Mark it as used */
27228 +               td->pages[chip] = page;
27229 +       }       
27230 +       return 0;
27231 +}
27232 +
27233 +/**
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
27237 + *
27238 + * The function creates a memory based bbt by scanning the device 
27239 + * for manufacturer / software marked good / bad blocks
27240 +*/
27241 +static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
27242 +{
27243 +       struct nand_chip *this = mtd->priv;
27244 +
27245 +       /* Ensure that we only scan for the pattern and nothing else */
27246 +       bd->options = 0;
27247 +       create_bbt (mtd, this->data_buf, bd, -1);
27248 +       return 0;
27249 +}
27250 +
27251 +/**
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
27256 + *
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
27262 +*/
27263 +static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
27264 +{
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;
27270 +
27271 +       /* Do we have a bbt per chip ? */
27272 +       if (td->options & NAND_BBT_PERCHIP) 
27273 +               chips = this->numchips;
27274 +       else 
27275 +               chips = 1;
27276 +       
27277 +       for (i = 0; i < chips; i++) {
27278 +               writeops = 0;
27279 +               rd = NULL;
27280 +               rd2 = NULL;
27281 +               /* Per chip or per device ? */
27282 +               chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
27283 +               /* Mirrored table avilable ? */
27284 +               if (md) {
27285 +                       if (td->pages[i] == -1 && md->pages[i] == -1) {
27286 +                               writeops = 0x03;
27287 +                               goto create;
27288 +                       }
27289 +
27290 +                       if (td->pages[i] == -1) {
27291 +                               rd = md;                                
27292 +                               td->version[i] = md->version[i];
27293 +                               writeops = 1;
27294 +                               goto writecheck;
27295 +                       }
27296 +
27297 +                       if (md->pages[i] == -1) {
27298 +                               rd = td;
27299 +                               md->version[i] = td->version[i];
27300 +                               writeops = 2;
27301 +                               goto writecheck;
27302 +                       }
27303 +
27304 +                       if (td->version[i] == md->version[i]) {
27305 +                               rd = td;
27306 +                               if (!(td->options & NAND_BBT_VERSION))
27307 +                                       rd2 = md;
27308 +                               goto writecheck;
27309 +                       }       
27310 +
27311 +                       if (((int8_t) (td->version[i] - md->version[i])) > 0) {
27312 +                               rd = td;
27313 +                               md->version[i] = td->version[i];
27314 +                               writeops = 2;
27315 +                       } else {
27316 +                               rd = md;
27317 +                               td->version[i] = md->version[i];
27318 +                               writeops = 1;
27319 +                       }
27320 +
27321 +                       goto writecheck;
27322 +
27323 +               } else {
27324 +                       if (td->pages[i] == -1) {
27325 +                               writeops = 0x01;
27326 +                               goto create;
27327 +                       }
27328 +                       rd = td;
27329 +                       goto writecheck;
27330 +               }
27331 +create:
27332 +               /* Create the bad block table by scanning the device ? */
27333 +               if (!(td->options & NAND_BBT_CREATE))
27334 +                       continue;       
27335 +               
27336 +               /* Create the table in memory by scanning the chip(s) */
27337 +               create_bbt (mtd, buf, bd, chipsel);
27338 +               
27339 +               td->version[i] = 1;
27340 +               if (md)
27341 +                       md->version[i] = 1;     
27342 +writecheck:    
27343 +               /* read back first ? */
27344 +               if (rd)
27345 +                       read_abs_bbt (mtd, buf, rd, chipsel);
27346 +               /* If they weren't versioned, read both. */
27347 +               if (rd2)
27348 +                       read_abs_bbt (mtd, buf, rd2, chipsel);
27349 +
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);
27353 +                       if (res < 0)
27354 +                               return res;
27355 +               }
27356 +               
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);
27360 +                       if (res < 0)
27361 +                               return res;
27362 +               }
27363 +       }
27364 +       return 0;       
27365 +}
27366 +
27367 +/**
27368 + * mark_bbt_regions - [GENERIC] mark the bad block table regions 
27369 + * @mtd:       MTD device structure
27370 + * @td:                bad block table descriptor
27371 + *
27372 + * The bad block table regions are marked as "bad" to prevent
27373 + * accidental erasures / writes. The regions are identified by
27374 + * the mark 0x02.
27375 +*/
27376 +static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
27377 +{
27378 +       struct nand_chip *this = mtd->priv;
27379 +       int i, j, chips, block, nrblocks, update;
27380 +       uint8_t oldval, newval;
27381 +
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);
27386 +       } else {
27387 +               chips = 1;
27388 +               nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
27389 +       }       
27390 +       
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);
27396 +                       block <<= 1;            
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));
27402 +                       continue;
27403 +               }
27404 +               update = 0;
27405 +               if (td->options & NAND_BBT_LASTBLOCK)
27406 +                       block = ((i + 1) * nrblocks) - td->maxblocks;
27407 +               else    
27408 +                       block = i * nrblocks;
27409 +               block <<= 1;    
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;
27415 +                       block += 2;
27416 +               }       
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));
27422 +       }
27423 +}
27424 +
27425 +/**
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
27429 + *
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.
27434 + *
27435 + * The bad block table memory is allocated here. It must be freed
27436 + * by calling the nand_free_bbt function.
27437 + *
27438 +*/
27439 +int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
27440 +{
27441 +       struct nand_chip *this = mtd->priv;
27442 +       int len, res = 0;
27443 +       uint8_t *buf;
27444 +       struct nand_bbt_descr *td = this->bbt_td;
27445 +       struct nand_bbt_descr *md = this->bbt_md;
27446 +
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");
27452 +               return -ENOMEM;
27453 +       }
27454 +       /* Clear the memory bad block table */
27455 +       memset (this->bbt, 0x00, len);
27456 +
27457 +       /* If no primary table decriptor is given, scan the device
27458 +        * to build a memory based bad block table
27459 +        */
27460 +       if (!td)
27461 +               return nand_memory_bbt(mtd, bd);
27462 +
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);
27467 +       if (!buf) {
27468 +               printk (KERN_ERR "nand_bbt: Out of memory\n");
27469 +               kfree (this->bbt);
27470 +               this->bbt = NULL;
27471 +               return -ENOMEM;
27472 +       }
27473 +       
27474 +       /* Is the bbt at a given page ? */
27475 +       if (td->options & NAND_BBT_ABSPAGE) {
27476 +               res = read_abs_bbts (mtd, buf, td, md);
27477 +       } else {        
27478 +               /* Search the bad block table using a pattern in oob */
27479 +               res = search_read_bbts (mtd, buf, td, md);
27480 +       }       
27481 +
27482 +       if (res) 
27483 +               res = check_create (mtd, buf, bd);
27484 +       
27485 +       /* Prevent the bbt regions from erasing / writing */
27486 +       mark_bbt_region (mtd, td);
27487 +       if (md)
27488 +               mark_bbt_region (mtd, md);
27489 +       
27490 +       kfree (buf);
27491 +       return res;
27492 +}
27493 +
27494 +
27495 +/**
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
27499 + *
27500 + * The function updates the bad block table(s)
27501 +*/
27502 +int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
27503 +{
27504 +       struct nand_chip *this = mtd->priv;
27505 +       int len, res = 0, writeops = 0;
27506 +       int chip, chipsel;
27507 +       uint8_t *buf;
27508 +       struct nand_bbt_descr *td = this->bbt_td;
27509 +       struct nand_bbt_descr *md = this->bbt_md;
27510 +
27511 +       if (!this->bbt || !td)
27512 +               return -EINVAL;
27513 +
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);
27519 +       if (!buf) {
27520 +               printk (KERN_ERR "nand_update_bbt: Out of memory\n");
27521 +               return -ENOMEM;
27522 +       }
27523 +       
27524 +       writeops = md != NULL ? 0x03 : 0x01;
27525 +
27526 +       /* Do we have a bbt per chip ? */
27527 +       if (td->options & NAND_BBT_PERCHIP) {
27528 +               chip = (int) (offs >> this->chip_shift);
27529 +               chipsel = chip;
27530 +       } else {
27531 +               chip = 0;
27532 +               chipsel = -1;
27533 +       }
27534 +
27535 +       td->version[chip]++;
27536 +       if (md)
27537 +               md->version[chip]++;    
27538 +
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);
27542 +               if (res < 0)
27543 +                       goto out;
27544 +       }
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);
27548 +       }
27549 +
27550 +out:   
27551 +       kfree (buf);
27552 +       return res;
27553 +}
27554 +
27555 +/* Define some generic bad / good block scan pattern which are used 
27556 + * while scanning a device for factory marked good / bad blocks
27557 + * 
27558 + * The memory based patterns just 
27559 + */
27560 +static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
27561 +
27562 +static struct nand_bbt_descr smallpage_memorybased = {
27563 +       .options = 0,
27564 +       .offs = 5,
27565 +       .len = 1,
27566 +       .pattern = scan_ff_pattern
27567 +};
27568 +
27569 +static struct nand_bbt_descr largepage_memorybased = {
27570 +       .options = 0,
27571 +       .offs = 0,
27572 +       .len = 2,
27573 +       .pattern = scan_ff_pattern
27574 +};
27575 +
27576 +static struct nand_bbt_descr smallpage_flashbased = {
27577 +       .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
27578 +       .offs = 5,
27579 +       .len = 1,
27580 +       .pattern = scan_ff_pattern
27581 +};
27582 +
27583 +static struct nand_bbt_descr largepage_flashbased = {
27584 +       .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
27585 +       .offs = 0,
27586 +       .len = 2,
27587 +       .pattern = scan_ff_pattern
27588 +};
27589 +
27590 +static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
27591 +
27592 +static struct nand_bbt_descr agand_flashbased = {
27593 +       .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
27594 +       .offs = 0x20,
27595 +       .len = 6,
27596 +       .pattern = scan_agand_pattern
27597 +};
27598 +
27599 +/* Generic flash bbt decriptors
27600 +*/
27601 +static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
27602 +static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
27603 +
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,
27607 +       .offs = 8,
27608 +       .len = 4,
27609 +       .veroffs = 12,
27610 +       .maxblocks = 4,
27611 +       .pattern = bbt_pattern
27612 +};
27613 +
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,
27617 +       .offs = 8,
27618 +       .len = 4,
27619 +       .veroffs = 12,
27620 +       .maxblocks = 4,
27621 +       .pattern = mirror_pattern
27622 +};
27623 +
27624 +/**
27625 + * nand_default_bbt - [NAND Interface] Select a default bad block table for the device 
27626 + * @mtd:       MTD device structure
27627 + *
27628 + * This function selects the default bad block table
27629 + * support for the device and calls the nand_scan_bbt function
27630 + *
27631 +*/
27632 +int nand_default_bbt (struct mtd_info *mtd)
27633 +{
27634 +       struct nand_chip *this = mtd->priv;
27635 +       
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 
27641 +        * startup
27642 +       */
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;
27648 +               }       
27649 +               this->options |= NAND_USE_FLASH_BBT;
27650 +               return nand_scan_bbt (mtd, &agand_flashbased);
27651 +       }
27652 +       
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;
27659 +               }       
27660 +               if (mtd->oobblock > 512)
27661 +                       return nand_scan_bbt (mtd, &largepage_flashbased);
27662 +               else    
27663 +                       return nand_scan_bbt (mtd, &smallpage_flashbased);                      
27664 +       } else {
27665 +               this->bbt_td = NULL;
27666 +               this->bbt_md = NULL;
27667 +               if (mtd->oobblock > 512)
27668 +                       return nand_scan_bbt (mtd, &largepage_memorybased);
27669 +               else
27670 +                       return nand_scan_bbt (mtd, &smallpage_memorybased);
27671 +       }
27672 +}
27673 +
27674 +/**
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
27679 + *
27680 +*/
27681 +int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
27682 +{
27683 +       struct nand_chip *this = mtd->priv;
27684 +       int block;
27685 +       uint8_t res;
27686 +       
27687 +       /* Get block number * 2 */
27688 +       block = (int) (offs >> (this->bbt_erase_shift - 1));
27689 +       res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
27690 +
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);
27693 +
27694 +       switch ((int)res) {
27695 +       case 0x00:      return 0;
27696 +       case 0x01:      return 1;
27697 +       case 0x02:      return allowbbt ? 0 : 1;
27698 +       }
27699 +       return 1;
27700 +}
27701 +
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
27708 @@ -1,22 +1,44 @@
27709  /*
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.
27713   *
27714 - *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
27715 - *                     Toshiba America Electronics Components, Inc.
27716 + * drivers/mtd/nand/nand_ecc.c
27717   *
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.
27721   *
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 $
27726   *
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
27732 + * later version.
27733 + * 
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.
27738 + * 
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.
27742 + * 
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.
27750 + * 
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.
27753   */
27754  
27755  #include <linux/types.h>
27756  #include <linux/kernel.h>
27757  #include <linux/module.h>
27758 +#include <linux/mtd/nand_ecc.h>
27759  
27760  /*
27761   * Pre-calculated 256-way 1 byte column parity
27762 @@ -41,7 +63,12 @@
27763  };
27764  
27765  
27766 -/*
27767 +/**
27768 + * nand_trans_result - [GENERIC] create non-inverted ECC
27769 + * @reg2:      line parity reg 2
27770 + * @reg3:      line parity reg 3
27771 + * @ecc_code:  ecc 
27772 + *
27773   * Creates non-inverted ECC code from line parity
27774   */
27775  static void nand_trans_result(u_char reg2, u_char reg3,
27776 @@ -81,10 +108,13 @@
27777         ecc_code[1] = tmp2;
27778  }
27779  
27780 -/*
27781 - * Calculate 3 byte ECC code for 256 byte block
27782 +/**
27783 + * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block
27784 + * @mtd:       MTD block structure
27785 + * @dat:       raw data
27786 + * @ecc_code:  buffer for ECC
27787   */
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)
27790  {
27791         u_char idx, reg1, reg2, reg3;
27792         int j;
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;
27797 +       return 0;
27798  }
27799  
27800 -/*
27801 +/**
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
27807 + *
27808   * Detect and correct a 1 bit error for 256 byte block
27809   */
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)
27812  {
27813         u_char a, b, c, d1, d2, d3, add, bit, i;
27814         
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
27819 @@ -2,9 +2,8 @@
27820   *  drivers/mtd/nandids.c
27821   *
27822   *  Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
27823 - *
27824 - *
27825 - * $Id: nand_ids.c,v 1.4 2003/05/21 15:15:08 dwmw2 Exp $
27826 +  *
27827 + * $Id: nand_ids.c,v 1.10 2004/05/26 13:40:12 gleixner Exp $
27828   *
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 @@
27832   */
27833  #include <linux/module.h>
27834  #include <linux/mtd/nand.h>
27835 -
27836  /*
27837  *      Chip ID list
27838 +*      
27839 +*      Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
27840 +*      options
27841 +* 
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      
27846  */
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},
27873 +       
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},
27878 +       
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},
27883 +       
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},
27888 +       
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},
27893 +       
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},
27898 +       
27899 +       {"NAND 256MiB 3,3V 8-bit",      0x71, 512, 256, 0x4000, 0},
27900 +
27901 +       {"NAND 512MiB 3,3V 8-bit",      0xDC, 512, 512, 0x4000, 0},
27902 +       
27903 +       /* These are the new chips with large page size. The pagesize
27904 +       * and the erasesize is determined from the extended id bytes
27905 +       */
27906 +       /* 1 Gigabit */
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},
27911 +
27912 +       /* 2 Gigabit */
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},
27917 +       
27918 +       /* 4 Gigabit */
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},
27923 +       
27924 +       /* 8 Gigabit */
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},
27929 +
27930 +       /* 16 Gigabit */
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},
27935 +
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 
27941 +        */
27942 +       {"AND 128MiB 3,3V 8-bit",       0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},
27943 +
27944         {NULL,}
27945  };
27946  
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"},
27953         {0x0, "Unknown"}
27954  };
27955  
27956 -
27957  EXPORT_SYMBOL (nand_manuf_ids);
27958  EXPORT_SYMBOL (nand_flash_ids);
27959  
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
27964 @@ -0,0 +1,419 @@
27965 +/*
27966 + *  drivers/mtd/nand/ppchameleonevb.c
27967 + *
27968 + *  Copyright (C) 2003 DAVE Srl (info@wawnet.biz)
27969 + *
27970 + *  Derived from drivers/mtd/nand/edb7312.c
27971 + *
27972 + *
27973 + * $Id: ppchameleonevb.c,v 1.3 2004/09/16 23:27:14 gleixner Exp $
27974 + *
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.
27978 + *
27979 + *  Overview:
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)
27988 + */
27989 +
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>
27998 +
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
28004 +
28005 +/* handy sizes */
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"
28010 +
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)
28021 +
28022 +/*
28023 + * MTD structure for PPChameleonEVB board
28024 + */
28025 +static struct mtd_info *ppchameleon_mtd        = NULL;
28026 +static struct mtd_info *ppchameleonevb_mtd = NULL;
28027 +
28028 +/*
28029 + * Module stuff
28030 + */
28031 +static int ppchameleon_fio_pbase       = CFG_NAND0_PADDR;
28032 +static int ppchameleonevb_fio_pbase = CFG_NAND1_PADDR;
28033 +
28034 +#ifdef MODULE
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);
28039 +#endif
28040 +
28041 +#ifdef CONFIG_MTD_PARTITIONS
28042 +/*
28043 + * Define static partitions for flash devices
28044 + */
28045 +static struct mtd_partition partition_info_hi[] = {
28046 +       { name: "PPChameleon HI Nand Flash",
28047 +                 offset: 0,
28048 +                 size: 128*1024*1024 }
28049 +};
28050 +
28051 +static struct mtd_partition partition_info_me[] = {
28052 +       { name: "PPChameleon ME Nand Flash",
28053 +                 offset: 0,
28054 +                 size: 32*1024*1024 }
28055 +};
28056 +
28057 +static struct mtd_partition partition_info_evb[] = {
28058 +       { name: "PPChameleonEVB Nand Flash",
28059 +                 offset: 0,
28060 +                 size: 32*1024*1024 }
28061 +};
28062 +
28063 +#define NUM_PARTITIONS 1
28064 +
28065 +extern int parse_cmdline_partitions(struct mtd_info *master,
28066 +                                   struct mtd_partition **pparts,
28067 +                                   const char *mtd_id);
28068 +#endif
28069 +
28070 +
28071 +/*
28072 + *     hardware specific access to control-lines
28073 + */
28074 +static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd)
28075 +{
28076 +       switch(cmd) {
28077 +
28078 +       case NAND_CTL_SETCLE:
28079 +               MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
28080 +               break;
28081 +       case NAND_CTL_CLRCLE:
28082 +               MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
28083 +               break;
28084 +       case NAND_CTL_SETALE:
28085 +               MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
28086 +               break;
28087 +       case NAND_CTL_CLRALE:
28088 +               MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
28089 +               break;
28090 +       case NAND_CTL_SETNCE:
28091 +                       MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
28092 +               break;
28093 +       case NAND_CTL_CLRNCE:
28094 +                       MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
28095 +               break;
28096 +       }
28097 +}
28098 +
28099 +static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
28100 +{
28101 +       switch(cmd) {
28102 +
28103 +       case NAND_CTL_SETCLE:
28104 +               MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
28105 +               break;
28106 +       case NAND_CTL_CLRCLE:
28107 +               MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
28108 +               break;
28109 +       case NAND_CTL_SETALE:
28110 +               MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
28111 +               break;
28112 +       case NAND_CTL_CLRALE:
28113 +               MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
28114 +               break;
28115 +       case NAND_CTL_SETNCE:
28116 +               MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
28117 +               break;
28118 +       case NAND_CTL_CLRNCE:
28119 +               MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
28120 +               break;
28121 +       }
28122 +}
28123 +
28124 +#ifdef USE_READY_BUSY_PIN
28125 +/*
28126 + *     read device ready pin
28127 + */
28128 +static int ppchameleon_device_ready(struct mtd_info *minfo)
28129 +{
28130 +       if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_RB_GPIO_PIN)
28131 +               return 1;
28132 +       return 0;
28133 +}
28134 +
28135 +static int ppchameleonevb_device_ready(struct mtd_info *minfo)
28136 +{
28137 +       if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
28138 +       return 1;
28139 +       return 0;
28140 +}
28141 +#endif
28142 +
28143 +#ifdef CONFIG_MTD_PARTITIONS
28144 +const char *part_probes[] = { "cmdlinepart", NULL };
28145 +const char *part_probes_evb[] = { "cmdlinepart", NULL };
28146 +#endif
28147 +
28148 +/*
28149 + * Main initialization routine
28150 + */
28151 +static int __init ppchameleonevb_init (void)
28152 +{
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;
28159 +
28160 +
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");
28169 +               return -ENOMEM;
28170 +       }
28171 +
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);
28177 +               return -EIO;
28178 +       }
28179 +
28180 +       /* Get pointer to private data */
28181 +       this = (struct nand_chip *) (&ppchameleon_mtd[1]);
28182 +
28183 +       /* Initialize structures */
28184 +       memset((char *) ppchameleon_mtd, 0, sizeof(struct mtd_info));
28185 +       memset((char *) this, 0, sizeof(struct nand_chip));
28186 +
28187 +       /* Link the private data with the MTD structure */
28188 +       ppchameleon_mtd->priv = this;
28189 +
28190 +        /* Initialize GPIOs */
28191 +       /* Pin mapping for NAND chip */
28192 +       /*
28193 +               CE      GPIO_01
28194 +               CLE     GPIO_02
28195 +               ALE     GPIO_03
28196 +               R/B     GPIO_04
28197 +       */
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);
28211 +#endif
28212 +
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;
28219 +#endif
28220 +       this->chip_delay = NAND_BIG_DELAY_US;
28221 +       /* ECC mode */
28222 +       this->eccmode = NAND_ECC_SOFT;
28223 +
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;
28229 +       }
28230 +
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;
28235 +#endif
28236 +
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";
28242 +       else
28243 +         mtd_parts_nb = 0;
28244 +#endif
28245 +       if (mtd_parts_nb == 0)
28246 +       {
28247 +               if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
28248 +                       mtd_parts = partition_info_me;
28249 +               else
28250 +                       mtd_parts = partition_info_hi;
28251 +               mtd_parts_nb = NUM_PARTITIONS;
28252 +               part_type = "static";
28253 +       }
28254 +
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);
28258 +
28259 +nand_evb_init:
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");
28268 +               return -ENOMEM;
28269 +       }
28270 +
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);
28276 +               return -EIO;
28277 +       }
28278 +
28279 +       /* Get pointer to private data */
28280 +       this = (struct nand_chip *) (&ppchameleonevb_mtd[1]);
28281 +
28282 +       /* Initialize structures */
28283 +       memset((char *) ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
28284 +       memset((char *) this, 0, sizeof(struct nand_chip));
28285 +
28286 +       /* Link the private data with the MTD structure */
28287 +       ppchameleonevb_mtd->priv = this;
28288 +
28289 +        /* Initialize GPIOs */
28290 +       /* Pin mapping for NAND chip */
28291 +       /*
28292 +               CE      GPIO_14
28293 +               CLE     GPIO_15
28294 +               ALE     GPIO_16
28295 +               R/B     GPIO_31
28296 +       */
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);
28313 +#endif
28314 +
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;
28321 +#endif
28322 +       this->chip_delay = NAND_SMALL_DELAY_US;
28323 +
28324 +       /* ECC mode */
28325 +       this->eccmode = NAND_ECC_SOFT;
28326 +
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);
28331 +               return -ENXIO;
28332 +       }
28333 +
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";
28339 +       else
28340 +         mtd_parts_nb = 0;
28341 +#endif
28342 +       if (mtd_parts_nb == 0)
28343 +       {
28344 +               mtd_parts = partition_info_evb;
28345 +               mtd_parts_nb = NUM_PARTITIONS;
28346 +               part_type = "static";
28347 +       }
28348 +
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);
28352 +
28353 +       /* Return happy */
28354 +       return 0;
28355 +}
28356 +module_init(ppchameleonevb_init);
28357 +
28358 +/*
28359 + * Clean up routine
28360 + */
28361 +static void __exit ppchameleonevb_cleanup (void)
28362 +{
28363 +       struct nand_chip *this;
28364 +
28365 +       /* Release resources, unregister device(s) */
28366 +       nand_release (ppchameleon_mtd);
28367 +       nand_release (ppchameleonevb_mtd);
28368 +       
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;
28374 +
28375 +       /* Free the MTD device structure */
28376 +       kfree (ppchameleon_mtd);
28377 +       kfree (ppchameleonevb_mtd);
28378 +}
28379 +module_exit(ppchameleonevb_cleanup);
28380 +
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
28388 @@ -0,0 +1,500 @@
28389 +/*
28390 + *  drivers/mtd/nand/rtc_from4.c
28391 + *
28392 + *  Copyright (C) 2004  Red Hat, Inc.
28393 + * 
28394 + *  Derived from drivers/mtd/nand/spia.c
28395 + *       Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
28396 + *
28397 + * $Id: rtc_from4.c,v 1.1 2004/09/16 23:23:42 gleixner Exp $
28398 + *
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.
28402 + *
28403 + * Overview:
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.
28408 + */
28409 +
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>
28421 +
28422 +/*
28423 + * MTD structure for Renesas board
28424 + */
28425 +static struct mtd_info *rtc_from4_mtd = NULL;
28426 +
28427 +#define RTC_FROM4_MAX_CHIPS    2
28428 +
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))
28437 +
28438 +/*
28439 + * Values specific to the Renesas Technology Corp. FROM_BOARD4 (used with HS77x9 processor)
28440 + */
28441 +/* Address where flash is mapped */
28442 +#define RTC_FROM4_FIO_BASE     0x14000000
28443 +
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)
28447 +
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)
28454 +
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
28458 +
28459 +/* FPGA Reed-Solomon ECC Control register */
28460 +
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)
28465 +
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)
28469 +
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)
28473 +
28474 +/* Undefine for software ECC */
28475 +#define RTC_FROM4_HWECC        1
28476 +
28477 +/*
28478 + * Module stuff
28479 + */
28480 +static void __iomem *rtc_from4_fio_base = P2SEGADDR(RTC_FROM4_FIO_BASE);
28481 +
28482 +MODULE_PARM(rtc_from4_fio_base, "i");
28483 +
28484 +const static struct mtd_partition partition_info[] = {
28485 +        {
28486 +                .name   = "Renesas flash partition 1",
28487 +                .offset = 0,
28488 +                .size   = MTDPART_SIZ_FULL
28489 +        },
28490 +};
28491 +#define NUM_PARTITIONS 1
28492 +
28493 +/* 
28494 + *     hardware specific flash bbt decriptors
28495 + *     Note: this is to allow debugging by disabling 
28496 + *             NAND_BBT_CREATE and/or NAND_BBT_WRITE
28497 + *
28498 + */
28499 +static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
28500 +static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
28501 +
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,
28505 +       .offs = 40,
28506 +       .len = 4,
28507 +       .veroffs = 44,
28508 +       .maxblocks = 4,
28509 +       .pattern = bbt_pattern
28510 +};
28511 +
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,
28515 +       .offs = 40,
28516 +       .len = 4,
28517 +       .veroffs = 44,
28518 +       .maxblocks = 4,
28519 +       .pattern = mirror_pattern
28520 +};
28521 +
28522 +
28523 +
28524 +#ifdef RTC_FROM4_HWECC
28525 +
28526 +/* the Reed Solomon control structure */
28527 +static struct rs_control *rs_decoder;
28528 +
28529 +/* 
28530 + *      hardware specific Out Of Band information
28531 + */
28532 +static struct nand_oobinfo rtc_from4_nand_oobinfo = {
28533 +       .useecc = MTD_NANDECC_AUTOPLACE,
28534 +       .eccbytes = 32,
28535 +       .eccpos = {
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} }
28541 +};
28542 +#endif
28543 +
28544 +
28545 +
28546 +/* 
28547 + * rtc_from4_hwcontrol - hardware specific access to control-lines
28548 + * @mtd:       MTD device structure
28549 + * @cmd:       hardware control command
28550 + *
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.
28553 + *
28554 + * Chip Enable is also controlled by the Chip Select (CS5) and 
28555 + * Address lines (A24-A22), so no action is required here.
28556 + *
28557 + */
28558 +static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
28559 +{
28560 +       struct nand_chip* this = (struct nand_chip *) (mtd->priv);
28561 +       
28562 +       switch(cmd) {
28563 +               
28564 +       case NAND_CTL_SETCLE: 
28565 +               this->IO_ADDR_W |= RTC_FROM4_CLE;
28566 +               break;
28567 +       case NAND_CTL_CLRCLE: 
28568 +               this->IO_ADDR_W &= ~RTC_FROM4_CLE;
28569 +               break;
28570 +               
28571 +       case NAND_CTL_SETALE:
28572 +               this->IO_ADDR_W |= RTC_FROM4_ALE;
28573 +               break;
28574 +       case NAND_CTL_CLRALE:
28575 +               this->IO_ADDR_W &= ~RTC_FROM4_ALE;
28576 +               break;
28577 +               
28578 +       case NAND_CTL_SETNCE:
28579 +               break;
28580 +       case NAND_CTL_CLRNCE:
28581 +               break;
28582 +
28583 +       }
28584 +}
28585 +
28586 +
28587 +/*
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)
28591 + *
28592 + * The chip select is based on address lines A24-A22.
28593 + * This driver uses flash slots 3 and 4 (A23-A22).
28594 + *
28595 + */
28596 +static void rtc_from4_nand_select_chip(struct mtd_info *mtd, int chip)
28597 +{
28598 +        struct nand_chip *this = mtd->priv;
28599 +
28600 +       this->IO_ADDR_R &= ~RTC_FROM4_NAND_ADDR_MASK;
28601 +       this->IO_ADDR_W &= ~RTC_FROM4_NAND_ADDR_MASK;
28602 +
28603 +        switch(chip) {
28604 +
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;
28608 +                break;
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;
28612 +                break;
28613 +
28614 +        }
28615 +}
28616 +
28617 +
28618 +
28619 +/*
28620 + * rtc_from4_nand_device_ready - hardware specific ready/busy check
28621 + * @mtd:       MTD device structure
28622 + *
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.
28625 + *
28626 + */
28627 +static int rtc_from4_nand_device_ready(struct mtd_info *mtd)
28628 +{
28629 +       unsigned short status;
28630 +
28631 +       status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_FPGA_SR));
28632 +
28633 +       return (status & RTC_FROM4_DEVICE_READY);
28634 +
28635 +}
28636 +
28637 +#ifdef RTC_FROM4_HWECC
28638 +/*
28639 + * rtc_from4_enable_hwecc - hardware specific hardware ECC enable function
28640 + * @mtd:       MTD device structure
28641 + * @mode:      I/O mode; read or write
28642 + *
28643 + * enable hardware ECC for data read or write 
28644 + *
28645 + */
28646 +static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode)
28647 +{
28648 +       volatile unsigned short * rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL);
28649 +       unsigned short status;
28650 +
28651 +       switch (mode) {
28652 +           case NAND_ECC_READ :
28653 +               status =  RTC_FROM4_RS_ECC_CTL_CLR 
28654 +                       | RTC_FROM4_RS_ECC_CTL_FD_E;
28655 +
28656 +               *rs_ecc_ctl = status;
28657 +               break;
28658 +
28659 +           case NAND_ECC_READSYN :
28660 +               status =  0x00;
28661 +
28662 +               *rs_ecc_ctl = status;
28663 +               break;
28664 +
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;
28669 +
28670 +               *rs_ecc_ctl = status;
28671 +               break;
28672 +
28673 +           default:
28674 +               BUG();
28675 +               break;
28676 +       }
28677 +
28678 +}
28679 +
28680 +/*
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
28685 + *
28686 + * The ECC code is calculated by the FPGA.  All we have to do is read the values
28687 + * from the FPGA registers.
28688 + *
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
28691 + *
28692 + */
28693 +static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
28694 +{
28695 +       volatile unsigned short * rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN);
28696 +       unsigned short value;
28697 +       int i;
28698 +
28699 +       for (i = 0; i < 8; i++) {
28700 +               value = *rs_eccn;
28701 +               ecc_code[i] = (unsigned char)value;
28702 +               rs_eccn++;
28703 +       }
28704 +       ecc_code[7] |= 0x0f;    /* set the last four bits (not used) */
28705 +}
28706 +
28707 +
28708 +/*
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
28714 + *
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
28718 + *
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.
28721 + */
28722 +static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2)
28723 +{
28724 +       int i, res;
28725 +       unsigned short status; 
28726 +       uint16_t rpar[6];
28727 +
28728 +       status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CHK));
28729 +
28730 +       if (!(status & RTC_FROM4_RS_ECC_CHK_ERROR))
28731 +               return 0;
28732 +
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);
28740 +
28741 +       /* Invert the codes */
28742 +       for (i = 0; i < 6; i++)
28743 +               rpar[i] ^= 0x3ff;
28744 +
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
28748 +       */
28749 +       res = decode_rs8 (rs_decoder, buf, rpar, 512, NULL, 0, NULL, 0xff);
28750 +       if (res > 0)
28751 +               DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " 
28752 +                       "ECC corrected %d errors on read\n", res);
28753 +
28754 +       return res;
28755 +}
28756 +#endif
28757 +
28758 +/*
28759 + * Main initialization routine
28760 + */
28761 +int __init rtc_from4_init (void)
28762 +{
28763 +       struct nand_chip *this;
28764 +       unsigned short bcr1, bcr2, wcr2;
28765 +
28766 +       /* Allocate memory for MTD device structure and private data */
28767 +       rtc_from4_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
28768 +                               GFP_KERNEL);
28769 +       if (!rtc_from4_mtd) {
28770 +               printk ("Unable to allocate Renesas NAND MTD device structure.\n");
28771 +               return -ENOMEM;
28772 +       }
28773 +
28774 +       /* Get pointer to private data */
28775 +       this = (struct nand_chip *) (&rtc_from4_mtd[1]);
28776 +
28777 +       /* Initialize structures */
28778 +       memset((char *) rtc_from4_mtd, 0, sizeof(struct mtd_info));
28779 +       memset((char *) this, 0, sizeof(struct nand_chip));
28780 +
28781 +       /* Link the private data with the MTD structure */
28782 +       rtc_from4_mtd->priv = this;
28783 +
28784 +       /* set area 5 as PCMCIA mode to clear the spec of tDH(Data hold time;9ns min) */
28785 +       bcr1 = *SH77X9_BCR1 & ~0x0002;
28786 +       bcr1 |= 0x0002;
28787 +       *SH77X9_BCR1 = bcr1;
28788 +
28789 +       /* set */
28790 +       bcr2 = *SH77X9_BCR2 & ~0x0c00;
28791 +       bcr2 |= 0x0800;
28792 +       *SH77X9_BCR2 = bcr2;
28793 +
28794 +       /* set area 5 wait states */
28795 +       wcr2 = *SH77X9_WCR2 & ~0x1c00;
28796 +       wcr2 |= 0x1c00;
28797 +       *SH77X9_WCR2 = wcr2;
28798 +
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;
28810 +
28811 +#ifdef RTC_FROM4_HWECC
28812 +       printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n");
28813 +
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;
28821 +#else
28822 +       printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
28823 +
28824 +       this->eccmode = NAND_ECC_SOFT;
28825 +#endif
28826 +
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;
28830 +
28831 +       /* Scan to find existence of the device */
28832 +       if (nand_scan (rtc_from4_mtd, RTC_FROM4_MAX_CHIPS)) {
28833 +               kfree (rtc_from4_mtd);
28834 +               return -ENXIO;
28835 +       }
28836 +
28837 +       /* Register the partitions */
28838 +       add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
28839 +
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 
28843 +        *
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
28849 +        */
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);
28855 +               return -ENOMEM;
28856 +       }
28857 +#endif
28858 +       /* Return happy */
28859 +       return 0;
28860 +}
28861 +module_init(rtc_from4_init);
28862 +
28863 +
28864 +/*
28865 + * Clean up routine
28866 + */
28867 +#ifdef MODULE
28868 +static void __exit rtc_from4_cleanup (void)
28869 +{
28870 +       /* Release resource, unregister partitions */
28871 +       nand_release(rtc_from4_mtd);
28872 +
28873 +       /* Free the MTD device structure */
28874 +       kfree (rtc_from4_mtd);
28875 +
28876 +#ifdef RTC_FROM4_HWECC
28877 +       /* Free the reed solomon resources */
28878 +       if (rs_decoder)
28879 +               free_rs(rs_decoder);
28880 +#endif
28881 +}
28882 +module_exit(rtc_from4_cleanup);
28883 +#endif
28884 +
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");
28888 +
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
28893 @@ -8,7 +8,7 @@
28894   *                     to controllines (due to change in nand.c)
28895   *                     page_cache added
28896   *
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 $
28899   *
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
28902 @@ -20,6 +20,8 @@
28903   *   a 64Mibit (8MiB x 8 bits) NAND flash device.
28904   */
28905  
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 @@
28912  /*
28913   * Values specific to the SPIA board (used with EP7212 processor)
28914   */
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
28923                                          * are wired to.
28924                                          */
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
28929                                          * lines.
28930 @@ -62,11 +64,6 @@
28931  MODULE_PARM(spia_pedr, "i");
28932  MODULE_PARM(spia_peddr, "i");
28933  
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);
28938 -
28939  /*
28940   * Define partitions for flash device
28941   */
28942 @@ -88,7 +85,7 @@
28943  /* 
28944   *     hardware specific access to control-lines
28945  */
28946 -void spia_hwcontrol(int cmd){
28947 +static void spia_hwcontrol(struct mtd_info *mtd, int cmd){
28948  
28949      switch(cmd){
28950  
28951 @@ -111,7 +108,7 @@
28952         struct nand_chip *this;
28953  
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),
28957                                 GFP_KERNEL);
28958         if (!spia_mtd) {
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;
28962  
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;          
28972  
28973         /* Scan to find existence of the device */
28974 -       if (nand_scan (spia_mtd)) {
28975 +       if (nand_scan (spia_mtd, 1)) {
28976                 kfree (spia_mtd);
28977                 return -ENXIO;
28978         }
28979  
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);
28985 -               return -ENOMEM;
28986 -       }
28987 -
28988         /* Register the partitions */
28989         add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS);
28990  
28991 @@ -170,13 +159,8 @@
28992  #ifdef MODULE
28993  static void __exit spia_cleanup (void)
28994  {
28995 -       struct nand_chip *this = (struct nand_chip *) &spia_mtd[1];
28996 -
28997 -       /* Unregister the device */
28998 -       del_mtd_device (spia_mtd);
28999 -
29000 -       /* Free internal data buffer */
29001 -       kfree (this->data_buf);
29002 +       /* Release resources, unregister device */
29003 +       nand_release (spia_mtd);
29004  
29005         /* Free the MTD device structure */
29006         kfree (spia_mtd);
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
29011 @@ -0,0 +1,205 @@
29012 +/*
29013 + *  drivers/mtd/nand/toto.c
29014 + *
29015 + *  Copyright (c) 2003 Texas Instruments
29016 + *
29017 + *  Derived from drivers/mtd/autcpu12.c
29018 + *
29019 + *  Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
29020 + *
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.
29024 + *
29025 + *  Overview:
29026 + *   This is a device driver for the NAND flash device found on the
29027 + *   TI fido board. It supports 32MiB and 64MiB cards
29028 + *
29029 + * $Id: toto.c,v 1.3 2004/09/16 23:27:15 gleixner Exp $
29030 + */
29031 +
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>
29045 +
29046 +/*
29047 + * MTD structure for TOTO board
29048 + */
29049 +static struct mtd_info *toto_mtd = NULL;
29050 +
29051 +static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
29052 +
29053 +#define CONFIG_NAND_WORKAROUND 1
29054 +
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)
29059 +
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)
29065 +#else
29066 +#define T_NAND_CTL_CLRCLE(iob)  gpiosetout(NAND_CLE, 0)
29067 +#define T_NAND_CTL_SETCLE(iob)  gpiosetout(NAND_CLE, NAND_CLE)
29068 +#endif
29069 +#define T_NAND_CTL_SETNCE(iob)  gpiosetout(NAND_NCE, 0)
29070 +#define T_NAND_CTL_CLRNCE(iob)  gpiosetout(NAND_NCE, NAND_NCE)
29071 +                
29072 +/*
29073 + * Define partitions for flash devices
29074 + */
29075 +
29076 +static struct mtd_partition partition_info64M[] = {
29077 +       { .name =       "toto kernel partition 1",
29078 +         .offset =     0,
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 },
29089 +};
29090 +
29091 +static struct mtd_partition partition_info32M[] = {
29092 +       { .name =       "toto kernel partition 1",
29093 +         .offset =     0,
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 },
29101 +};
29102 +
29103 +#define NUM_PARTITIONS32M 3
29104 +#define NUM_PARTITIONS64M 4
29105 +/* 
29106 + *     hardware specific access to control-lines
29107 +*/
29108 +
29109 +static void toto_hwcontrol(struct mtd_info *mtd, int cmd)
29110 +{
29111 +
29112 +       udelay(1); /* hopefully enough time for tc make proceding write to clear */
29113 +       switch(cmd){
29114 +
29115 +               case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
29116 +               case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
29117 +
29118 +               case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break;
29119 +               case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break;
29120 +
29121 +               case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
29122 +               case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
29123 +       }
29124 +       udelay(1); /* allow time to ensure gpio state to over take memory write */
29125 +}
29126 +
29127 +/*
29128 + * Main initialization routine
29129 + */
29130 +int __init toto_init (void)
29131 +{
29132 +       struct nand_chip *this;
29133 +       int err = 0;
29134 +
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),
29137 +                               GFP_KERNEL);
29138 +       if (!toto_mtd) {
29139 +               printk (KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
29140 +               err = -ENOMEM;
29141 +               goto out;
29142 +       }
29143 +
29144 +       /* Get pointer to private data */
29145 +       this = (struct nand_chip *) (&toto_mtd[1]);
29146 +
29147 +       /* Initialize structures */
29148 +       memset((char *) toto_mtd, 0, sizeof(struct mtd_info));
29149 +       memset((char *) this, 0, sizeof(struct nand_chip));
29150 +
29151 +       /* Link the private data with the MTD structure */
29152 +       toto_mtd->priv = this;
29153 +
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;
29162 +
29163 +        /* Scan to find existance of the device */
29164 +       if (nand_scan (toto_mtd, 1)) {
29165 +               err = -ENXIO;
29166 +               goto out_mtd;
29167 +       }
29168 +
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; 
29173 +               default: {
29174 +                       printk (KERN_WARNING "Unsupported Nand device\n"); 
29175 +                       err = -ENXIO;
29176 +                       goto out_buf;
29177 +               }
29178 +       }
29179 +
29180 +       gpioreserve(NAND_MASK);  /* claim our gpios */
29181 +       archflashwp(0,0);        /* open up flash for writing */
29182 +
29183 +       goto out;
29184 +    
29185 +out_buf:
29186 +       kfree (this->data_buf);    
29187 +out_mtd:
29188 +       kfree (toto_mtd);
29189 +out:
29190 +       return err;
29191 +}
29192 +
29193 +module_init(toto_init);
29194 +
29195 +/*
29196 + * Clean up routine
29197 + */
29198 +static void __exit toto_cleanup (void)
29199 +{
29200 +       /* Release resources, unregister device */
29201 +       nand_release (toto_mtd);
29202 +
29203 +       /* Free the MTD device structure */
29204 +       kfree (toto_mtd);
29205 +
29206 +       /* stop flash writes */
29207 +        archflashwp(0,1);
29208 +       
29209 +       /* release gpios to system */
29210 +        gpiorelease(NAND_MASK);
29211 +}
29212 +module_exit(toto_cleanup);
29213 +
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
29221 @@ -0,0 +1,416 @@
29222 +/*
29223 + *  drivers/mtd/tx4925ndfmc.c
29224 + *
29225 + *  Overview:
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.
29229 + *
29230 + * Author: MontaVista Software, Inc.  source@mvista.com
29231 + *
29232 + * Derived from drivers/mtd/autcpu12.c
29233 + *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
29234 + *
29235 + * $Id: tx4925ndfmc.c,v 1.4 2004/09/16 23:27:15 gleixner Exp $
29236 + *
29237 + * Copyright (C) 2001 Toshiba Corporation 
29238 + * 
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
29242 + * or implied.
29243 + *
29244 + */
29245 +
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>
29255 +
29256 +extern struct nand_oobinfo jffs2_oobinfo;
29257 +
29258 +/*
29259 + * MTD structure for RBTX4925 board
29260 + */
29261 +static struct mtd_info *tx4925ndfmc_mtd = NULL;
29262 +
29263 +/*
29264 + * Define partitions for flash devices
29265 + */
29266 +
29267 +static struct mtd_partition partition_info16k[] = {
29268 +       { .name = "RBTX4925 flash partition 1",
29269 +         .offset =  0,
29270 +         .size =    8 * 0x00100000 },
29271 +       { .name = "RBTX4925 flash partition 2",
29272 +         .offset =  8 * 0x00100000,
29273 +         .size =    8 * 0x00100000 },
29274 +};
29275 +
29276 +static struct mtd_partition partition_info32k[] = {
29277 +       { .name = "RBTX4925 flash partition 1",
29278 +         .offset =  0,
29279 +         .size =    8 * 0x00100000 },
29280 +       { .name = "RBTX4925 flash partition 2",
29281 +         .offset = 8 * 0x00100000,
29282 +         .size =  24 * 0x00100000 },
29283 +};
29284 +
29285 +static struct mtd_partition partition_info64k[] = {
29286 +       { .name = "User FS",
29287 +         .offset =  0,
29288 +         .size =   16 * 0x00100000 },
29289 +       { .name = "RBTX4925 flash partition 2",
29290 +         .offset = 16 * 0x00100000,
29291 +         .size =   48 * 0x00100000},
29292 +};
29293 +
29294 +static struct mtd_partition partition_info128k[] = {
29295 +       { .name = "Skip bad section",
29296 +         .offset =  0,
29297 +         .size =   16 * 0x00100000 },
29298 +       { .name = "User FS",
29299 +         .offset = 16 * 0x00100000,
29300 +         .size =   112 * 0x00100000 },
29301 +};
29302 +#define NUM_PARTITIONS16K  2
29303 +#define NUM_PARTITIONS32K  2
29304 +#define NUM_PARTITIONS64K  2
29305 +#define NUM_PARTITIONS128K 2
29306 +
29307 +/* 
29308 + *     hardware specific access to control-lines
29309 +*/
29310 +static void tx4925ndfmc_hwcontrol(struct mtd_info *mtd, int cmd)
29311 +{
29312 +
29313 +       switch(cmd){
29314 +
29315 +               case NAND_CTL_SETCLE: 
29316 +                       tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CLE;
29317 +                       break;
29318 +               case NAND_CTL_CLRCLE:
29319 +                       tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CLE;
29320 +                       break;
29321 +               case NAND_CTL_SETALE:
29322 +                       tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ALE;
29323 +                       break;
29324 +               case NAND_CTL_CLRALE: 
29325 +                       tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ALE;
29326 +                       break;
29327 +               case NAND_CTL_SETNCE:
29328 +                       tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CE;
29329 +                       break;
29330 +               case NAND_CTL_CLRNCE:
29331 +                       tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CE;
29332 +                       break;
29333 +               case NAND_CTL_SETWP:
29334 +                       tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_WE;
29335 +                       break;
29336 +               case NAND_CTL_CLRWP:
29337 +                       tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_WE;
29338 +                       break;
29339 +       }
29340 +}
29341 +
29342 +/*
29343 +*      read device ready pin
29344 +*/
29345 +static int tx4925ndfmc_device_ready(struct mtd_info *mtd)
29346 +{
29347 +       int ready;
29348 +       ready = (tx4925_ndfmcptr->sr & TX4925_NDSFR_BUSY) ? 0 : 1;
29349 +       return ready;
29350 +}
29351 +void tx4925ndfmc_enable_hwecc(struct mtd_info *mtd, int mode)
29352 +{
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;
29357 +}
29358 +static void tx4925ndfmc_disable_ecc(void)
29359 +{
29360 +       tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK;
29361 +}
29362 +static void tx4925ndfmc_enable_read_ecc(void)
29363 +{
29364 +       tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK;
29365 +       tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_READ;
29366 +}
29367 +void tx4925ndfmc_readecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code){
29368 +       int i;
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();
29374 +}
29375 +void tx4925ndfmc_device_setup(void)
29376 +{
29377 +
29378 +       *(unsigned char *)0xbb005000 &= ~0x08;
29379 +
29380 +        /* reset NDFMC */
29381 +        tx4925_ndfmcptr->rstr |= TX4925_NDFRSTR_RST;
29382 +       while (tx4925_ndfmcptr->rstr & TX4925_NDFRSTR_RST);       
29383 +
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;             
29387 +}
29388 +static u_char tx4925ndfmc_nand_read_byte(struct mtd_info *mtd)
29389 +{
29390 +        struct nand_chip *this = mtd->priv;
29391 +        return tx4925_read_nfmc(this->IO_ADDR_R);
29392 +}
29393 +
29394 +static void tx4925ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte)
29395 +{
29396 +        struct nand_chip *this = mtd->priv;
29397 +        tx4925_write_nfmc(byte, this->IO_ADDR_W);
29398 +}
29399 +
29400 +static void tx4925ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
29401 +{
29402 +       int i;
29403 +       struct nand_chip *this = mtd->priv;
29404 +
29405 +       for (i=0; i<len; i++)
29406 +               tx4925_write_nfmc(buf[i], this->IO_ADDR_W);
29407 +}
29408 +
29409 +static void tx4925ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
29410 +{
29411 +       int i;
29412 +       struct nand_chip *this = mtd->priv;
29413 +
29414 +       for (i=0; i<len; i++)
29415 +               buf[i] = tx4925_read_nfmc(this->IO_ADDR_R);
29416 +}
29417 +
29418 +static int tx4925ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
29419 +{
29420 +       int i;
29421 +       struct nand_chip *this = mtd->priv;
29422 +
29423 +       for (i=0; i<len; i++)
29424 +               if (buf[i] != tx4925_read_nfmc(this->IO_ADDR_R))
29425 +                       return -EFAULT;
29426 +
29427 +       return 0;
29428 +}
29429 +
29430 +/*
29431 + * Send command to NAND device
29432 + */
29433 +static void tx4925ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
29434 +{
29435 +       register struct nand_chip *this = mtd->priv;
29436 +
29437 +       /* Begin command latch cycle */
29438 +       this->hwcontrol(mtd, NAND_CTL_SETCLE);
29439 +       /*
29440 +        * Write out the command to the device.
29441 +        */
29442 +       if (command == NAND_CMD_SEQIN) {
29443 +               int readcmd;
29444 +
29445 +               if (column >= mtd->oobblock) {
29446 +                       /* OOB area */
29447 +                       column -= mtd->oobblock;
29448 +                       readcmd = NAND_CMD_READOOB;
29449 +               } else if (column < 256) {
29450 +                       /* First 256 bytes --> READ0 */
29451 +                       readcmd = NAND_CMD_READ0;
29452 +               } else {
29453 +                       column -= 256;
29454 +                       readcmd = NAND_CMD_READ1;
29455 +               }
29456 +               this->write_byte(mtd, readcmd);
29457 +       }
29458 +       this->write_byte(mtd, command);
29459 +
29460 +       /* Set ALE and clear CLE to start address cycle */
29461 +       this->hwcontrol(mtd, NAND_CTL_CLRCLE);
29462 +
29463 +       if (column != -1 || page_addr != -1) {
29464 +               this->hwcontrol(mtd, NAND_CTL_SETALE);
29465 +
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));
29475 +               }
29476 +               /* Latch in address */
29477 +               this->hwcontrol(mtd, NAND_CTL_CLRALE);
29478 +       }
29479 +       
29480 +       /* 
29481 +        * program and erase have their own busy handlers 
29482 +        * status and sequential in needs no delay
29483 +       */
29484 +       switch (command) {
29485 +                       
29486 +       case NAND_CMD_PAGEPROG:
29487 +               /* Turn off WE */
29488 +               this->hwcontrol (mtd, NAND_CTL_CLRWP);
29489 +                return;
29490 +
29491 +       case NAND_CMD_SEQIN:
29492 +               /* Turn on WE */
29493 +               this->hwcontrol (mtd, NAND_CTL_SETWP);
29494 +                return;
29495 +
29496 +       case NAND_CMD_ERASE1:
29497 +       case NAND_CMD_ERASE2:
29498 +       case NAND_CMD_STATUS:
29499 +               return;
29500 +
29501 +       case NAND_CMD_RESET:
29502 +               if (this->dev_ready)    
29503 +                       break;
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));
29508 +               return;
29509 +
29510 +       /* This applies to read commands */     
29511 +       default:
29512 +               /* 
29513 +                * If we don't have access to the busy pin, we apply the given
29514 +                * command delay
29515 +               */
29516 +               if (!this->dev_ready) {
29517 +                       udelay (this->chip_delay);
29518 +                       return;
29519 +               }       
29520 +       }
29521 +       
29522 +       /* wait until command is processed */
29523 +       while (!this->dev_ready(mtd));
29524 +}
29525 +
29526 +#ifdef CONFIG_MTD_CMDLINE_PARTS
29527 +extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partitio
29528 +n **pparts, char *);
29529 +#endif
29530 +
29531 +/*
29532 + * Main initialization routine
29533 + */
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)
29536 +{
29537 +       struct nand_chip *this;
29538 +       int err = 0;
29539 +
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),
29542 +                               GFP_KERNEL);
29543 +       if (!tx4925ndfmc_mtd) {
29544 +               printk ("Unable to allocate RBTX4925 NAND MTD device structure.\n");
29545 +               err = -ENOMEM;
29546 +               goto out;
29547 +       }
29548 +
29549 +        tx4925ndfmc_device_setup();
29550 +
29551 +       /* io is indirect via a register so don't need to ioremap address */
29552 +
29553 +       /* Get pointer to private data */
29554 +       this = (struct nand_chip *) (&tx4925ndfmc_mtd[1]);
29555 +
29556 +       /* Initialize structures */
29557 +       memset((char *) tx4925ndfmc_mtd, 0, sizeof(struct mtd_info));
29558 +       memset((char *) this, 0, sizeof(struct nand_chip));
29559 +
29560 +       /* Link the private data with the MTD structure */
29561 +       tx4925ndfmc_mtd->priv = this;
29562 +
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;
29580 +
29581 +       /* Scan to find existance of the device */
29582 +       if (nand_scan (tx4925ndfmc_mtd, 1)) {
29583 +               err = -ENXIO;
29584 +               goto out_ior;
29585 +       }
29586 +
29587 +       /* Register the partitions */
29588 +#ifdef CONFIG_MTD_CMDLINE_PARTS
29589 +        {
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);
29595 +                else
29596 +                        add_mtd_device(tx4925ndfmc_mtd);
29597 +        }
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; 
29604 +               default: {
29605 +                       printk ("Unsupported SmartMedia device\n"); 
29606 +                       err = -ENXIO;
29607 +                       goto out_ior;
29608 +               }
29609 +       }
29610 +#endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */
29611 +       goto out;
29612 +
29613 +out_ior:
29614 +out:
29615 +       return err;
29616 +}
29617 +
29618 +module_init(tx4925ndfmc_init);
29619 +
29620 +/*
29621 + * Clean up routine
29622 + */
29623 +#ifdef MODULE
29624 +static void __exit tx4925ndfmc_cleanup (void)
29625 +{
29626 +       /* Release resources, unregister device */
29627 +       nand_release (tx4925ndfmc_mtd);
29628 +
29629 +       /* Free the MTD device structure */
29630 +       kfree (tx4925ndfmc_mtd);
29631 +}
29632 +module_exit(tx4925ndfmc_cleanup);
29633 +#endif
29634 +
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
29642 @@ -0,0 +1,406 @@
29643 +/*
29644 + * drivers/mtd/nand/tx4938ndfmc.c
29645 + *
29646 + *  Overview:
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.
29650 + *
29651 + * Author: source@mvista.com
29652 + *
29653 + * Based on spia.c by Steven J. Hill
29654 + *
29655 + * $Id: tx4938ndfmc.c,v 1.3 2004/09/16 23:27:15 gleixner Exp $
29656 + *
29657 + * Copyright (C) 2000-2001 Toshiba Corporation 
29658 + *
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
29662 + * or implied.
29663 + */
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>
29676 +
29677 +extern struct nand_oobinfo jffs2_oobinfo;
29678 +
29679 +/*
29680 + * MTD structure for TX4938 NDFMC
29681 + */
29682 +static struct mtd_info *tx4938ndfmc_mtd;
29683 +
29684 +/*
29685 + * Define partitions for flash device
29686 + */
29687 +#define flush_wb()     (void)tx4938_ndfmcptr->mcr;
29688 +
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
29695 +/*
29696 + * You can use the following sample of MTD partitions 
29697 + * on the NAND Flash Memory 32MB or more.
29698 + *
29699 + * The following figure shows the image of the sample partition on
29700 + * the 32MB NAND Flash Memory. 
29701 + *
29702 + *   Block No.
29703 + *    0 +-----------------------------+ ------
29704 + *      |             CIS             |   ^
29705 + *   24 +-----------------------------+   |
29706 + *      |         kernel image        |   | Zone 0
29707 + *      |                             |   |
29708 + *      +-----------------------------+   |
29709 + * 1023 |         unused area         |   v
29710 + *      +-----------------------------+ ------
29711 + * 1024 |            JFFS2            |   ^
29712 + *      |                             |   |
29713 + *      |                             |   | Zone 1
29714 + *      |                             |   |
29715 + *      |                             |   |
29716 + *      |                             |   v
29717 + * 2047 +-----------------------------+ ------
29718 + *
29719 + */
29720 +static struct mtd_partition partition_info[NUM_PARTITIONS] = {
29721 +       {
29722 +               .name = "RBTX4938 CIS Area",
29723 +               .offset =  0,
29724 +               .size =    (NUMBER_OF_CIS_BLOCKS * SIZE_OF_BLOCK),
29725 +               .mask_flags  = MTD_WRITEABLE    /* This partition is NOT writable */
29726 +       },
29727 +       {
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 */
29732 +       },
29733 +       {
29734 +               .name = "Root FS (JFFS2)",
29735 +               .offset =  (0 + SIZE_OF_ZONE),    /* start address of next zone */
29736 +               .size =    MTDPART_SIZ_FULL
29737 +       },
29738 +};
29739 +#endif
29740 +
29741 +static void tx4938ndfmc_hwcontrol(struct mtd_info *mtd, int cmd)
29742 +{
29743 +       switch (cmd) {
29744 +               case NAND_CTL_SETCLE:
29745 +                       tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CLE;
29746 +                       break;
29747 +               case NAND_CTL_CLRCLE:
29748 +                       tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CLE;
29749 +                       break;
29750 +               case NAND_CTL_SETALE:
29751 +                       tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_ALE;
29752 +                       break;
29753 +               case NAND_CTL_CLRALE:
29754 +                       tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_ALE;
29755 +                       break;
29756 +               /* TX4938_NDFMCR_CE bit is 0:high 1:low */
29757 +               case NAND_CTL_SETNCE:
29758 +                       tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CE;
29759 +                       break;
29760 +               case NAND_CTL_CLRNCE:
29761 +                       tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CE;
29762 +                       break;
29763 +               case NAND_CTL_SETWP:
29764 +                       tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_WE;
29765 +                       break;
29766 +               case NAND_CTL_CLRWP:
29767 +                       tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_WE;
29768 +                       break;
29769 +       }
29770 +}
29771 +static int tx4938ndfmc_dev_ready(struct mtd_info *mtd)
29772 +{
29773 +       flush_wb();
29774 +       return !(tx4938_ndfmcptr->sr & TX4938_NDFSR_BUSY);
29775 +}
29776 +static void tx4938ndfmc_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
29777 +{
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;
29786 +}
29787 +static void tx4938ndfmc_enable_hwecc(struct mtd_info *mtd, int mode)
29788 +{
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;
29794 +}
29795 +
29796 +static u_char tx4938ndfmc_nand_read_byte(struct mtd_info *mtd)
29797 +{
29798 +       struct nand_chip *this = mtd->priv;
29799 +       return tx4938_read_nfmc(this->IO_ADDR_R);
29800 +}
29801 +
29802 +static void tx4938ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte)
29803 +{
29804 +       struct nand_chip *this = mtd->priv;
29805 +       tx4938_write_nfmc(byte, this->IO_ADDR_W);
29806 +}
29807 +
29808 +static void tx4938ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
29809 +{
29810 +       int i;
29811 +       struct nand_chip *this = mtd->priv;
29812 +
29813 +       for (i=0; i<len; i++)
29814 +               tx4938_write_nfmc(buf[i], this->IO_ADDR_W);
29815 +}
29816 +
29817 +static void tx4938ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
29818 +{
29819 +       int i;
29820 +       struct nand_chip *this = mtd->priv;
29821 +
29822 +       for (i=0; i<len; i++)
29823 +               buf[i] = tx4938_read_nfmc(this->IO_ADDR_R);
29824 +}
29825 +
29826 +static int tx4938ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
29827 +{
29828 +       int i;
29829 +       struct nand_chip *this = mtd->priv;
29830 +
29831 +       for (i=0; i<len; i++)
29832 +               if (buf[i] != tx4938_read_nfmc(this->IO_ADDR_R))
29833 +                       return -EFAULT;
29834 +
29835 +       return 0;
29836 +}
29837 +
29838 +/*
29839 + * Send command to NAND device
29840 + */
29841 +static void tx4938ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
29842 +{
29843 +       register struct nand_chip *this = mtd->priv;
29844 +
29845 +       /* Begin command latch cycle */
29846 +       this->hwcontrol(mtd, NAND_CTL_SETCLE);
29847 +       /*
29848 +        * Write out the command to the device.
29849 +        */
29850 +       if (command == NAND_CMD_SEQIN) {
29851 +               int readcmd;
29852 +
29853 +               if (column >= mtd->oobblock) {
29854 +                       /* OOB area */
29855 +                       column -= mtd->oobblock;
29856 +                       readcmd = NAND_CMD_READOOB;
29857 +               } else if (column < 256) {
29858 +                       /* First 256 bytes --> READ0 */
29859 +                       readcmd = NAND_CMD_READ0;
29860 +               } else {
29861 +                       column -= 256;
29862 +                       readcmd = NAND_CMD_READ1;
29863 +               }
29864 +               this->write_byte(mtd, readcmd);
29865 +       }
29866 +       this->write_byte(mtd, command);
29867 +
29868 +       /* Set ALE and clear CLE to start address cycle */
29869 +       this->hwcontrol(mtd, NAND_CTL_CLRCLE);
29870 +
29871 +       if (column != -1 || page_addr != -1) {
29872 +               this->hwcontrol(mtd, NAND_CTL_SETALE);
29873 +
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));
29883 +               }
29884 +               /* Latch in address */
29885 +               this->hwcontrol(mtd, NAND_CTL_CLRALE);
29886 +       }
29887 +       
29888 +       /* 
29889 +        * program and erase have their own busy handlers 
29890 +        * status and sequential in needs no delay
29891 +       */
29892 +       switch (command) {
29893 +                       
29894 +       case NAND_CMD_PAGEPROG:
29895 +               /* Turn off WE */
29896 +               this->hwcontrol (mtd, NAND_CTL_CLRWP);
29897 +                return;
29898 +
29899 +       case NAND_CMD_SEQIN:
29900 +               /* Turn on WE */
29901 +               this->hwcontrol (mtd, NAND_CTL_SETWP);
29902 +                return;
29903 +
29904 +       case NAND_CMD_ERASE1:
29905 +       case NAND_CMD_ERASE2:
29906 +       case NAND_CMD_STATUS:
29907 +               return;
29908 +
29909 +       case NAND_CMD_RESET:
29910 +               if (this->dev_ready)    
29911 +                       break;
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));
29916 +               return;
29917 +
29918 +       /* This applies to read commands */     
29919 +       default:
29920 +               /* 
29921 +                * If we don't have access to the busy pin, we apply the given
29922 +                * command delay
29923 +               */
29924 +               if (!this->dev_ready) {
29925 +                       udelay (this->chip_delay);
29926 +                       return;
29927 +               }       
29928 +       }
29929 +       
29930 +       /* wait until command is processed */
29931 +       while (!this->dev_ready(mtd));
29932 +}
29933 +
29934 +#ifdef CONFIG_MTD_CMDLINE_PARTS
29935 +extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *);
29936 +#endif
29937 +/*
29938 + * Main initialization routine
29939 + */
29940 +int __init tx4938ndfmc_init (void)
29941 +{
29942 +       struct nand_chip *this;
29943 +       int bsprt = 0, hold = 0xf, spw = 0xf;
29944 +       int protected = 0;
29945 +
29946 +       if ((*rbtx4938_piosel_ptr & 0x0c) != 0x08) {
29947 +               printk("TX4938 NDFMC: disabled by IOC PIOSEL\n");
29948 +               return -ENODEV;
29949 +       }
29950 +       bsprt = 1;
29951 +       hold = 2;
29952 +       spw = 9 - 1;    /* 8 GBUSCLK = 80ns (@ GBUSCLK 100MHz) */
29953 +
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");
29958 +               return -ENODEV;
29959 +       }
29960 +
29961 +       /* reset NDFMC */
29962 +       tx4938_ndfmcptr->rstr |= TX4938_NDFRSTR_RST;
29963 +       while (tx4938_ndfmcptr->rstr & TX4938_NDFRSTR_RST)
29964 +               ;
29965 +       /* setup BusSeparete, Hold Time, Strobe Pulse Width */
29966 +       tx4938_ndfmcptr->mcr = bsprt ? TX4938_NDFMCR_BSPRT : 0;
29967 +       tx4938_ndfmcptr->spr = hold << 4 | spw;
29968 +
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),
29971 +                                     GFP_KERNEL);
29972 +       if (!tx4938ndfmc_mtd) {
29973 +               printk ("Unable to allocate TX4938 NDFMC MTD device structure.\n");
29974 +               return -ENOMEM;
29975 +       }
29976 +
29977 +       /* Get pointer to private data */
29978 +       this = (struct nand_chip *) (&tx4938ndfmc_mtd[1]);
29979 +
29980 +       /* Initialize structures */
29981 +       memset((char *) tx4938ndfmc_mtd, 0, sizeof(struct mtd_info));
29982 +       memset((char *) this, 0, sizeof(struct nand_chip));
29983 +
29984 +       /* Link the private data with the MTD structure */
29985 +       tx4938ndfmc_mtd->priv = this;
29986 +
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;
30003 +
30004 +       /* Scan to find existance of the device */
30005 +       if (nand_scan (tx4938ndfmc_mtd, 1)) {
30006 +               kfree (tx4938ndfmc_mtd);
30007 +               return -ENXIO;
30008 +       }
30009 +
30010 +       if (protected) {
30011 +               printk(KERN_INFO "TX4938 NDFMC: write protected.\n");
30012 +               tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE);
30013 +       }
30014 +
30015 +#ifdef CONFIG_MTD_CMDLINE_PARTS
30016 +       {
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);
30022 +               else
30023 +                       add_mtd_device(tx4938ndfmc_mtd);
30024 +       }
30025 +#else
30026 +       add_mtd_partitions(tx4938ndfmc_mtd, partition_info, NUM_PARTITIONS );
30027 +#endif
30028 +
30029 +       return 0;
30030 +}
30031 +module_init(tx4938ndfmc_init);
30032 +
30033 +/*
30034 + * Clean up routine
30035 + */
30036 +static void __exit tx4938ndfmc_cleanup (void)
30037 +{
30038 +       /* Release resources, unregister device */
30039 +       nand_release (tx4938ndfmc_mtd);
30040 +
30041 +       /* Free the MTD device structure */
30042 +       kfree (tx4938ndfmc_mtd);
30043 +}
30044 +module_exit(tx4938ndfmc_cleanup);
30045 +
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
30053 @@ -1,7 +1,7 @@
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 $ */
30059  
30060  /*
30061    The contents of this file are distributed under the GNU General
30062 @@ -43,9 +43,19 @@
30063         struct NFTLrecord *nftl;
30064         unsigned long temp;
30065  
30066 -       if (mtd->ecctype != MTD_ECC_RS_DiskOnChip)
30067 +       if (mtd->type != MTD_NANDFLASH)
30068 +               return;
30069 +       /* OK, this is moderately ugly.  But probably safe.  Alternatives? */
30070 +       if (memcmp(mtd->name, "DiskOnChip", 10))
30071                 return;
30072  
30073 +       if (!mtd->block_isbad) {
30074 +               printk(KERN_ERR
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");
30077 +               return;
30078 +       }
30079 +
30080         DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name);
30081  
30082         nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
30083 @@ -60,6 +70,8 @@
30084         nftl->mbd.devnum = -1;
30085         nftl->mbd.blksize = 512;
30086         nftl->mbd.tr = tr;
30087 +       memcpy(&nftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
30088 +       nftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
30089  
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)
30094                          continue;
30095                  
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); 
30100                  if (ret < 0) {
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); 
30105 +                                      movebuf); 
30106                      if (ret != -EIO) 
30107                          printk("Error went away on retry.\n");
30108                  }
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);
30114         }
30115          
30116          /* add the header so that it is now a valid chain */
30117 @@ -390,7 +404,6 @@
30118  
30119                  if (NFTL_formatblock(nftl, thisEUN) < 0) {
30120                         /* could not erase : mark block as reserved
30121 -                        * FixMe: Update Bad Unit Table on disk
30122                          */
30123                         nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED;
30124                  } else {
30125 @@ -617,7 +630,7 @@
30126         u16 writeEUN;
30127         unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
30128         size_t retlen;
30129 -       u8 eccbuf[6];
30130 +       struct nftl_oob oob;
30131  
30132         writeEUN = NFTL_findwriteunit(nftl, block);
30133  
30134 @@ -628,9 +641,11 @@
30135                 return 1;
30136         }
30137  
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 */
30145  
30146         return 0;
30147  }
30148 @@ -692,8 +707,7 @@
30149         } else {
30150                 loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
30151                 size_t retlen;
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))
30155                         return -EIO;
30156         }
30157         return 0;
30158 @@ -735,7 +749,7 @@
30159  
30160  int __init init_nftl(void)
30161  {
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);
30164  
30165         return register_mtd_blktrans(&nftl_tr);
30166  }
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
30171 @@ -4,7 +4,7 @@
30172   * Author: Fabrice Bellard (fabrice.bellard@netgem.com) 
30173   * Copyright (C) 2000 Netgem S.A.
30174   *
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 $
30177   *
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
30180 @@ -31,7 +31,7 @@
30181  
30182  #define SECTORSIZE 512
30183  
30184 -char nftlmountrev[]="$Revision: 1.34 $";
30185 +char nftlmountrev[]="$Revision: 1.37 $";
30186  
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
30189 @@ -41,7 +41,6 @@
30190  static int find_boot_record(struct NFTLrecord *nftl)
30191  {
30192         struct nftl_uci1 h1;
30193 -       struct nftl_oob oob;
30194         unsigned int block, boot_record_count = 0;
30195         size_t retlen;
30196         u8 buf[SECTORSIZE];
30197 @@ -50,6 +49,10 @@
30198  
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;
30207  
30208 @@ -62,7 +65,10 @@
30209  
30210                 /* Check for ANAND header first. Then can whinge if it's found but later
30211                    checks fail */
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;
30218  
30219                         if (warncount) {
30220 @@ -104,7 +110,7 @@
30221  
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);
30228                         continue;
30229 @@ -149,6 +155,10 @@
30230                 memcpy(mh, buf, sizeof(struct NFTLMediaHeader));
30231  
30232                 /* Do some sanity checks on it */
30233 +#if 0
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;
30243                 }
30244 +#endif
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 @@
30249  
30250                 /* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */
30251                 for (i = 0; i < nftl->nb_blocks; i++) {
30252 +#if 0
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",
30261                                                ret);
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;
30267 +#endif
30268 +                       if (nftl->mbd.mtd->block_isbad(nftl->mbd.mtd, i * nftl->EraseSize))
30269 +                               nftl->ReplUnitTable[i] = BLOCK_RESERVED;
30270                 }
30271                 
30272                 nftl->MediaUnit = block;
30273 @@ -253,21 +269,16 @@
30274                               int check_oob)
30275  {
30276         int i, retlen;
30277 -       u8 buf[SECTORSIZE];
30278 +       u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
30279  
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)
30285                         return -1;
30286                 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
30287                         return -1;
30288  
30289                 if (check_oob) {
30290 -                       if (MTD_READOOB(nftl->mbd.mtd, address, nftl->mbd.mtd->oobsize,
30291 -                                       &retlen, buf) < 0)
30292 -                               return -1;
30293 -                       if (memcmpb(buf, 0xff, nftl->mbd.mtd->oobsize) != 0)
30294 +                       if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0)
30295                                 return -1;
30296                 }
30297                 address += SECTORSIZE;
30298 @@ -282,7 +293,6 @@
30299   * Return: 0 when succeed, -1 on error.
30300   *
30301   *  ToDo: 1. Is it neceressary to check_free_sector after erasing ?? 
30302 - *        2. UnitSizeFactor != 0xFF
30303   */
30304  int NFTL_formatblock(struct NFTLrecord *nftl, int block)
30305  {
30306 @@ -312,11 +322,10 @@
30307         MTD_ERASE(nftl->mbd.mtd, instr);
30308  
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);
30313 -               return -1;
30314 -       } else {
30315 +               goto fail;
30316 +       }
30317 +
30318                 /* increase and write Wear-Leveling info */
30319                 nb_erases = le32_to_cpu(uci.WearInfo);
30320                 nb_erases++;
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)
30325 -                       return -1;
30326 +                       goto fail;
30327  
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)
30331 -                       return -1;
30332 +                       goto fail;
30333                 return 0;
30334 -       }
30335 +fail:
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);
30339 +       return -1;
30340  }
30341  
30342  /* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct.
30343 @@ -441,8 +454,7 @@
30344  
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;
30351                 } else {
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
30357 @@ -1,5 +1,5 @@
30358  /*
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 $
30361   *
30362   * Parse RedBoot-style Flash Image System (FIS) tables and
30363   * produce a Linux partition array to match.
30364 @@ -8,6 +8,7 @@
30365  #include <linux/kernel.h>
30366  #include <linux/slab.h>
30367  #include <linux/init.h>
30368 +#include <linux/vmalloc.h>
30369  
30370  #include <linux/mtd/mtd.h>
30371  #include <linux/mtd/partitions.h>
30372 @@ -48,21 +49,24 @@
30373         char *names;
30374         char *nullname;
30375         int namelen = 0;
30376 +       int nulllen = 0;
30377 +#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
30378         static char nullstring[] = "unallocated";
30379 +#endif
30380  
30381 -       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
30382 +       buf = vmalloc(master->erasesize);
30383  
30384         if (!buf)
30385                 return -ENOMEM;
30386  
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);
30391  
30392         if (ret)
30393                 goto out;
30394  
30395 -       if (retlen != PAGE_SIZE) {
30396 +       if (retlen != master->erasesize) {
30397                 ret = -EIO;
30398                 goto out;
30399         }
30400 @@ -80,7 +84,7 @@
30401                 goto out;
30402         }
30403  
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;
30407  
30408                 if (buf[i].name[0] == 0xff)
30409 @@ -112,48 +116,69 @@
30410  
30411                 nrparts++;
30412         }
30413 -       if (fl->img->flash_base)
30414 +#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
30415 +       if (fl->img->flash_base) {
30416                 nrparts++;
30417 +               nulllen = sizeof(nullstring);
30418 +       }
30419  
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) {
30423                         nrparts++;
30424 +                       nulllen = sizeof(nullstring);
30425 +               }
30426         }
30427 -       parts = kmalloc(sizeof(*parts)*nrparts + sizeof(nullstring) + namelen, GFP_KERNEL);
30428 +#endif
30429 +       parts = kmalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
30430  
30431         if (!parts) {
30432                 ret = -ENOMEM;
30433                 goto out;
30434         }
30435  
30436 -       memset(parts, 0, sizeof(*parts)*nrparts + namelen);
30437 +       memset(parts, 0, sizeof(*parts)*nrparts + nulllen + namelen);
30438  
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);
30446 +       }
30447 +#endif
30448 +       names = nullname + nulllen;
30449  
30450         i=0;
30451  
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;
30457 +               i++;
30458         }
30459 +#endif
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;
30464  
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;
30471 +               }
30472 +#endif
30473                 names += strlen(names)+1;
30474  
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) {
30478                         i++;
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;
30482                 }
30483 +#endif
30484                 tmp_fl = fl;
30485                 fl = fl->next;
30486                 kfree(tmp_fl);
30487 @@ -166,7 +191,7 @@
30488                 fl = fl->next;
30489                 kfree(old);
30490         }
30491 -       kfree(buf);
30492 +       vfree(buf);
30493         return ret;
30494  }
30495  
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
30500 @@ -0,0 +1,1132 @@
30501 +/*
30502 + *  drivers/mtd/ssfdc.c
30503 + *
30504 + *  Copyright (C) 2003 Simon Haynes (simon@baydel.con)
30505 + *                     Baydel Ltd
30506 + *
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.
30510 + *
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
30515 + *
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.
30518 + *
30519 + * To build an compile the driver I added the following lines
30520 + * to mtd/Config.in
30521 + *
30522 + *  dep_tristate '  SSFDC support' CONFIG_SSFDC $CONFIG_MTD
30523 + *
30524 + * to /mtd/Makefile
30525 + *
30526 + * obj-$(CONFIG_SSFDC)             += ssfdc.o
30527 + *
30528 + * and compiled the kernel via the usual methods.
30529 + *
30530 + * I am sure that there are many problems I don't know about but here are
30531 + * some that I know of
30532 + *
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.
30543 + *
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.
30548 + *
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.
30553 + *
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
30559 + *
30560 + * 17th August 2004 MHB
30561 + *
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.
30566 + *
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
30569 + * restrictions
30570 +
30571 +
30572 +*/
30573 +
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>
30595 +
30596 +
30597 +#if (LINUX_VERSION_CODE >= 0x20100)
30598 +#include <linux/vmalloc.h>
30599 +#endif
30600 +#if (LINUX_VERSION_CODE >= 0x20303)
30601 +#include <linux/blkpg.h>
30602 +#endif
30603 +
30604 +#include <asm/semaphore.h>
30605 +
30606 +#define SSFDC_FORMAT 1
30607 +
30608 +#define PDEBUG(fmt, args...)
30609 +
30610 +#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT
30611 +#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT
30612 +
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
30618 +#else
30619 +#define request_arg_t           request_queue_t *q
30620 +#endif
30621 +
30622 +#define TRUE 1
30623 +#define FALSE 0
30624 +
30625 +#define SSFDC_MAJOR    44
30626 +
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)
30632 +
30633 +#include <linux/blk.h>
30634 +
30635 +#include "/home/simon/ebony/dbwhatu/dbwhatu/smccontrol.h"
30636 +
30637 +
30638 +
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
30646 +
30647 +
30648 +#define MAX_DEVICES    4
30649 +#define MAX_PARTITIONS         8
30650 +#define PARTITION_BITS         3
30651 +#define MAX_ZONES      8
30652 +
30653 +
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];
30660 +
30661 +
30662 +static struct nand_oobinfo ssfdc_ffoob_info = {
30663 +       .useecc = 0,
30664 +};
30665 +
30666 +
30667 +typedef struct minor_t {
30668 +       atomic_t open;
30669 +       int cached;
30670 +       unsigned char * pt_data;
30671 +       unsigned char * pt_oob;
30672 +} minor_t;
30673 +
30674 +
30675 +
30676 +typedef struct partition_t {
30677 +       int type;
30678 +       struct mtd_info *mtd;
30679 +       int count;
30680 +       unsigned int *zone;
30681 +       unsigned int zoneCount;
30682 +       minor_t minor[MAX_PARTITIONS];
30683 +       unsigned int last_written[MAX_ZONES];
30684 +} partition_t;
30685 +
30686 +partition_t SMCParts[MAX_DEVICES];
30687 +
30688 +
30689 +static unsigned char ssfdc_ecc[] = {14, 13, 15, 9, 8, 10};
30690 +
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;
30695 +
30696 +
30697 +static struct gendisk ssfdc_gendisk = {
30698 +    major:             SSFDC_MAJOR,
30699 +    major_name:                "ssfdc",
30700 +    minor_shift:       PARTITION_BITS,
30701 +    max_p:             MAX_PARTITIONS,
30702 +    part:              ssfdc_hd,
30703 +    sizes:             ssfdc_sizes,
30704 +};
30705 +
30706 +
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);
30722 +
30723 +
30724 +
30725 +static DECLARE_WAIT_QUEUE_HEAD(ssfdc_wq);
30726 +
30727 +
30728 +static struct mtd_notifier ssfdc_notifier = {
30729 +       add:            ssfdc_notify_add,
30730 +       remove:         ssfdc_notify_remove,
30731 +};
30732 +
30733 +
30734 +
30735 +static struct block_device_operations ssfdc_fops = {
30736 +    open:      ssfdc_open,
30737 +    release:   ssfdc_close,
30738 +    ioctl:     ssfdc_ioctl,
30739 +};
30740 +                                               
30741 +static struct semaphore ssfdc_semaphore;
30742 +
30743 +static void ssfdc_notify_add(struct mtd_info *mtd) {
30744 +
30745 +
30746 +
30747 +       
30748 +       if(mtd->index >= 1) return;   // Hack to limit SSFDC to 1 partition
30749 +
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);      
30752 +       }
30753 +       else {
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);
30760 +               
30761 +
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;
30765 +               }
30766 +               else {
30767 +                       memset((void *)SMCParts[mtd->index].zone, 0xFF, SMCParts[mtd->index].zoneCount * 8192);
30768 +               }
30769 +       
30770 +               ssfdc_read_partitions((partition_t *)&SMCParts[mtd->index].type);
30771 +       }
30772 +       return;
30773 +
30774 +}
30775 +static int ssfdc_read_partitions(partition_t * pt_smcpart) {
30776 +
30777 +       int whole, i, j, size;
30778 +
30779 +//=printk("ssfdc_read_partitions : start\n");
30780 +
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);
30784 +
30785 +               return -EBUSY;
30786 +               }
30787 +
30788 +
30789 +//=printk("ssfdc_read_partitions : tables start\n");
30790 +       ssfdc_tables(pt_smcpart);
30791 +//=printk("ssfdc_read_partitions : tables end\n");
30792 +
30793 +       whole = pt_smcpart->count << PARTITION_BITS;                    
30794 +
30795 +
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);
30801 +               }
30802 +               ssfdc_hd[whole+j].start_sect = 0;
30803 +               ssfdc_hd[whole+j].nr_sects = 0;
30804 +       }
30805 +
30806 +
30807 +       size = (((pt_smcpart->mtd->size / 16384) * 1000) / 1024) * 32;
30808 +       size /= (0x8 * 0x20);
30809 +       size = size * (0x8 * 0x20);
30810 +
30811 +//=printk("ssfdc_read_partitions : register start\n");
30812 +
30813 +    register_disk(&ssfdc_gendisk, whole >> PARTITION_BITS, MAX_PARTITIONS,
30814 +                 &ssfdc_fops, size);
30815 +
30816 +//=printk("ssfdc_read_partitions : register end\n");
30817 +
30818 +
30819 +       return 0;
30820 +}
30821 +
30822 +
30823 +static void ssfdc_notify_remove(struct mtd_info *mtd) {
30824 +int i, j, whole;
30825 +
30826 +       i=mtd->index;
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;
30835 +                       }
30836 +               }
30837 +               return;
30838 +       }
30839 +       return;
30840 +}
30841 +
30842 +
30843 +
30844 +static int ssfdc_ioctl(struct inode *inode, struct file *file,
30845 +               u_int cmd, u_long arg) {
30846 +
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;
30851 +    int size;
30852 +/*
30853 +       unsigned char smc_status;
30854 +
30855 +       smc_status = in_8((void *)&pt_ssfdc_smc->smc_status);
30856 +       if(!(smc_status & SMC_PRESENT)) {
30857 +               printk("ssfdc : media not present\n");
30858 +               ret = 1;
30859 +               goto ssfdc_ioctl_error;
30860 +       }
30861 +
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");
30867 +       }
30868 +*/
30869 +       switch(cmd) {
30870 +
30871 +           case HDIO_GETGEO:
30872 +                       memset(&geo, 0, sizeof(geo));
30873 +                       size = (((pt_smcpart->mtd->size / 16384) * 1000) / 1024) * 32;
30874 +                       size /= (0x8 * 0x20);
30875 +                       geo.heads = 0x8;
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));
30882 +                       ret = 0;
30883 +               break;
30884 +
30885 +           case BLKGETSIZE64:
30886 +               case BLKGETSIZE:
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));
30890 +               break;
30891 +               case BLKSSZGET:
30892 +                       size = 512;
30893 +                       ret = copy_to_user((unsigned long *)arg, &size, sizeof(size));
30894 +               break;
30895 +               break;
30896 +
30897 +       case BLKRRPART:
30898 +                               if(minor & ((1<< PARTITION_BITS) - 1)) return -ENOTTY;
30899 +                               ssfdc_read_partitions(pt_smcpart);
30900 +                               ret=0;
30901 +               break;
30902 +               case BLKFLSBUF:
30903 +                       printk(KERN_WARNING "ssfdc : block ioctl 0x%x\n", cmd);
30904 +               break;
30905 +
30906 +               default:
30907 +                       printk(KERN_WARNING "ssfdc: unknown ioctl 0x%x\n", cmd);
30908 +    }
30909 +
30910 +//ssfdc_ioctl_error:
30911 +    return(ret);
30912 +
30913 +}
30914 +static int ssfdc_open(struct inode *inode, struct file *file)
30915 +{
30916 +    int minor = MINOR(inode->i_rdev);
30917 +    partition_t *pt_smcpart;
30918 +       int index;
30919 +
30920 +    if (minor >= MAX_MTD_DEVICES)
30921 +       return -ENODEV;
30922 +
30923 +    index = (minor & ~(MAX_PARTITIONS -1)) >> PARTITION_BITS;
30924 +
30925 +
30926 +    if(SMCParts[index].type != SSFDC_FORMAT)
30927 +       return -ENXIO;
30928 +
30929 +       pt_smcpart = &SMCParts[index];
30930 +
30931 +
30932 +       if(!pt_smcpart->zone)
30933 +       return -ENXIO;
30934
30935 +
30936 +    BLK_INC_USE_COUNT;
30937 +
30938 +    if (!get_mtd_device(pt_smcpart->mtd, -1)) {
30939 +           BLK_DEC_USE_COUNT;
30940 +           return -ENXIO;
30941 +    }
30942 +
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;
30946 +            return -EROFS;
30947 +    }
30948 +
30949 +
30950 +    atomic_inc(&pt_smcpart->minor[minor & ~(MAX_PARTITIONS -1)].open);
30951 +
30952 +       PDEBUG("ssfdc_open : device %d\n", minor);
30953 +
30954 +       return(0);
30955 +}
30956 +
30957 +static void ssfdc_tables(partition_t * pt_smcpart) {
30958 +
30959 +       int * logical, * physical;
30960 +       int offset = 0;
30961 +       int zone, block;
30962 +       int i, retlen;
30963 +       int block_address, parity;
30964 +       int h, l;
30965 +
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));
30971 +
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;
30978 +                               return;
30979 +                       }
30980 +
30981 +                       l = (ssfdc_buffer[7] & 0xFF);
30982 +                       h = (ssfdc_buffer[6] & 0xFF);
30983 +                       block_address = l + (h << 8L);
30984 +
30985 +                       if((block_address & ~0x7FF) != 0x1000) {
30986 +                                       continue;
30987 +                       }
30988 +
30989 +                       parity = block_address & 0x01;
30990 +                       
30991 +                       block_address &= 0x7FF;
30992 +                       block_address >>= 1;
30993 +
30994 +
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]);
31000 +                               }
31001 +                               printk("\n");
31002 +                               pt_smcpart->type = 0;
31003 +                               return;                         
31004 +                       }
31005 +
31006 +
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);
31013 +                       
31014 +
31015 +               }
31016 +       }
31017 +       return;
31018 +}
31019 +int ssfdc_parity(int number) {
31020 +       int i;
31021 +       int parity = 1; // the 0x1000 bit
31022 +
31023 +       for(i=0; i<10; i++) {
31024 +               parity += ((number >> i) & 1);
31025 +       }
31026 +       PDEBUG("ssfdc_parity : number 0x%x, parity 0x%x\n", number, parity);
31027 +       return(parity % 2);
31028 +}
31029 +static int ssfdc_physical(partition_t * pt_smcpart, int zone, int block) {
31030 +
31031 +       unsigned int * logical;
31032 +
31033 +       logical = pt_smcpart->zone + (zone * 2048);
31034 +
31035 +       logical += block;
31036 +
31037 +       if(*logical == 0xFFFFFFFF) {
31038 +               PDEBUG("ssfdc_physical : physical for zone %d, block %d invalid\n", zone, block);
31039 +               return(-1);
31040 +       }
31041 +
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);
31044 +}
31045 +
31046 +static int ssfdc_close(struct inode *inode, struct file *file)
31047 +{                       
31048 +    int minor = MINOR(inode->i_rdev);
31049 +    partition_t *pt_smcpart;
31050 +       int index = (minor & ~(MAX_PARTITIONS -1)) >> PARTITION_BITS;
31051 +
31052 +    if (minor >= MAX_MTD_DEVICES)
31053 +       return -ENODEV;
31054 +
31055 +    if(SMCParts[index].type != SSFDC_FORMAT)
31056 +       return -ENXIO;
31057 +
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;
31062 +
31063 +    return(0);
31064 +} 
31065 +
31066 +
31067 +static void do_ssfdc_request(request_arg_t)
31068 +{
31069 +    int ret, minor;
31070 +    partition_t *pt_smcpart;
31071 +       int index;
31072 +    do {
31073 +
31074 +       INIT_REQUEST;
31075 +
31076 +
31077 +
31078 +       minor = MINOR(CURRENT->rq_dev);
31079 +       index = (minor & ~(MAX_PARTITIONS -1)) >> PARTITION_BITS;
31080 +
31081 +       pt_smcpart = &SMCParts[index];
31082 +       if (pt_smcpart->type == SSFDC_FORMAT) {
31083 +               ret = 0;
31084 +               switch (CURRENT->cmd) {
31085 +                       case READ:
31086 +                               ret = ssfdc_read(pt_smcpart, CURRENT->buffer,
31087 +                                       CURRENT->sector + ssfdc_hd[minor].start_sect,
31088 +                                       CURRENT->current_nr_sectors);
31089 +                   break;
31090 +
31091 +                       case WRITE:
31092 +                       ret = ssfdc_write(pt_smcpart, CURRENT->buffer,
31093 +                                   CURRENT->sector     + ssfdc_hd[minor].start_sect,
31094 +                                   CURRENT->current_nr_sectors);
31095 +                   break;
31096 +
31097 +                 default:
31098 +                   panic("do_ssfdc_request : unknown block command!\n");
31099 +                 }
31100 +       
31101 +       } else {
31102 +         ret = 1;
31103 +         PDEBUG("not ssfdc partition type\n");
31104 +       }
31105 +
31106 +       if (!ret) {
31107 +         CURRENT->sector += CURRENT->current_nr_sectors;
31108 +       }
31109 +
31110 +       end_request((ret == 0) ? 1 : 0);
31111 +    } while (1);
31112 +}
31113 +
31114 +static int ssfdc_write(partition_t *pt_smcpart, caddr_t buffer,
31115 +                    u_long sector, u_long nblocks)
31116 +{
31117 +       int zone, block, offset;
31118 +       int sectors_written = 0;
31119 +       int physical;
31120 +       int * pt_logical;
31121 +       int * pt_physical;
31122 +       int new = -1;
31123 +       int size;
31124 +       int retlen;
31125 +       int i;
31126 +       int sc;
31127 +       int ptr_done = 0;
31128 +       unsigned char * ptr = (unsigned char *)buffer;
31129 +       unsigned char ecc_code[6], ecc_calc[6];
31130 +       int do_erase;
31131 +//     unsigned char smc_status;
31132 +
31133 +
31134 +
31135 +       offset = (sector % SECTORS_PER_ZONE) % SECTORS_PER_BLOCK ;
31136 +
31137 +       PDEBUG("write device %d, sector %d, count %d\n",
31138 +                       pt_smcpart->count, sector, nblocks);
31139 +/*
31140 +       smc_status = in_8((void *)&pt_ssfdc_smc->smc_status);
31141 +       if(!(smc_status & SMC_PRESENT)) {
31142 +               printk("ssfdc : media not present\n");
31143 +               return -ENXIO;
31144 +       }
31145 +
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");
31150 +       }
31151 +*/
31152 +       while(sectors_written < nblocks) {
31153 +
31154 +               new = -1;
31155 +               do_erase = FALSE;
31156 +    
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 ;
31160 +
31161 +               pt_logical = pt_smcpart->zone + (zone * 2048);
31162 +               pt_physical = pt_smcpart->zone + (zone * 2048) + 1024;
31163 +
31164 +               size = ((SECTORS_PER_BLOCK - offset) < (nblocks - sectors_written)) ?
31165 +                               (SECTORS_PER_BLOCK - offset) : (nblocks - sectors_written);
31166 +               size *= SECTOR_SIZE;
31167 +
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);
31170 +
31171 +               physical = ssfdc_physical(pt_smcpart, zone, block);
31172 +
31173 +
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");
31180 +                                       return -ENXIO;
31181 +                               }
31182 +
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");
31187 +                                               return -ENXIO;
31188 +                                       }
31189 +
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]);
31195 +                               }
31196 +
31197 +                       }
31198 +                       
31199 +                       for(sc=0; sc<SECTORS_PER_BLOCK; sc++) {
31200 +                               if(offset > sc) {
31201 +                                       PDEBUG("offset %d, sector %d\n", offset, sc);
31202 +                                       continue;
31203 +                               }
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");
31207 +                                       return -ENXIO;
31208 +                               }
31209 +
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]);
31215 +                               
31216 +                               /* find out if the block is being used */
31217 +
31218 +
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;
31230 +
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);
31236 +                                               return -ENXIO;
31237 +                                       }
31238 +
31239 +                    ptr_done += SECTOR_SIZE;
31240 +                                       if(ptr_done >= size) break;
31241 +                               }
31242 +                               else {
31243 +                                       new = ssfdc_allocate_new(pt_smcpart, zone);
31244 +                                       /* erase the old block */
31245 +                           *(pt_physical + ((physical % ZONE_SIZE) / SMC_BLOCK_SIZE)) = 0xFFFFFFFF;
31246 +
31247 +                                       PDEBUG("ssfdc_write : physical 0x%x + 0x%x = 0x%x\n",
31248 +                                               (unsigned int)pt_physical, ((physical % ZONE_SIZE) / SMC_BLOCK_SIZE), 0xFFFFFFFF);
31249 +                                       do_erase = TRUE;
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);
31252 +                                       break;
31253 +                               }
31254 +                       }
31255 +               }
31256 +               else {
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);
31262 +               }
31263 +
31264 +
31265 +
31266 +               if(new != -1) {
31267 +
31268 +
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);
31281 +                       }
31282 +
31283 +
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);
31288 +                               return -ENXIO;
31289 +                       }
31290 +                       /* change the mapping table to reflect the new block placement */
31291 +
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);
31295 +
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);
31299 +
31300 +
31301 +                       ssfdc_cached = new;
31302 +           }
31303 +
31304 +
31305 +               ptr += size;
31306 +               ptr_done = 0;
31307 +               sectors_written += (size / SECTOR_SIZE);
31308 +               if(do_erase) ssfdc_erase(pt_smcpart, physical);
31309 +
31310 +       }
31311 +
31312 +
31313 +
31314 +
31315 +       return(0);
31316 +}
31317 +static int ssfdc_sector_blank(partition_t * pt_smcpart, int sc) {
31318 +int b;
31319 +
31320 +       for(b=0; b<SECTOR_SIZE; b++) {
31321 +               if(ssfdc_scratch[b + (sc * SECTOR_SIZE)] != 0xFF) return(0);
31322 +       }
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);
31326 +       }
31327 +    return(1);
31328 +}
31329 +static int ssfdc_allocate_new(partition_t * pt_smcpart, int zone) {
31330 +
31331 +       int new = pt_smcpart->last_written[zone] + 1;
31332 +       int * pt_physical;
31333 +       int physical;
31334 +       int block;
31335 +       int retlen;
31336 +       unsigned char oob[16];
31337 +       
31338 +
31339 +       if(new >= BLOCKS_PER_ZONE) new = 0;
31340 +
31341 +
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);
31346 +
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));
31356 +                       }
31357 +                       else {
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);
31359 +                       }
31360 +               }
31361 +               new++;
31362 +               if(new >= BLOCKS_PER_ZONE) new = 0;
31363 +       }
31364 +
31365 +       panic("ssfdc_allocate_new : cant find free block\n");
31366 +
31367 +}
31368 +       
31369 +
31370 +
31371 +static int ssfdc_read(partition_t *pt_smcpart, caddr_t buffer,
31372 +                   u_long sector, u_long nblocks)
31373 +{
31374 +       int zone, block, offset;
31375 +       int sectors_read = 0;
31376 +    int physical;
31377 +       int size;
31378 +       int retlen;
31379 +       int i;
31380 +       int sc;
31381 +       unsigned char * ptr = (unsigned char *)buffer;
31382 +       unsigned char ecc_code[6], ecc_calc[6];
31383 +/*
31384 +    unsigned char smc_status;
31385 +
31386 +       smc_status = in_8((void *)&pt_ssfdc_smc->smc_status);
31387 +       if(!(smc_status & SMC_PRESENT)) {
31388 +               printk("ssfdc : media not present\n");
31389 +               return -ENXIO;
31390 +       }
31391 +
31392 +
31393 +
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");
31398 +       }
31399 +*/
31400 +       while(sectors_read < nblocks) {
31401 +
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 ;
31405 +
31406 +
31407 +               if(offset) {
31408 +                       size = ((SECTORS_PER_BLOCK - offset) < (nblocks - sectors_read)) ?
31409 +                                       (SECTORS_PER_BLOCK - offset) : (nblocks - sectors_read);
31410 +               }
31411 +               else {
31412 +                       size = (SECTORS_PER_BLOCK < (nblocks - sectors_read)) ? SECTORS_PER_BLOCK : nblocks - sectors_read;
31413 +               }
31414 +               size *= SECTOR_SIZE;
31415 +
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);
31418 +
31419 +                       
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");
31427 +                                       return -ENXIO;
31428 +                               }
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");
31433 +                                               return -ENXIO;
31434 +                                       }
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]);
31441 +                               }
31442 +
31443 +                               /* Get the ecc bytes and check that they are ok */
31444 +
31445 +
31446 +                       }
31447 +                       ssfdc_cached = physical;
31448 +                       
31449 +                       
31450 +               }
31451 +               else {
31452 +                       memset(ssfdc_scratch, 0xFF, sizeof(ssfdc_scratch));
31453 +                       ssfdc_cached = 0xFFFFFFFF;
31454 +               }
31455 +                       
31456 +
31457 +               memcpy(ptr, &ssfdc_scratch[(offset * SECTOR_SIZE)], size);
31458 +               ptr += size;
31459 +               sectors_read += (size / SECTOR_SIZE);   
31460 +       }
31461 +
31462 +
31463 +                                                           
31464 +       return(0);
31465 +}
31466 +
31467 +static void ssfdc_erase_callback(struct erase_info *erase) {
31468 +
31469 +       PDEBUG("ssfdc_erase_callback : wake erase\n");
31470 +       up(&ssfdc_semaphore);
31471 +       PDEBUG("ssfdc_erase_callback : woken erase\n");
31472 +}
31473 +
31474 +static int ssfdc_erase(partition_t *pt_smcpart, unsigned int offset)
31475 +{
31476 +       int ret = 0;
31477 +       struct erase_info *erase;
31478 +       unsigned char * junk;
31479 +       unsigned char * oob;
31480 +       int retlen;
31481 +       int b, sc;
31482 +
31483 +
31484 +       PDEBUG("ssfdc_erase : offset 0x%08x\n", offset);
31485 +
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;
31489 +
31490 +       if (!erase)
31491 +                return -ENOMEM;
31492 +       if (!junk)
31493 +                return -ENOMEM;
31494 +
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);
31499 +       if(ret) {
31500 +               printk(KERN_WARNING "ssfdc_erase : failed status 0x%x\n", ret);
31501 +               goto end;
31502 +
31503 +       }
31504 +
31505 +       down(&ssfdc_semaphore);
31506 +
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);
31511 +               goto end;
31512 +       }
31513 +
31514 +
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))));
31520 +                               goto end;
31521 +                       }
31522 +               }
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);
31526 +                       goto end;
31527 +               }
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));
31532 +                               goto end;
31533 +                       }
31534 +               }
31535 +       }
31536 +
31537 +end:
31538 +       
31539 +    kfree(erase);
31540 +       kfree(junk);
31541 +
31542 +    return ret;
31543 +} /* erase_xfer */
31544 +
31545 +
31546 +
31547 +
31548 +
31549 +int init_ssfdc(void)
31550 +{
31551 +       int result, i;
31552 +
31553 +//     unsigned char smc_status;
31554 +//     #define B01159_FIO_PBASE 0x0000000148000000  /* Physical Base address of SMC control chip  */
31555 +
31556 +       printk(KERN_INFO "SSFDC block device translation layer V1.0\n");
31557 +/*
31558 +       pt_ssfdc_smc = ioremap64(B01159_FIO_PBASE, 1024);
31559 +       if(!pt_ssfdc_smc){
31560 +       printk("ssfdc : failed to map SMC control device\n");
31561 +        return(-EFAULT);
31562 +       }
31563 +       
31564 +       smc_status = in_8((void *)&pt_ssfdc_smc->smc_status);
31565 +*/     
31566 +    memset(ssfdc_ffoob_buf, 0xFF, sizeof(ssfdc_ffoob_buf));
31567 +    
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;
31572 +       }
31573 +       blksize_size[SSFDC_MAJOR] = ssfdc_blocksizes;
31574 +       ssfdc_gendisk.major = SSFDC_MAJOR;
31575 +
31576 +
31577 +       memset(ssfdc_scratch, 0xFF, sizeof(ssfdc_scratch));
31578 +
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");
31582 +               return(result);
31583 +       }
31584 +//     if(ssfdc_major == 0) ssfdc_major = result;
31585 +       
31586 +       blk_init_queue(BLK_DEFAULT_QUEUE(ssfdc_major), &do_ssfdc_request);
31587 +
31588 +       add_gendisk(&ssfdc_gendisk);
31589 +
31590 +
31591 +
31592 +       register_mtd_user(&ssfdc_notifier);
31593 +
31594 +
31595 +       init_MUTEX_LOCKED(&ssfdc_semaphore);
31596 +
31597 +
31598 +
31599 +       return 0;
31600 +}
31601 +
31602 +static void __exit cleanup_ssfdc(void)
31603 +{
31604 +       int i;
31605 +
31606 +       for(i=0; i<MAX_DEVICES; i++) {
31607 +                       if(SMCParts[i].zone)kfree(SMCParts[i].zone);
31608 +       }
31609 +
31610 +
31611 +       unregister_mtd_user(&ssfdc_notifier);
31612 +       unregister_blkdev(ssfdc_major, "ssfdc");
31613 +       blk_cleanup_queue(BLK_DEFAULT_QUEUE(ssfdc_major));
31614 +
31615 +
31616 +
31617 +       blksize_size[SSFDC_MAJOR] = NULL;
31618 +       del_gendisk(&ssfdc_gendisk);
31619 +
31620 +}
31621 +
31622 +module_init(init_ssfdc);
31623 +module_exit(cleanup_ssfdc);
31624 +
31625 +
31626 +MODULE_LICENSE("GPL");
31627 +MODULE_AUTHOR("Simon Haynes <simon@baydel.com>");
31628 +MODULE_DESCRIPTION("SSFDC translation layer support for MTD");
31629 +
31630 +
31631 +
31632 +
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
31637 @@ -1,7 +1,7 @@
31638  
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 $
31643   */
31644  
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>
31652  
31653 -/*
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)
31658 - *
31659 - * By default, all (known) geometries are supported.
31660 - */
31661 -
31662 -#ifndef CONFIG_MTD_CFI_GEOMETRY
31663 -
31664 -/* The default case - support all but 64-bit, which has
31665 -   a performance penalty */
31666 -
31667 -#define CFIDEV_INTERLEAVE_1 (1)
31668 -#define CFIDEV_INTERLEAVE_2 (2)
31669 -#define CFIDEV_INTERLEAVE_4 (4)
31670 -
31671 -#define CFIDEV_BUSWIDTH_1 (1)
31672 -#define CFIDEV_BUSWIDTH_2 (2)
31673 -#define CFIDEV_BUSWIDTH_4 (4)
31674 -
31675 -typedef __u32 cfi_word;
31676 -
31677 -#else
31678 -
31679 -/* Explicitly configured buswidth/interleave support */
31680 -
31681  #ifdef CONFIG_MTD_CFI_I1
31682 -#define CFIDEV_INTERLEAVE_1 (1)
31683 -#endif
31684 -#ifdef CONFIG_MTD_CFI_I2
31685 -#define CFIDEV_INTERLEAVE_2 (2)
31686 -#endif
31687 -#ifdef CONFIG_MTD_CFI_I4
31688 -#define CFIDEV_INTERLEAVE_4 (4)
31689 -#endif
31690 -#ifdef CONFIG_MTD_CFI_I8
31691 -#define CFIDEV_INTERLEAVE_8 (8)
31692 -#endif
31693 -
31694 -#ifdef CONFIG_MTD_CFI_B1
31695 -#define CFIDEV_BUSWIDTH_1 (1)
31696 -#endif
31697 -#ifdef CONFIG_MTD_CFI_B2
31698 -#define CFIDEV_BUSWIDTH_2 (2)
31699 -#endif
31700 -#ifdef CONFIG_MTD_CFI_B4
31701 -#define CFIDEV_BUSWIDTH_4 (4)
31702 -#endif
31703 -#ifdef CONFIG_MTD_CFI_B8
31704 -#define CFIDEV_BUSWIDTH_8 (8)
31705 -#endif
31706 -
31707 -/* pick the largest necessary */
31708 -#ifdef CONFIG_MTD_CFI_B8
31709 -typedef __u64 cfi_word;
31710 -
31711 -/* This only works if asm/io.h is included first */
31712 -#ifndef __raw_readll
31713 -#define __raw_readll(addr)     (*(volatile __u64 *)(addr))
31714 -#endif
31715 -#ifndef __raw_writell
31716 -#define __raw_writell(v, addr) (*(volatile __u64 *)(addr) = (v))
31717 -#endif
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 */
31724 -
31725 -#endif
31726 -
31727 -/*
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
31739 - * out of range.
31740 - */
31741 -
31742 -#ifdef CFIDEV_INTERLEAVE_1
31743 -# ifdef CFIDEV_INTERLEAVE
31744 -#  undef CFIDEV_INTERLEAVE
31745 -#  define CFIDEV_INTERLEAVE (cfi->interleave)
31746 -# else
31747 -#  define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_1
31748 -# endif
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)
31752  #else
31753 -# define cfi_interleave_is_1() (0)
31754 +#define cfi_interleave_is_1(cfi) (0)
31755  #endif
31756  
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)
31765  # else
31766 -#  define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_2
31767 +#  define cfi_interleave(cfi) 2
31768  # endif
31769 -# define cfi_interleave_is_2() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_2)
31770 +#define cfi_interleave_is_2(cfi) (cfi_interleave(cfi) == 2)
31771  #else
31772 -# define cfi_interleave_is_2() (0)
31773 +#define cfi_interleave_is_2(cfi) (0)
31774  #endif
31775  
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)
31784  # else
31785 -#  define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_4
31786 +#  define cfi_interleave(cfi) 4
31787  # endif
31788 -# define cfi_interleave_is_4() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_4)
31789 +#define cfi_interleave_is_4(cfi) (cfi_interleave(cfi) == 4)
31790  #else
31791 -# define cfi_interleave_is_4() (0)
31792 +#define cfi_interleave_is_4(cfi) (0)
31793  #endif
31794  
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)
31803  # else
31804 -#  define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_8
31805 +#  define cfi_interleave(cfi) 8
31806  # endif
31807 -# define cfi_interleave_is_8() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_8)
31808 +#define cfi_interleave_is_8(cfi) (cfi_interleave(cfi) == 8)
31809  #else
31810 -# define cfi_interleave_is_8() (0)
31811 +#define cfi_interleave_is_8(cfi) (0)
31812  #endif
31813  
31814 -#ifndef CFIDEV_INTERLEAVE
31815 -#error You must define at least one interleave to support!
31816 +static inline int cfi_interleave_supported(int i)
31817 +{
31818 +       switch (i) {
31819 +#ifdef CONFIG_MTD_CFI_I1
31820 +       case 1:
31821  #endif
31822 -
31823 -#ifdef CFIDEV_BUSWIDTH_1
31824 -# ifdef CFIDEV_BUSWIDTH
31825 -#  undef CFIDEV_BUSWIDTH
31826 -#  define CFIDEV_BUSWIDTH (map->buswidth)
31827 -# else
31828 -#  define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_1
31829 -# endif
31830 -# define cfi_buswidth_is_1() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_1)
31831 -#else
31832 -# define cfi_buswidth_is_1() (0)
31833 +#ifdef CONFIG_MTD_CFI_I2
31834 +       case 2:
31835  #endif
31836 -
31837 -#ifdef CFIDEV_BUSWIDTH_2
31838 -# ifdef CFIDEV_BUSWIDTH
31839 -#  undef CFIDEV_BUSWIDTH
31840 -#  define CFIDEV_BUSWIDTH (map->buswidth)
31841 -# else
31842 -#  define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_2
31843 -# endif
31844 -# define cfi_buswidth_is_2() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_2)
31845 -#else
31846 -# define cfi_buswidth_is_2() (0)
31847 +#ifdef CONFIG_MTD_CFI_I4
31848 +       case 4:
31849  #endif
31850 -
31851 -#ifdef CFIDEV_BUSWIDTH_4
31852 -# ifdef CFIDEV_BUSWIDTH
31853 -#  undef CFIDEV_BUSWIDTH
31854 -#  define CFIDEV_BUSWIDTH (map->buswidth)
31855 -# else
31856 -#  define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_4
31857 -# endif
31858 -# define cfi_buswidth_is_4() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_4)
31859 -#else
31860 -# define cfi_buswidth_is_4() (0)
31861 +#ifdef CONFIG_MTD_CFI_I8
31862 +       case 8:
31863  #endif
31864 +               return 1;
31865  
31866 -#ifdef CFIDEV_BUSWIDTH_8
31867 -# ifdef CFIDEV_BUSWIDTH
31868 -#  undef CFIDEV_BUSWIDTH
31869 -#  define CFIDEV_BUSWIDTH (map->buswidth)
31870 -# else
31871 -#  define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_8
31872 -# endif
31873 -# define cfi_buswidth_is_8() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_8)
31874 -#else
31875 -# define cfi_buswidth_is_8() (0)
31876 -#endif
31877 +       default:
31878 +               return 0;
31879 +       }
31880 +}
31881  
31882 -#ifndef CFIDEV_BUSWIDTH
31883 -#error You must define at least one bus width to support!
31884 -#endif
31885  
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 @@
31889  
31890  /* Basic Query Structure */
31891  struct cfi_ident {
31892 -  __u8  qry[3];
31893 -  __u16 P_ID;
31894 -  __u16 P_ADR;
31895 -  __u16 A_ID;
31896 -  __u16 A_ADR;
31897 -  __u8  VccMin;
31898 -  __u8  VccMax;
31899 -  __u8  VppMin;
31900 -  __u8  VppMax;
31901 -  __u8  WordWriteTimeoutTyp;
31902 -  __u8  BufWriteTimeoutTyp;
31903 -  __u8  BlockEraseTimeoutTyp;
31904 -  __u8  ChipEraseTimeoutTyp;
31905 -  __u8  WordWriteTimeoutMax;
31906 -  __u8  BufWriteTimeoutMax;
31907 -  __u8  BlockEraseTimeoutMax;
31908 -  __u8  ChipEraseTimeoutMax;
31909 -  __u8  DevSize;
31910 -  __u16 InterfaceDesc;
31911 -  __u16 MaxBufWriteSize;
31912 -  __u8  NumEraseRegions;
31913 -  __u32 EraseRegionInfo[0]; /* Not host ordered */
31914 +       uint8_t  qry[3];
31915 +       uint16_t P_ID;
31916 +       uint16_t P_ADR;
31917 +       uint16_t A_ID;
31918 +       uint16_t A_ADR;
31919 +       uint8_t  VccMin;
31920 +       uint8_t  VccMax;
31921 +       uint8_t  VppMin;
31922 +       uint8_t  VppMax;
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;
31931 +       uint8_t  DevSize;
31932 +       uint16_t InterfaceDesc;
31933 +       uint16_t MaxBufWriteSize;
31934 +       uint8_t  NumEraseRegions;
31935 +       uint32_t EraseRegionInfo[0]; /* Not host ordered */
31936  } __attribute__((packed));
31937  
31938  /* Extended Query Structure for both PRI and ALT */
31939  
31940  struct cfi_extquery {
31941 -  __u8  pri[3];
31942 -  __u8  MajorVersion;
31943 -  __u8  MinorVersion;
31944 +       uint8_t  pri[3];
31945 +       uint8_t  MajorVersion;
31946 +       uint8_t  MinorVersion;
31947  } __attribute__((packed));
31948  
31949  /* Vendor-Specific PRI for Intel/Sharp Extended Command Set (0x0001) */
31950  
31951  struct cfi_pri_intelext {
31952 -  __u8  pri[3];
31953 -  __u8  MajorVersion;
31954 -  __u8  MinorVersion;
31955 -  __u32 FeatureSupport;
31956 -  __u8  SuspendCmdSupport;
31957 -  __u16 BlkStatusRegMask;
31958 -  __u8  VccOptimal;
31959 -  __u8  VppOptimal;
31960 -  __u8  NumProtectionFields;
31961 -  __u16 ProtRegAddr;
31962 -  __u8  FactProtRegSize;
31963 -  __u8  UserProtRegSize;
31964 +       uint8_t  pri[3];
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));
31978 +
31979 +/* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */
31980 +
31981 +struct cfi_pri_amdstd {
31982 +       uint8_t  pri[3];
31983 +       uint8_t  MajorVersion;
31984 +       uint8_t  MinorVersion;
31985 +       uint8_t  SiliconRevision; /* bits 1-0: Address Sensitive Unlock */
31986 +       uint8_t  EraseSuspend;
31987 +       uint8_t  BlkProt;
31988 +       uint8_t  TmpBlkUnprotect;
31989 +       uint8_t  BlkProtUnprot;
31990 +       uint8_t  SimultaneousOps;
31991 +       uint8_t  BurstMode;
31992 +       uint8_t  PageMode;
31993 +       uint8_t  VppMin;
31994 +       uint8_t  VppMax;
31995 +       uint8_t  TopBottom;
31996  } __attribute__((packed));
31997  
31998  struct cfi_pri_query {
31999 -  __u8  NumFields;
32000 -  __u32 ProtField[1]; /* Not host ordered */
32001 +       uint8_t  NumFields;
32002 +       uint32_t ProtField[1]; /* Not host ordered */
32003  } __attribute__((packed));
32004  
32005  struct cfi_bri_query {
32006 -  __u8  PageModeReadCap;
32007 -  __u8  NumFields;
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));
32013  
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
32024  
32025  
32026 @@ -297,14 +193,13 @@
32027  #define CFI_MODE_JEDEC 0
32028  
32029  struct cfi_private {
32030 -       __u16 cmdset;
32031 +       uint16_t cmdset;
32032         void *cmdset_priv;
32033         int interleave;
32034         int device_type;
32035         int cfi_mode;           /* Are we a JEDEC device pretending to be CFI? */
32036         int addr_unlock1;
32037         int addr_unlock2;
32038 -       int fast_prog;
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 */
32044  };
32045  
32046 -#define MAX_CFI_CHIPS 8 /* Entirely arbitrary to avoid realloc() */
32047 -
32048  /*
32049   * Returns the command address according to the given geometry.
32050   */
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)
32053  {
32054         return (cmd_ofs * type) * interleave;
32055  }
32056  
32057  /*
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. 
32062   */
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)
32065  {
32066 -       cfi_word val = 0;
32067 -
32068 -       if (cfi_buswidth_is_1()) {
32069 -               /* 1 x8 device */
32070 -               val = cmd;
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);
32078 -               }
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);
32090 -               }
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 */
32098 -                       val = cmd;
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);
32110 -               }
32111 -#endif /* CFI_WORD_64 */
32112 -       }
32113 -       return val;
32114 -}
32115 -#define CMD(x)  cfi_build_cmd((x), map, cfi)
32116 -
32117 -/*
32118 - * Read a value according to the bus width.
32119 - */
32120 -
32121 -static inline cfi_word cfi_read(struct map_info *map, __u32 addr)
32122 -{
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;
32134 +       int i;
32135 +
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
32139 +          disabled */
32140 +       if (map_bankwidth_is_large(map)) {
32141 +               wordwidth = sizeof(unsigned long);
32142 +               words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
32143         } else {
32144 -               return 0;
32145 +               wordwidth = map_bankwidth(map);
32146 +               words_per_bus = 1;
32147 +       }
32148 +       
32149 +       chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
32150 +       chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
32151 +
32152 +       /* First, determine what the bit-pattern should be for a single
32153 +          device, according to chip mode and endianness... */
32154 +       switch (chip_mode) {
32155 +       default: BUG();
32156 +       case 1:
32157 +               onecmd = cmd;
32158 +               break;
32159 +       case 2:
32160 +               onecmd = cpu_to_cfi16(cmd);
32161 +               break;
32162 +       case 4:
32163 +               onecmd = cpu_to_cfi32(cmd);
32164 +               break;
32165         }
32166 -}
32167  
32168 -/*
32169 - * Write a value according to the bus width.
32170 - */
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) {
32174 +       default: BUG();
32175 +#if BITS_PER_LONG >= 64
32176 +       case 8:
32177 +               onecmd |= (onecmd << (chip_mode * 32));
32178 +#endif
32179 +       case 4:
32180 +               onecmd |= (onecmd << (chip_mode * 16));
32181 +       case 2:
32182 +               onecmd |= (onecmd << (chip_mode * 8));
32183 +       case 1:
32184 +               ;
32185 +       }
32186  
32187 -static inline void cfi_write(struct map_info *map, cfi_word val, __u32 addr)
32188 -{
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;
32201         }
32202 +
32203 +       return val;
32204  }
32205 +#define CMD(x)  cfi_build_cmd((x), map, cfi)
32206  
32207  /*
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.
32212   */
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)
32218  {
32219 -       cfi_word val;
32220 -       __u32 addr = base + cfi_build_cmd_addr(cmd_addr, CFIDEV_INTERLEAVE, type);
32221 +       map_word val;
32222 +       uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type);
32223  
32224         val = cfi_build_cmd(cmd, map, cfi);
32225  
32226         if (prev_val)
32227 -               *prev_val = cfi_read(map, addr);
32228 +               *prev_val = map_read(map, addr);
32229  
32230 -       cfi_write(map, val, addr);
32231 +       map_write(map, val, addr);
32232  
32233         return addr - base;
32234  }
32235  
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)
32238  {
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);
32248 +
32249 +       if (map_bankwidth_is_1(map)) {
32250 +               return val.x[0];
32251 +       } else if (map_bankwidth_is_2(map)) {
32252 +               return cfi16_to_cpu(val.x[0]);
32253         } else {
32254 -               return 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]);
32259         }
32260  }
32261  
32262  static inline void cfi_udelay(int us)
32263  {
32264 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
32265         unsigned long t = us * HZ / 1000000;
32266         if (t) {
32267                 set_current_state(TASK_UNINTERRUPTIBLE);
32268                 schedule_timeout(t);
32269                 return;
32270         }
32271 -#endif
32272         udelay(us);
32273         cond_resched();
32274  }
32275 @@ -480,4 +348,28 @@
32276         spin_unlock_bh(mutex);
32277  }
32278  
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 {
32282 +       uint16_t mfr;
32283 +       uint16_t id;
32284 +       void (*fixup)(struct mtd_info *mtd, void* param);
32285 +       void* param;
32286 +};
32287 +
32288 +#define CFI_MFR_ANY 0xffff
32289 +#define CFI_ID_ANY  0xffff
32290 +
32291 +#define CFI_MFR_AMD 0x0001
32292 +#define CFI_MFR_ST  0x0020     /* STMicroelectronics */
32293 +
32294 +void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups);
32295 +
32296 +typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
32297 +                             unsigned long adr, int len, void *thunk);
32298 +
32299 +int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
32300 +       loff_t ofs, size_t len, void *thunk);
32301 +
32302 +
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
32308 @@ -1,10 +1,210 @@
32309 +/*
32310 + * $Id: compatmac.h,v 1.68 2004/09/17 22:00:30 eric Exp $
32311 + *
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.
32315 + */
32316  
32317  #ifndef __LINUX_MTD_COMPATMAC_H__
32318  #define __LINUX_MTD_COMPATMAC_H__
32319  
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
32323 -   anyway... */
32324 +#include <linux/version.h>
32325 +
32326 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
32327 +#error "This kernel is too old: not supported by this file"
32328 +#endif
32329 +
32330 +       /* O(1) scheduler stuff. */
32331 +
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)
32335 +{
32336 +       recalc_sigpending(current);
32337 +}
32338 +#undef recalc_sigpending
32339 +#define recalc_sigpending() __recalc_sigpending ()
32340 +
32341 +#define set_user_nice(tsk, n) do { (tsk)->nice = n; } while(0)
32342 +#endif
32343 +
32344 +
32345 +
32346 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20)
32347 +
32348 +#ifndef yield
32349 +#define yield() do { set_current_state(TASK_RUNNING); schedule(); } while(0)
32350 +#endif
32351 +
32352 +#ifndef minor
32353 +#define major(d) (MAJOR(to_kdev_t(d)))
32354 +#define minor(d) (MINOR(to_kdev_t(d)))
32355 +#endif
32356 +
32357 +#ifndef mk_kdev
32358 +#define mk_kdev(ma,mi) MKDEV(ma,mi)
32359 +#define kdev_t_to_nr(x)        (x)
32360 +#endif
32361 +
32362 +#define need_resched() (current->need_resched)
32363 +#define cond_resched() do { if need_resched() { yield(); } } while(0)
32364 +
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)
32372 +#endif
32373 +
32374 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61)
32375 +
32376 +#include <linux/sched.h>
32377 +
32378 +#ifdef __rh_config_h__
32379 +#define sigmask_lock sighand->siglock
32380 +#define sig sighand
32381 +#endif
32382 +
32383 +static inline void __daemonize_modvers(void)
32384 +{
32385 +       daemonize();
32386 +
32387 +       spin_lock_irq(&current->sigmask_lock);
32388 +       sigfillset(&current->blocked);
32389 +       recalc_sigpending();
32390 +       spin_unlock_irq(&current->sigmask_lock);
32391 +}
32392 +#undef daemonize
32393 +#define daemonize(fmt, ...) do {                                               \
32394 +       snprintf(current->comm, sizeof(current->comm), fmt ,##__VA_ARGS__);     \
32395 +       __daemonize_modvers();                                                  \
32396 +       } while(0)
32397 +
32398 +static inline int dequeue_signal_lock(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
32399 +{
32400 +       unsigned long flags;
32401 +       unsigned long ret;
32402 +
32403 +       spin_lock_irqsave(&current->sigmask_lock, flags);
32404 +       ret = dequeue_signal(mask, info);
32405 +       spin_unlock_irqrestore(&current->sigmask_lock, flags);
32406 +
32407 +       return ret;
32408 +}
32409 +
32410 +static inline int allow_signal(int sig)
32411 +{
32412 +       if (sig < 1 || sig > _NSIG)
32413 +               return -EINVAL;
32414 +
32415 +        spin_lock_irq(&current->sigmask_lock);
32416 +       sigdelset(&current->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(&current->sigmask_lock);
32421 +       return 0;
32422 +}
32423 +static inline int disallow_signal(int sig)
32424 +{
32425 +       if (sig < 1 || sig > _NSIG)
32426 +               return -EINVAL;
32427 +
32428 +       spin_lock_irq(&current->sigmask_lock);
32429 +       sigaddset(&current->blocked, sig);
32430 +       recalc_sigpending();
32431 +
32432 +       current->sig->action[sig-1].sa.sa_handler = SIG_DFL;
32433 +       spin_unlock_irq(&current->sigmask_lock);
32434 +       return 0;
32435 +}
32436 +
32437 +#define PF_FREEZE 0
32438 +#define refrigerator(x) do { ; } while(0)
32439 +#endif
32440 +
32441 +       /* Module bits */
32442 +
32443 +
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)
32449 +#endif
32450 +
32451 +
32452 +       /* Random filesystem stuff, only for JFFS2 really */
32453 +
32454 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5)
32455 +#define parent_ino(d) ((d)->d_parent->d_inode->i_ino)
32456 +#endif
32457 +
32458 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,12)
32459 +#define PageUptodate(x) Page_Uptodate(x)
32460 +#endif
32461 +
32462 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)
32463 +#define get_seconds() CURRENT_TIME
32464 +#endif
32465 +
32466 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,53)
32467 +#define generic_file_readonly_mmap generic_file_mmap
32468 +#endif
32469 +
32470 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,70)
32471 +
32472 +#include <linux/kmod.h>
32473 +#include <linux/string.h>
32474 +
32475 +static inline char *strlcpy(char *dest, const char *src, int len)
32476 +{
32477 +       dest[len-1] = 0;
32478 +       return strncpy(dest, src, len-1);
32479 +}
32480 +
32481 +static inline int do_old_request_module(const char *mod)
32482 +{
32483 +       return request_module(mod);
32484 +}
32485 +#undef request_module
32486 +#define request_module(fmt, ...) \
32487 + ({ char modname[32]; snprintf(modname, 31, fmt ,##__VA_ARGS__); do_old_request_module(modname); })
32488 +
32489 +#endif /* 2.5.70 */
32490 +
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) );})
32495 +#endif
32496 +
32497 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
32498 +#define kvec iovec
32499 +#define __user 
32500 +#endif
32501 +
32502 +#ifndef __iomem
32503 +#define __iomem
32504 +#endif
32505 +
32506 +#ifndef list_for_each_entry_safe
32507 +/**
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.
32513 + */
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))
32519 +
32520 +#endif
32521  
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
32527 @@ -1,13 +1,21 @@
32528 -
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 $ */
32533 +/* 
32534 + * Linux driver for Disk-On-Chip devices
32535 + *
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
32540 + *
32541 + * $Id: doc2000.h,v 1.23 2004/09/16 23:26:08 gleixner Exp $ 
32542 + *
32543 + * Released under GPL
32544 + */
32545  
32546  #ifndef __MTD_DOC2000_H__
32547  #define __MTD_DOC2000_H__
32548  
32549  #include <linux/mtd/mtd.h>
32550 +#include <asm/semaphore.h>
32551  
32552  #define DoC_Sig1 0
32553  #define DoC_Sig2 1
32554 @@ -73,16 +81,16 @@
32555   * Others use readb/writeb 
32556   */
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
32569  #else
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
32575  
32576  #endif
32577 @@ -106,6 +114,7 @@
32578  #define DOC_MODE_MDWREN        0x04
32579  
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
32588  
32589 -#define MAX_FLOORS_MIL 4
32590 +#define MAX_FLOORS_MIL 1
32591  #define MAX_CHIPS_MIL 1
32592  
32593 -#define MAX_FLOORS_MPLUS 1
32594 +#define MAX_FLOORS_MPLUS 2
32595  #define MAX_CHIPS_MPLUS 1
32596  
32597  #define ADDR_COLUMN 1
32598 @@ -159,9 +168,9 @@
32599  
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 */
32607         int ioreg;
32608         
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
32614 @@ -6,7 +6,7 @@
32615   *
32616   * (C) 2000 Red Hat. GPLd.
32617   *
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 $
32620   *
32621   */
32622  
32623 @@ -43,7 +43,8 @@
32624  
32625  
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. */
32630  
32631  struct flchip {
32632         unsigned long start; /* Offset within the map */
32633 @@ -61,6 +62,7 @@
32634  
32635         int write_suspended:1;
32636         int erase_suspended:1;
32637 +       unsigned long in_progress_block_addr;
32638  
32639         spinlock_t *mutex;
32640         spinlock_t _spinlock; /* We do it like this because sometimes they'll be shared. */
32641 @@ -69,8 +71,17 @@
32642         int word_write_time;
32643         int buffer_write_time;
32644         int erase_time;
32645 +
32646 +       void *priv;
32647  };
32648  
32649 +/* This is used to handle contention on write/erase operations
32650 +   between partitions of the same physical chip. */
32651 +struct flchip_shared {
32652 +       spinlock_t lock;
32653 +       struct flchip *writing;
32654 +       struct flchip *erasing;
32655 +};
32656  
32657  
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
32663 @@ -1,5 +1,5 @@
32664  /*
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 $
32667   * 
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
32674 @@ -1,7 +1,7 @@
32675  /*
32676   * (C) 2001, 2001 Red Hat, Inc.
32677   * GPL'd
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 $
32680   */
32681  
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>
32688  
32689  struct chip_probe {
32690         char *name;
32691         int (*probe_chip)(struct map_info *map, __u32 base,
32692 -                         struct flchip *chips, struct cfi_private *cfi);
32693 -
32694 +                         unsigned long *chip_map, struct cfi_private *cfi);
32695  };
32696  
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
32702 @@ -3,105 +3,32 @@
32703   *
32704   *     (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
32705   *
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 $
32708   */
32709  
32710  #ifndef __MTD_INFTL_H__
32711  #define __MTD_INFTL_H__
32712  
32713 +#ifndef __KERNEL__
32714 +#error This is a kernel header. Perhaps include nftl-user.h instead?
32715 +#endif
32716 +
32717  #include <linux/mtd/blktrans.h>
32718  #include <linux/mtd/mtd.h>
32719  #include <linux/mtd/nftl.h>
32720  
32721 -#define        OSAK_VERSION    0x5120
32722 -#define        PERCENTUSED     98
32723 -
32724 -#define        SECTORSIZE      512
32725 +#include <mtd/inftl-user.h>
32726  
32727  #ifndef INFTL_MAJOR
32728 -#define INFTL_MAJOR 93 /* FIXME */
32729 +#define INFTL_MAJOR 94
32730  #endif
32731  #define INFTL_PARTN_BITS 4
32732  
32733 -/* Block Control Information */
32734 -
32735 -struct inftl_bci {
32736 -       __u8 ECCsig[6];
32737 -       __u8 Status;
32738 -       __u8 Status1;
32739 -} __attribute__((packed));
32740 -
32741 -struct inftl_unithead1 {
32742 -       __u16 virtualUnitNo;
32743 -       __u16 prevUnitNo;
32744 -       __u8 ANAC;
32745 -       __u8 NACs;
32746 -       __u8 parityPerField;
32747 -       __u8 discarded;
32748 -} __attribute__((packed));
32749 -
32750 -struct inftl_unithead2 {
32751 -       __u8 parityPerField;
32752 -       __u8 ANAC;
32753 -       __u16 prevUnitNo;
32754 -       __u16 virtualUnitNo;
32755 -       __u8 NACs;
32756 -       __u8 discarded;
32757 -} __attribute__((packed));
32758 -
32759 -struct inftl_unittail {
32760 -       __u8 Reserved[4];
32761 -       __u16 EraseMark;
32762 -       __u16 EraseMark1;
32763 -} __attribute__((packed));
32764 -
32765 -union inftl_uci {
32766 -       struct inftl_unithead1 a;
32767 -       struct inftl_unithead2 b;
32768 -       struct inftl_unittail c;
32769 -};
32770 -
32771 -struct inftl_oob {
32772 -       struct inftl_bci b;
32773 -       union inftl_uci u;
32774 -};
32775 -
32776 -
32777 -/* INFTL Media Header */
32778 -
32779 -struct INFTLPartition {
32780 -       __u32 virtualUnits;
32781 -       __u32 firstUnit;
32782 -       __u32 lastUnit;
32783 -       __u32 flags;
32784 -       __u32 spareUnits;
32785 -       __u32 Reserved0;
32786 -       __u32 Reserved1;
32787 -} __attribute__((packed));
32788 -
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));
32800 -
32801 -/* Partition flag types */
32802 -#define        INFTL_BINARY    0x20000000
32803 -#define        INFTL_BDTL      0x40000000
32804 -#define        INFTL_LAST      0x80000000
32805 -
32806 -
32807  #ifdef __KERNEL__
32808  
32809  struct INFTLrecord {
32810         struct mtd_blktrans_dev mbd;
32811 -       __u16 MediaUnit, SpareMediaUnit;
32812 +       __u16 MediaUnit;
32813         __u32 EraseSize;
32814         struct INFTLMediaHeader MediaHdr;
32815         int usecount;
32816 @@ -119,6 +46,7 @@
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;
32821  };
32822  
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
32828 @@ -1,6 +1,6 @@
32829  
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 $ */
32833  
32834  #ifndef __LINUX_MTD_MAP_H__
32835  #define __LINUX_MTD_MAP_H__
32836 @@ -8,17 +8,164 @@
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>
32845 +
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
32852 +#else
32853 +#define map_bankwidth_is_1(map) (0)
32854 +#endif
32855 +
32856 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
32857 +# ifdef map_bankwidth
32858 +#  undef map_bankwidth
32859 +#  define map_bankwidth(map) ((map)->bankwidth)
32860 +# else
32861 +#  define map_bankwidth(map) 2
32862 +#  define map_bankwidth_is_large(map) (0)
32863 +#  define map_words(map) (1)
32864 +# endif
32865 +#define map_bankwidth_is_2(map) (map_bankwidth(map) == 2)
32866 +#undef MAX_MAP_BANKWIDTH
32867 +#define MAX_MAP_BANKWIDTH 2
32868 +#else
32869 +#define map_bankwidth_is_2(map) (0)
32870 +#endif
32871 +
32872 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
32873 +# ifdef map_bankwidth
32874 +#  undef map_bankwidth
32875 +#  define map_bankwidth(map) ((map)->bankwidth)
32876 +# else
32877 +#  define map_bankwidth(map) 4
32878 +#  define map_bankwidth_is_large(map) (0)
32879 +#  define map_words(map) (1)
32880 +# endif
32881 +#define map_bankwidth_is_4(map) (map_bankwidth(map) == 4)
32882 +#undef MAX_MAP_BANKWIDTH
32883 +#define MAX_MAP_BANKWIDTH 4
32884 +#else
32885 +#define map_bankwidth_is_4(map) (0)
32886 +#endif
32887 +
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)
32895 +#   undef map_words
32896 +#   define map_words(map) (map_bankwidth(map) / sizeof(unsigned long))
32897 +#  endif
32898 +# else
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))
32902 +# endif
32903 +#define map_bankwidth_is_8(map) (map_bankwidth(map) == 8)
32904 +#undef MAX_MAP_BANKWIDTH
32905 +#define MAX_MAP_BANKWIDTH 8
32906 +#else
32907 +#define map_bankwidth_is_8(map) (0)
32908 +#endif
32909 +
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)
32916 +#  undef map_words
32917 +#  define map_words(map) (map_bankwidth(map) / sizeof(unsigned long))
32918 +# else
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))
32922 +# endif
32923 +#define map_bankwidth_is_16(map) (map_bankwidth(map) == 16)
32924 +#undef MAX_MAP_BANKWIDTH
32925 +#define MAX_MAP_BANKWIDTH 16
32926 +#else
32927 +#define map_bankwidth_is_16(map) (0)
32928 +#endif
32929 +
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)
32936 +#  undef map_words
32937 +#  define map_words(map) (map_bankwidth(map) / sizeof(unsigned long))
32938 +# else
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))
32942 +# endif
32943 +#define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
32944 +#undef MAX_MAP_BANKWIDTH
32945 +#define MAX_MAP_BANKWIDTH 32
32946 +#else
32947 +#define map_bankwidth_is_32(map) (0)
32948 +#endif
32949 +
32950 +#ifndef map_bankwidth
32951 +#error "No bus width supported. What's the point?"
32952 +#endif
32953 +
32954 +static inline int map_bankwidth_supported(int w)
32955 +{
32956 +       switch (w) {
32957 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
32958 +       case 1:
32959 +#endif
32960 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
32961 +       case 2:
32962 +#endif
32963 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
32964 +       case 4:
32965 +#endif
32966 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
32967 +       case 8:
32968 +#endif
32969 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
32970 +       case 16:
32971 +#endif
32972 +#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
32973 +       case 32:
32974 +#endif
32975 +               return 1;
32976 +
32977 +       default:
32978 +               return 0;
32979 +       }
32980 +}
32981 +
32982 +#define MAX_MAP_LONGS ( ((MAX_MAP_BANKWIDTH*8) + BITS_PER_LONG - 1) / BITS_PER_LONG )
32983 +
32984 +typedef union {
32985 +       unsigned long x[MAX_MAP_LONGS];
32986 +} map_word;
32987  
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 
32995 -   it.
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
33002 +   use; whatever.
33003     
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)
33009  
33010 -       unsigned long virt;
33011 +       void __iomem *virt;
33012         void *cached;
33013  
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.
33018 +                     */
33019  
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.
33026 -        * It doesn't.
33027 -        * I won't.
33028 -        * dwmw2 */
33029 -       
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);
33036 +
33037 +       void (*write)(struct map_info *, const map_word, unsigned long);
33038         void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
33039  
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. */
33042  #endif
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);
33050 +
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)
33057  
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)
33071  
33072 -extern void simple_map_init(struct map_info *);
33073 -#define map_is_linear(map) (map->phys != NO_XIP)
33074  
33075 -#else
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)
33078  {
33079 -       return __raw_readb(map->virt + ofs);
33080 +       int i;
33081 +       for (i=0; i<map_words(map); i++) {
33082 +               if (val1.x[i] != val2.x[i])
33083 +                       return 0;
33084 +       }
33085 +       return 1;
33086  }
33087  
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)
33090  {
33091 -       return __raw_readw(map->virt + ofs);
33092 +       map_word r;
33093 +       int i;
33094 +
33095 +       for (i=0; i<map_words(map); i++) {
33096 +               r.x[i] = val1.x[i] & val2.x[i];
33097 +       }
33098 +       return r;
33099  }
33100  
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)
33103  {
33104 -       return __raw_readl(map->virt + ofs);
33105 +       map_word r;
33106 +       int i;
33107 +
33108 +       for (i=0; i<map_words(map); i++) {
33109 +               r.x[i] = val1.x[i] | val2.x[i];
33110 +       }
33111 +       return r;
33112  }
33113 +#define map_word_andequal(m, a, b, z) map_word_equal(m, z, map_word_and(m, a, b))
33114  
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)
33117  {
33118 -#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */
33119 -       BUG();
33120 +       int i;
33121 +
33122 +       for (i=0; i<map_words(map); i++) {
33123 +               if (val1.x[i] & val2.x[i])
33124 +                       return 1;
33125 +       }
33126         return 0;
33127 -#else
33128 -       return __raw_readll(map->virt + ofs);
33129 -#endif
33130  }
33131  
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)
33134  {
33135 -       __raw_writeb(datum, map->virt + ofs);
33136 -       mb();
33137 +       map_word r;
33138 +
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);
33148 +#endif
33149 +       else if (map_bankwidth_is_large(map))
33150 +               memcpy(r.x, ptr, map->bankwidth);
33151 +
33152 +       return r;
33153  }
33154  
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)
33157  {
33158 -       __raw_writew(datum, map->virt + ofs);
33159 -       mb();
33160 +       int i;
33161 +
33162 +       if (map_bankwidth_is_large(map)) {
33163 +               char *dest = (char *)&orig;
33164 +               memcpy(dest+start, buf, len);
33165 +       } else {
33166 +               for (i=start; i < start+len; i++) {
33167 +                       int bitpos;
33168 +#ifdef __LITTLE_ENDIAN
33169 +                       bitpos = i*8;
33170 +#else /* __BIG_ENDIAN */
33171 +                       bitpos = (map_bankwidth(map)-1-i)*8;
33172 +#endif
33173 +                       orig.x[0] &= ~(0xff << bitpos);
33174 +                       orig.x[0] |= buf[i] << bitpos;
33175 +               }
33176 +       }
33177 +       return orig;
33178  }
33179  
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)
33182  {
33183 -       __raw_writel(datum, map->virt + ofs);
33184 -       mb();
33185 +       map_word r;
33186 +       int i;
33187 +
33188 +       for (i=0; i<map_words(map); i++) {
33189 +               r.x[i] = ~0UL;
33190 +       }
33191 +       return r;
33192 +}
33193 +static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
33194 +{
33195 +       map_word r;
33196 +
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);
33206 +#endif
33207 +       else if (map_bankwidth_is_large(map))
33208 +               memcpy_fromio(r.x, map->virt+ofs, map->bankwidth);
33209 +
33210 +       return r;
33211  }
33212  
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)
33215  {
33216 -#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */
33217 -       BUG();
33218 -#else
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);
33229 +#endif
33230 +       else if (map_bankwidth_is_large(map))
33231 +               memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
33232         mb();
33233 -#endif /* CFI_B8 */
33234  }
33235  
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)
33238  {
33239 -       memcpy_fromio(to, map->virt + from, len);
33240 +       if (map->cached)
33241 +               memcpy(to, (char *)map->cached + from, len);
33242 +       else
33243 +               memcpy_fromio(to, map->virt + from, len);
33244  }
33245  
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)
33248  {
33249         memcpy_toio(map->virt + to, from, len);
33250  }
33251  
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)
33258 +
33259 +extern void simple_map_init(struct map_info *);
33260 +#define map_is_linear(map) (map->phys != NO_XIP)
33261 +
33262 +#else
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)
33267 +
33268 +
33269 +#define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
33270  #define map_is_linear(map) (1)
33271  
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
33277 @@ -1,10 +1,17 @@
33278 -
33279 -/* $Id: mtd.h,v 1.45 2003/05/20 21:56:40 dwmw2 Exp $ */
33280 +/* 
33281 + * $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $
33282 + *
33283 + * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
33284 + *
33285 + * Released under GPL
33286 + */
33287  
33288  #ifndef __MTD_MTD_H__
33289  #define __MTD_MTD_H__
33290  
33291 -#ifdef __KERNEL__
33292 +#ifndef __KERNEL__
33293 +#error This is a kernel header. Perhaps include mtd-user.h instead?
33294 +#endif
33295  
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>
33301  
33302 -#endif /* __KERNEL__ */
33303 -
33304 -struct erase_info_user {
33305 -       u_int32_t start;
33306 -       u_int32_t length;
33307 -};
33308 -
33309 -struct mtd_oob_buf {
33310 -       u_int32_t start;
33311 -       u_int32_t length;
33312 -       unsigned char *ptr;
33313 -};
33314 +#include <linux/mtd/compatmac.h>
33315 +#include <mtd/mtd-abi.h>
33316  
33317  #define MTD_CHAR_MAJOR 90
33318  #define MTD_BLOCK_MAJOR 31
33319  #define MAX_MTD_DEVICES 16
33320  
33321 -
33322 -
33323 -#define MTD_ABSENT             0
33324 -#define MTD_RAM                        1
33325 -#define MTD_ROM                        2
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
33331 -
33332 -
33333 -
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
33342 -
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)
33349 -
33350 -
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
33355 -
33356 -struct mtd_info_user {
33357 -       u_char type;
33358 -       u_int32_t flags;
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;
33365 -};
33366 -
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;
33373 -};
33374 -
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)
33384 -
33385 -struct nand_oobinfo {
33386 -       int     useecc;
33387 -       int     eccpos[6];      
33388 -};
33389 -
33390 -
33391 -#ifndef __KERNEL__
33392 -
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;
33397 -
33398 -       /* User-space ioctl definitions */
33399 -
33400 -#else /* __KERNEL__ */
33401 -
33402 -
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
33408  
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;
33414         u_int32_t addr;
33415         u_int32_t len;
33416 +       u_int32_t fail_addr;
33417         u_long time;
33418         u_long retries;
33419         u_int dev;
33420 @@ -150,6 +69,7 @@
33421  
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 
33425         u_int32_t ecctype;
33426         u_int32_t eccsize;
33427         
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);
33431  
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.
33437         */
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);
33448  
33449         /* Sync */
33450 @@ -222,9 +142,10 @@
33451         /* Power Management functions */
33452         int (*suspend) (struct mtd_info *mtd);
33453         void (*resume) (struct mtd_info *mtd);
33454 -       
33455 -       /* Semaphore */
33456 -       struct semaphore mutex;
33457 +
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);
33461  
33462         void *priv;
33463  
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);
33467  
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);
33471  
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);
33475  
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) 
33480  
33481 +
33482 +#ifdef CONFIG_MTD_PARTITIONS
33483 +void mtd_erase_callback(struct erase_info *instr);
33484 +#else
33485 +static inline void mtd_erase_callback(struct erase_info *instr)
33486 +{
33487 +       if (instr->callback)
33488 +               instr->callback(instr);
33489 +}
33490 +#endif
33491 +
33492  /*
33493   * Debugging macro and defines
33494   */
33495 @@ -291,6 +223,4 @@
33496  
33497  #endif /* CONFIG_MTD_DEBUG */
33498  
33499 -#endif /* __KERNEL__ */
33500 -
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
33506 @@ -5,7 +5,7 @@
33507   *                     Steven J. Hill <sjhill@realitydiluted.com>
33508   *                    Thomas Gleixner <tglx@linutronix.de>
33509   *
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 $
33512   *
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
33515 @@ -44,6 +44,10 @@
33516   *                     NAND_YAFFS_OOB
33517   *  11-25-2002 tglx    Added Manufacturer code FUJITSU, NATIONAL
33518   *                     Split manufacturer and device ID structures 
33519 + *
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
33523   */
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>
33531  
33532  struct mtd_info;
33533 -/*
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);
33539 +
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);
33542 +
33543 +
33544 +/* The maximum number of NAND chips in an array */
33545 +#define NAND_MAX_CHIPS         8
33546 +
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.
33550   */
33551 -extern int nand_scan (struct mtd_info *mtd);
33552 +#define NAND_MAX_OOBSIZE       64
33553  
33554  /*
33555   * Constants for hardware specific CLE/ALE/NCE function
33556  */
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
33573  
33574  /*
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
33585  
33586 +/* Extended commands for large page devices */
33587 +#define NAND_CMD_READSTART     0x30
33588 +#define NAND_CMD_CACHEDPROG    0x15
33589 +
33590 +/* Status bits */
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
33596 +
33597  /* 
33598   * Constants for ECC_MODES
33599 - *
33600 - * NONE:       No ECC
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
33604 - *
33605 - *
33606 -*/
33607 + */
33608 +
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
33622  
33623  /*
33624   * Constants for Hardware ECC
33625  */
33626 +/* Reset Hardware ECC for read */
33627  #define NAND_ECC_READ          0
33628 +/* Reset Hardware ECC for write */
33629  #define NAND_ECC_WRITE         1
33630 -       
33631 +/* Enable Hardware ECC before syndrom is read back from flash */
33632 +#define NAND_ECC_READSYN       2
33633 +
33634 +/* Option constants for bizarre disfunctionality and real
33635 +*  features
33636 +*/
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 
33653 +
33654 +/* Options valid for Samsung large page devices */
33655 +#define NAND_SAMSUNG_LP_OPTIONS \
33656 +       (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
33657 +
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))
33663 +
33664 +/* Mask to zero out the chip options, which come from the id table */
33665 +#define NAND_CHIPOPTIONS_MSK   (0x0000ffff & ~NAND_NO_AUTOINCR)
33666 +
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
33675 +
33676 +
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
33682 +
33683 +
33684  /*
33685 + * nand_state_t - chip states
33686   * Enumeration for NAND flash chip state
33687   */
33688  typedef enum {
33689 @@ -113,71 +208,116 @@
33690         FL_READING,
33691         FL_WRITING,
33692         FL_ERASING,
33693 -       FL_SYNCING
33694 +       FL_SYNCING,
33695 +       FL_CACHEDPRG,
33696  } nand_state_t;
33697  
33698  
33699 -/*
33700 - * NAND Private Flash Chip Data
33701 - *
33702 - * Structure overview:
33703 - *
33704 - *  IO_ADDR_R - address to read the 8 I/O lines of the flash device 
33705 - *
33706 - *  IO_ADDR_W - address to write the 8 I/O lines of the flash device 
33707 - *
33708 - *  hwcontrol - hardwarespecific function for accesing control-lines
33709 - *
33710 - *  dev_ready - hardwarespecific function for accesing device ready/busy line
33711 - *
33712 - *  waitfunc - hardwarespecific function for wait on ready
33713 - *
33714 - *  calculate_ecc - function for ecc calculation or readback from ecc hardware
33715 - *
33716 - *  correct_data - function for ecc correction, matching to ecc generator (sw/hw)
33717 - *
33718 - *  enable_hwecc - function to enable (reset) hardware ecc generator
33719 - *
33720 - *  eccmod - mode of ecc: see constants
33721 - *
33722 - *  eccsize - databytes used per ecc-calculation
33723 - *
33724 - *  chip_delay - chip dependent delay for transfering data from array to read regs (tR)
33725 - *
33726 - *  chip_lock - spinlock used to protect access to this structure
33727 - *
33728 - *  wq - wait queue to sleep on if a NAND operation is in progress
33729 - *
33730 - *  state - give the current state of the NAND device
33731 - *
33732 - *  page_shift - number of address bits in a page (column address bits)
33733 - *
33734 - *  data_buf - data buffer passed to/from MTD user modules
33735 - *
33736 - *  data_cache - data cache for redundant page access and shadow for
33737 - *              ECC failure
33738 - *
33739 - *  cache_page - number of last valid page in page_cache 
33740 +/**
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
33793   */
33794
33795  struct nand_chip {
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;
33802 +       
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);
33807 +       
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);
33826         int             eccmode;
33827         int             eccsize;
33828 +       int             eccsteps;
33829         int             chip_delay;
33830 -       spinlock_t      chip_lock;
33831 +       spinlock_t      chip_lock;
33832         wait_queue_head_t wq;
33833         nand_state_t    state;
33834         int             page_shift;
33835 +       int             phys_erase_shift;
33836 +       int             bbt_erase_shift;
33837 +       int             chip_shift;
33838         u_char          *data_buf;
33839 +       u_char          *oob_buf;
33840 +       int             oobdirty;
33841         u_char          *data_poi;
33842 +       unsigned int    options;
33843 +       int             badblockpos;
33844 +       int             numchips;
33845 +       unsigned long   chipsize;
33846 +       int             pagemask;
33847 +       int             pagebuf;
33848 +       struct nand_oobinfo     *autooob;
33849 +       uint8_t         *bbt;
33850 +       struct nand_bbt_descr   *bbt_td;
33851 +       struct nand_bbt_descr   *bbt_md;
33852 +       void            *priv;
33853  };
33854  
33855  /*
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
33862  
33863 -/*
33864 - * NAND Flash Device ID Structure
33865 - *
33866 - * Structure overview:
33867 +/**
33868 + * struct nand_flash_dev - NAND Flash Device ID Structure
33869   *
33870 - *  name - Identify the device type
33871 - *
33872 - *  id -  device ID code
33873 - *
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.
33877 - *
33878 - *  page256 - denotes if flash device has 256 byte pages or not.
33879 - *
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.
33887 - *
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
33898   */
33899  struct nand_flash_dev {
33900 -       char * name;
33901 +       char *name;
33902         int id;
33903 -       int chipshift;
33904 +       unsigned long pagesize;
33905 +       unsigned long chipsize;
33906         unsigned long erasesize;
33907 -       char page256;
33908 +       unsigned long options;
33909  };
33910  
33911 -/*
33912 - * NAND Flash Manufacturer ID Structure
33913 - *
33914 - *  name - Manufacturer name
33915 - *
33916 - *  id - manufacturer ID code of device.
33917 +/**
33918 + * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
33919 + * @name:      Manufacturer name
33920 + * @id:        manufacturer ID code of device.
33921  */
33922  struct nand_manufacturers {
33923         int id;
33924 @@ -236,9 +365,85 @@
33925  extern struct nand_flash_dev nand_flash_ids[];
33926  extern struct nand_manufacturers nand_manuf_ids[];
33927  
33928 +/** 
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 
33940 + *             written.
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
33945 + *
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.
33950 + */
33951 +struct nand_bbt_descr {
33952 +       int     options;
33953 +       int     pages[NAND_MAX_CHIPS];
33954 +       int     offs;
33955 +       int     veroffs;
33956 +       uint8_t version[NAND_MAX_CHIPS];
33957 +       int     len;
33958 +       int     maxblocks;
33959 +       int     reserved_block_code;
33960 +       uint8_t *pattern;
33961 +};
33962 +
33963 +/* Options for the bad block table descriptors */
33964 +
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
33993 +
33994 +/* The maximum number of blocks to scan for a bbt */
33995 +#define NAND_BBT_SCAN_MAXBLOCKS        4
33996 +
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);
34002 +
34003  /*
34004  * Constants for oob configuration
34005  */
34006 -#define NAND_BADBLOCK_POS              5
34007 +#define NAND_SMALL_BADBLOCK_POS                5
34008 +#define NAND_LARGE_BADBLOCK_POS                0
34009  
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
34015 @@ -3,7 +3,7 @@
34016   *
34017   *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
34018   *
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 $
34021   *
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.
34026   */
34027  
34028 -/*
34029 - * Creates non-inverted ECC code from line parity
34030 - */
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__
34034 +
34035 +struct mtd_info;
34036  
34037  /*
34038   * Calculate 3 byte ECC code for 256 byte block
34039   */
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);
34042  
34043  /*
34044   * Detect and correct a 1 bit error for 256 byte block
34045   */
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);
34048 +
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
34054 @@ -1,5 +1,5 @@
34055  /*
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 $
34058   *
34059   * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
34060   */
34061 @@ -10,71 +10,7 @@
34062  #include <linux/mtd/mtd.h>
34063  #include <linux/mtd/blktrans.h>
34064  
34065 -/* Block Control Information */
34066 -
34067 -struct nftl_bci {
34068 -       unsigned char ECCSig[6];
34069 -       __u8 Status;
34070 -       __u8 Status1;
34071 -}__attribute__((packed));
34072 -
34073 -/* Unit Control Information */
34074 -
34075 -struct nftl_uci0 {
34076 -       __u16 VirtUnitNum;
34077 -       __u16 ReplUnitNum;
34078 -       __u16 SpareVirtUnitNum;
34079 -       __u16 SpareReplUnitNum;
34080 -} __attribute__((packed));
34081 -
34082 -struct nftl_uci1 {
34083 -       __u32 WearInfo;
34084 -       __u16 EraseMark;
34085 -       __u16 EraseMark1;
34086 -} __attribute__((packed));
34087 -
34088 -struct nftl_uci2 {
34089 -        __u16 FoldMark;
34090 -        __u16 FoldMark1;
34091 -       __u32 unused;
34092 -} __attribute__((packed));
34093 -
34094 -union nftl_uci {
34095 -       struct nftl_uci0 a;
34096 -       struct nftl_uci1 b;
34097 -       struct nftl_uci2 c;
34098 -};
34099 -
34100 -struct nftl_oob {
34101 -       struct nftl_bci b;
34102 -       union nftl_uci u;
34103 -};
34104 -
34105 -/* NFTL Media Header */
34106 -
34107 -struct NFTLMediaHeader {
34108 -       char DataOrgID[6];
34109 -       __u16 NumEraseUnits;
34110 -       __u16 FirstPhysicalEUN;
34111 -       __u32 FormattedSize;
34112 -       unsigned char UnitSizeFactor;
34113 -} __attribute__((packed));
34114 -
34115 -#define MAX_ERASE_ZONES (8192 - 512)
34116 -
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
34122 -
34123 -#define FOLD_MARK_IN_PROGRESS 0x5555
34124 -
34125 -#define ZONE_GOOD 0xff
34126 -#define ZONE_BAD_ORIGINAL 0
34127 -#define ZONE_BAD_MARKED 7
34128 -
34129 -#ifdef __KERNEL__
34130 +#include <mtd/nftl-user.h>
34131  
34132  /* these info are used in ReplUnitTable */
34133  #define BLOCK_NIL          0xffff /* last block of a chain */
34134 @@ -101,6 +37,7 @@
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;
34139  };
34140  
34141  int NFTL_mount(struct NFTLrecord *s);
34142 @@ -114,6 +51,4 @@
34143  #define MAX_SECTORS_PER_UNIT 64
34144  #define NFTL_PARTN_BITS 4
34145  
34146 -#endif /* __KERNEL__ */
34147 -
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
34153 @@ -5,7 +5,7 @@
34154   *
34155   * This code is GPL
34156   *
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 $
34159   */
34160  
34161  #ifndef MTD_PARTITIONS_H
34162 @@ -50,7 +50,7 @@
34163  #define MTDPART_SIZ_FULL       (0)
34164  
34165  
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 *);
34169  
34170  /*
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
34175 @@ -0,0 +1,61 @@
34176 +/*
34177 + * For boards with physically mapped flash and using 
34178 + * drivers/mtd/maps/physmap.c mapping driver.
34179 + *
34180 + * $Id: physmap.h,v 1.3 2004/07/21 00:16:15 jwboyer Exp $
34181 + *
34182 + * Copyright (C) 2003 MontaVista Software Inc.
34183 + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
34184 + *
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.
34189 + *
34190 + */
34191 +
34192 +#ifndef __LINUX_MTD_PHYSMAP__
34193 +
34194 +#include <linux/config.h>
34195 +
34196 +#if defined(CONFIG_MTD_PHYSMAP) 
34197 +
34198 +#include <linux/mtd/mtd.h>
34199 +#include <linux/mtd/map.h>
34200 +#include <linux/mtd/partitions.h>
34201 +
34202 +/*
34203 + * The map_info for physmap.  Board can override size, buswidth, phys,
34204 + * (*set_vpp)(), etc in their initial setup routine.
34205 + */
34206 +extern struct map_info physmap_map;
34207 +
34208 +/*
34209 + * Board needs to specify the exact mapping during their setup time.
34210 + */
34211 +static inline void physmap_configure(unsigned long addr, unsigned long size, int bankwidth, void (*set_vpp)(struct map_info *, int) )
34212 +{
34213 +       physmap_map.phys = addr;
34214 +       physmap_map.size = size;
34215 +       physmap_map.bankwidth = bankwidth;
34216 +       physmap_map.set_vpp = set_vpp;
34217 +}
34218 +
34219 +#if defined(CONFIG_MTD_PARTITIONS)
34220 +
34221 +/*
34222 + * Machines that wish to do flash partition may want to call this function in 
34223 + * their setup routine.  
34224 + *
34225 + *     physmap_set_partitions(mypartitions, num_parts);
34226 + *
34227 + * Note that one can always override this hard-coded partition with 
34228 + * command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS).
34229 + */
34230 +void physmap_set_partitions(struct mtd_partition *parts, int num_parts);
34231 +
34232 +#endif /* defined(CONFIG_MTD_PARTITIONS) */
34233 +#endif /* defined(CONFIG_MTD) */
34234 +
34235 +#endif /* __LINUX_MTD_PHYSMAP__ */
34236 +
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
34241 @@ -0,0 +1,99 @@
34242 +/* 
34243 + * include/linux/rslib.h
34244 + *
34245 + * Overview:
34246 + *   Generic Reed Solomon encoder / decoder library
34247 + *   
34248 + * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
34249 + *
34250 + * RS code lifted from reed solomon library written by Phil Karn
34251 + * Copyright 2002 Phil Karn, KA9Q
34252 + *
34253 + * $Id: rslib.h,v 1.1 2004/09/16 23:58:55 gleixner Exp $
34254 + *
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.
34258 + */
34259 +
34260 +#ifndef _RSLIB_H_
34261 +#define _RSLIB_H_
34262 +
34263 +#include <linux/list.h>
34264 +
34265 +/** 
34266 + * struct rs_contol - rs control structure
34267 + * 
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
34280 +*/
34281 +struct rs_control {
34282 +       int             mm;
34283 +       int             nn;
34284 +       uint16_t        *alpha_to;
34285 +       uint16_t        *index_of;
34286 +       uint16_t        *genpoly;
34287 +       int             nroots;
34288 +       int             fcr;
34289 +       int             prim;
34290 +       int             iprim;
34291 +       int             gfpoly;
34292 +       int             users;
34293 +       struct list_head list;
34294 +};
34295 +
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);
34300 +
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);
34305 +
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);
34310 +
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);
34313 +
34314 +/* Release a rs control structure */
34315 +void free_rs (struct rs_control *rs);
34316 +
34317 +/* Internal usage only */
34318 +static inline int modnn (struct rs_control *rs, int x)
34319 +{
34320 +       while (x >= rs->nn) {
34321 +               x -= rs->nn;
34322 +               x = (x >> rs->mm) + (x & rs->nn);
34323 +       }
34324 +       return x;
34325 +}
34326 +
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)
34337 +#define A0 (NN)
34338 +
34339 +#endif
34340 +
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
34345 @@ -0,0 +1,91 @@
34346 +/*
34347 + * $Id: inftl-user.h,v 1.1 2004/05/05 15:17:00 dwmw2 Exp $
34348 + *
34349 + * Parts of INFTL headers shared with userspace 
34350 + *
34351 + */
34352 +
34353 +#ifndef __MTD_INFTL_USER_H__
34354 +#define __MTD_INFTL_USER_H__
34355 +
34356 +#define        OSAK_VERSION    0x5120
34357 +#define        PERCENTUSED     98
34358 +
34359 +#define        SECTORSIZE      512
34360 +
34361 +/* Block Control Information */
34362 +
34363 +struct inftl_bci {
34364 +       uint8_t ECCsig[6];
34365 +       uint8_t Status;
34366 +       uint8_t Status1;
34367 +} __attribute__((packed));
34368 +
34369 +struct inftl_unithead1 {
34370 +       uint16_t virtualUnitNo;
34371 +       uint16_t prevUnitNo;
34372 +       uint8_t ANAC;
34373 +       uint8_t NACs;
34374 +       uint8_t parityPerField;
34375 +       uint8_t discarded;
34376 +} __attribute__((packed));
34377 +
34378 +struct inftl_unithead2 {
34379 +       uint8_t parityPerField;
34380 +       uint8_t ANAC;
34381 +       uint16_t prevUnitNo;
34382 +       uint16_t virtualUnitNo;
34383 +       uint8_t NACs;
34384 +       uint8_t discarded;
34385 +} __attribute__((packed));
34386 +
34387 +struct inftl_unittail {
34388 +       uint8_t Reserved[4];
34389 +       uint16_t EraseMark;
34390 +       uint16_t EraseMark1;
34391 +} __attribute__((packed));
34392 +
34393 +union inftl_uci {
34394 +       struct inftl_unithead1 a;
34395 +       struct inftl_unithead2 b;
34396 +       struct inftl_unittail c;
34397 +};
34398 +
34399 +struct inftl_oob {
34400 +       struct inftl_bci b;
34401 +       union inftl_uci u;
34402 +};
34403 +
34404 +
34405 +/* INFTL Media Header */
34406 +
34407 +struct INFTLPartition {
34408 +       __u32 virtualUnits;
34409 +       __u32 firstUnit;
34410 +       __u32 lastUnit;
34411 +       __u32 flags;
34412 +       __u32 spareUnits;
34413 +       __u32 Reserved0;
34414 +       __u32 Reserved1;
34415 +} __attribute__((packed));
34416 +
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));
34428 +
34429 +/* Partition flag types */
34430 +#define        INFTL_BINARY    0x20000000
34431 +#define        INFTL_BDTL      0x40000000
34432 +#define        INFTL_LAST      0x80000000
34433 +
34434 +#endif /* __MTD_INFTL_USER_H__ */
34435 +
34436 +
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
34441 @@ -0,0 +1,35 @@
34442 +/*
34443 + * $Id: jffs2-user.h,v 1.1 2004/05/05 11:57:54 dwmw2 Exp $
34444 + *
34445 + * JFFS2 definitions for use in user space only
34446 + */
34447 +
34448 +#ifndef __JFFS2_USER_H__
34449 +#define __JFFS2_USER_H__
34450 +
34451 +/* This file is blessed for inclusion by userspace */
34452 +#include <linux/jffs2.h>
34453 +#include <endian.h>
34454 +#include <byteswap.h>
34455 +
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
34462 +
34463 +extern int target_endian;
34464 +
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); })
34467 +
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)})
34471 +
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))
34475 +
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
34481 @@ -0,0 +1,102 @@
34482 +/*
34483 + * $Id: mtd-abi.h,v 1.6 2004/08/09 13:38:30 dwmw2 Exp $
34484 + *
34485 + * Portions of MTD ABI definition which are shared by kernel and user space 
34486 + */
34487 +
34488 +#ifndef __MTD_ABI_H__
34489 +#define __MTD_ABI_H__
34490 +
34491 +#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into
34492 +                   separate files was to avoid #ifdef __KERNEL__ */
34493 +#define __user
34494 +#endif
34495 +
34496 +struct erase_info_user {
34497 +       uint32_t start;
34498 +       uint32_t length;
34499 +};
34500 +
34501 +struct mtd_oob_buf {
34502 +       uint32_t start;
34503 +       uint32_t length;
34504 +       unsigned char __user *ptr;
34505 +};
34506 +
34507 +#define MTD_ABSENT             0
34508 +#define MTD_RAM                        1
34509 +#define MTD_ROM                        2
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
34515 +
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
34524 +
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)
34531 +
34532 +
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
34537 +
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)
34543 +
34544 +struct mtd_info_user {
34545 +       uint8_t type;
34546 +       uint32_t flags;
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;
34553 +};
34554 +
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;
34561 +};
34562 +
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)
34575 +
34576 +struct nand_oobinfo {
34577 +       uint32_t useecc;
34578 +       uint32_t eccbytes;
34579 +       uint32_t oobfree[8][2];
34580 +       uint32_t eccpos[32];
34581 +};
34582 +
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
34588 @@ -0,0 +1,20 @@
34589 +/*
34590 + * $Id: mtd-user.h,v 1.2 2004/05/05 14:44:57 dwmw2 Exp $
34591 + *
34592 + * MTD ABI header for use by user space only.
34593 + */
34594 +
34595 +#ifndef __MTD_USER_H__
34596 +#define __MTD_USER_H__
34597 +
34598 +#include <stdint.h>
34599 +
34600 +/* This file is blessed for inclusion by userspace */
34601 +#include <mtd/mtd-abi.h>
34602 +
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;
34607 +
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
34613 @@ -0,0 +1,76 @@
34614 +/*
34615 + * $Id: nftl-user.h,v 1.1 2004/05/05 14:44:57 dwmw2 Exp $
34616 + *
34617 + * Parts of NFTL headers shared with userspace 
34618 + *
34619 + */
34620 +
34621 +#ifndef __MTD_NFTL_USER_H__
34622 +#define __MTD_NFTL_USER_H__
34623 +
34624 +/* Block Control Information */
34625 +
34626 +struct nftl_bci {
34627 +       unsigned char ECCSig[6];
34628 +       uint8_t Status;
34629 +       uint8_t Status1;
34630 +}__attribute__((packed));
34631 +
34632 +/* Unit Control Information */
34633 +
34634 +struct nftl_uci0 {
34635 +       uint16_t VirtUnitNum;
34636 +       uint16_t ReplUnitNum;
34637 +       uint16_t SpareVirtUnitNum;
34638 +       uint16_t SpareReplUnitNum;
34639 +} __attribute__((packed));
34640 +
34641 +struct nftl_uci1 {
34642 +       uint32_t WearInfo;
34643 +       uint16_t EraseMark;
34644 +       uint16_t EraseMark1;
34645 +} __attribute__((packed));
34646 +
34647 +struct nftl_uci2 {
34648 +        uint16_t FoldMark;
34649 +        uint16_t FoldMark1;
34650 +       uint32_t unused;
34651 +} __attribute__((packed));
34652 +
34653 +union nftl_uci {
34654 +       struct nftl_uci0 a;
34655 +       struct nftl_uci1 b;
34656 +       struct nftl_uci2 c;
34657 +};
34658 +
34659 +struct nftl_oob {
34660 +       struct nftl_bci b;
34661 +       union nftl_uci u;
34662 +};
34663 +
34664 +/* NFTL Media Header */
34665 +
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));
34673 +
34674 +#define MAX_ERASE_ZONES (8192 - 512)
34675 +
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
34681 +
34682 +#define FOLD_MARK_IN_PROGRESS 0x5555
34683 +
34684 +#define ZONE_GOOD 0xff
34685 +#define ZONE_BAD_ORIGINAL 0
34686 +#define ZONE_BAD_MARKED 7
34687 +
34688 +
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
34694 @@ -24,5 +24,11 @@
34695  config ZLIB_DEFLATE
34696         tristate
34697  
34698 +#
34699 +# reed solomon support is select'ed if needed
34700 +#
34701 +config REED_SOLOMON
34702 +       tristate
34703 +
34704  endmenu
34705  
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
34710 @@ -0,0 +1,28 @@
34711 +#
34712 +# Library configuration
34713 +#
34714 +
34715 +menu "Library routines"
34716 +
34717 +config CRC32
34718 +       tristate "CRC32 functions"
34719 +       help
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
34723 +         require M here.
34724 +
34725 +config QSORT
34726 +       bool "Quick Sort"
34727 +
34728 +#
34729 +# compression support is select'ed if needed
34730 +#
34731 +config ZLIB_INFLATE
34732 +       tristate
34733 +
34734 +config ZLIB_DEFLATE
34735 +       tristate
34736 +
34737 +endmenu
34738 +
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
34743 @@ -23,6 +23,7 @@
34744  
34745  obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
34746  obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
34747 +obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
34748  
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
34755 @@ -0,0 +1,6 @@
34756 +#
34757 +# This is a modified version of reed solomon lib, 
34758 +#
34759 +
34760 +obj-$(CONFIG_REED_SOLOMON) += reed_solomon.o
34761 +
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
34766 @@ -0,0 +1,225 @@
34767 +/* 
34768 + * lib/reed_solomon/decode_rs.c
34769 + *
34770 + * Overview:
34771 + *   Generic Reed Solomon encoder / decoder library
34772 + *   
34773 + * Copyright 2002, Phil Karn, KA9Q
34774 + * May be used under the terms of the GNU General Public License (GPL)
34775 + *
34776 + * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
34777 + *
34778 + * $Id: decode_rs.c,v 1.1 2004/09/16 23:58:56 gleixner Exp $
34779 + *
34780 + */
34781 +
34782 +/* Generic data witdh independend code which is included by the 
34783 + * wrappers.
34784 + */
34785 +{ 
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];
34793 +       int count = 0;
34794 +       uint16_t msk = (uint16_t) rs->nn;
34795 +
34796 +       /* Check length parameter for validity */
34797 +       PAD = NN - NROOTS - len;
34798 +       if (PAD < 0 || PAD >= NN)
34799 +               return -ERANGE;
34800 +               
34801 +       /* The caller does not provide the syndrome */
34802 +       if (s == NULL) {
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;
34806 +
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;
34811 +                               } else {
34812 +                                       syn[i] = ((((uint16_t) data[j]) ^ invmsk) & msk) ^ ALPHA_TO[MODNN(INDEX_OF[syn[i]] + (FCR+i)*PRIM)];
34813 +                               }
34814 +                       }
34815 +               }
34816 +
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;
34821 +                               } else {
34822 +                                       syn[i] = (((uint16_t) par[j]) & msk) ^ ALPHA_TO[MODNN(INDEX_OF[syn[i]] + (FCR+i)*PRIM)];
34823 +                               }
34824 +                       }
34825 +               }
34826 +               s = syn;
34827 +       }
34828 +
34829 +       /* Convert syndromes to index form, checking for nonzero condition */
34830 +       syn_error = 0;
34831 +       for (i = 0; i < NROOTS; i++) {
34832 +               syn_error |= s[i];
34833 +               s[i] = INDEX_OF[s[i]];
34834 +       }
34835 +
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
34839 +                */
34840 +               count = 0;
34841 +               goto finish;
34842 +       }
34843 +       memset (&lambda[1], 0, NROOTS * sizeof (lambda[0]));
34844 +       lambda[0] = 1;
34845 +
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]];
34853 +                               if (tmp != A0)
34854 +                                       lambda[j] ^= ALPHA_TO[MODNN (u + tmp)];
34855 +                       }
34856 +               }
34857 +       }
34858 +
34859 +       for (i = 0; i < NROOTS + 1; i++)
34860 +               b[i] = INDEX_OF[lambda[i]];
34861 +
34862 +       /*
34863 +        * Begin Berlekamp-Massey algorithm to determine error+erasure
34864 +        * locator polynomial
34865 +        */
34866 +       r = no_eras;
34867 +       el = no_eras;
34868 +       while (++r <= NROOTS) { /* r is the step number */
34869 +               /* Compute discrepancy at the r-th step in poly-form */
34870 +               discr_r = 0;
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])];
34874 +                       }
34875 +               }
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]));
34880 +                       b[0] = A0;
34881 +               } else {
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++) {
34885 +                               if (b[i] != A0)
34886 +                                       t[i + 1] = lambda[i + 1] ^ ALPHA_TO[MODNN (discr_r + b[i])];
34887 +                               else
34888 +                                       t[i + 1] = lambda[i + 1];
34889 +                       }
34890 +                       if (2 * el <= r + no_eras - 1) {
34891 +                               el = r + no_eras - el;
34892 +                               /*
34893 +                                * 2 lines below: B(x) <-- inv(discr_r) *
34894 +                                * lambda(x)
34895 +                                */
34896 +                               for (i = 0; i <= NROOTS; i++)
34897 +                                       b[i] = (lambda[i] == 0) ? A0 : MODNN (INDEX_OF[lambda[i]] - discr_r + NN);
34898 +                       } else {
34899 +                               /* 2 lines below: B(x) <-- x*B(x) */
34900 +                               memmove (&b[1], b, NROOTS * sizeof (b[0]));
34901 +                               b[0] = A0;
34902 +                       }
34903 +                       memcpy (lambda, t, (NROOTS + 1) * sizeof (t[0]));
34904 +               }
34905 +       }
34906 +
34907 +       /* Convert lambda to index form and compute deg(lambda(x)) */
34908 +       deg_lambda = 0;
34909 +       for (i = 0; i < NROOTS + 1; i++) {
34910 +               lambda[i] = INDEX_OF[lambda[i]];
34911 +               if (lambda[i] != A0)
34912 +                       deg_lambda = i;
34913 +       }
34914 +       /* Find roots of the error+erasure locator polynomial by Chien search */
34915 +       memcpy (&reg[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]];
34923 +                       }
34924 +               }
34925 +               if (q != 0)
34926 +                       continue;       /* Not a root */
34927 +               /* store root (index-form) and error location number */
34928 +               root[count] = i;
34929 +               loc[count] = k;
34930 +               /* If we've already found max possible roots,
34931 +                * abort the search to save time
34932 +                */
34933 +               if (++count == deg_lambda)
34934 +                       break;
34935 +       }
34936 +       if (deg_lambda != count) {
34937 +               /*
34938 +                * deg(lambda) unequal to number of roots => uncorrectable
34939 +                * error detected
34940 +                */
34941 +               count = -1;
34942 +               goto finish;
34943 +       }
34944 +       /*
34945 +        * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
34946 +        * x**NROOTS). in index form. Also find deg(omega).
34947 +        */
34948 +       deg_omega = deg_lambda - 1;
34949 +       for (i = 0; i <= deg_omega; i++) {
34950 +               tmp = 0;
34951 +               for (j = i; j >= 0; j--) {
34952 +                       if ((s[i - j] != A0) && (lambda[j] != A0))
34953 +                               tmp ^=
34954 +                                   ALPHA_TO[MODNN (s[i - j] + lambda[j])];
34955 +               }
34956 +               omega[i] = INDEX_OF[tmp];
34957 +       }
34958 +
34959 +       /*
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
34962 +        */
34963 +       for (j = count - 1; j >= 0; j--) {
34964 +               num1 = 0;
34965 +               for (i = deg_omega; i >= 0; i--) {
34966 +                       if (omega[i] != A0)
34967 +                               num1 ^= ALPHA_TO[MODNN (omega[i] + i * root[j])];
34968 +               }
34969 +               num2 = ALPHA_TO[MODNN (root[j] * (FCR - 1) + NN)];
34970 +               den = 0;
34971 +
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])];
34976 +               }
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;
34981 +               }
34982 +       }
34983 +
34984 +finish:
34985 +       if (eras_pos != NULL) {
34986 +               for (i = 0; i < count; i++)
34987 +                       eras_pos[i] = loc[i] - PAD;
34988 +       }
34989 +       return count;
34990 +
34991 +}
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
34996 @@ -0,0 +1,47 @@
34997 +/* 
34998 + * lib/reed_solomon/encode_rs.c
34999 + *
35000 + * Overview:
35001 + *   Generic Reed Solomon encoder / decoder library
35002 + *   
35003 + * Copyright 2002, Phil Karn, KA9Q
35004 + * May be used under the terms of the GNU General Public License (GPL)
35005 + *
35006 + * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
35007 + *
35008 + * $Id: encode_rs.c,v 1.1 2004/09/16 23:58:56 gleixner Exp $
35009 + *
35010 + */
35011 +
35012 +/* Generic data witdh independend code which is included by the 
35013 + * wrappers.
35014 + * int encode_rsX (struct rs_control *rs, uintX_t *data, int len, uintY_t *par)
35015 + */
35016 +{
35017 +       int i, j, pad;
35018 +       uint16_t feedback;
35019 +       uint16_t msk = (uint16_t) NN;
35020 +
35021 +       /* Check length parameter for validity */
35022 +       pad = NN - NROOTS - len;
35023 +       if (pad < 0 || pad >= NN)
35024 +               return -ERANGE;
35025 +
35026 +       memset (par, 0, NROOTS * sizeof (uint16_t));
35027 +
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])];
35034 +               }
35035 +               /* Shift */
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])];
35039 +               else
35040 +                       par[NROOTS - 1] = 0;
35041 +       }
35042 +       return 0;
35043 +}
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
35048 @@ -0,0 +1,366 @@
35049 +/* 
35050 + * lib/reed_solomon/lib_rs.c
35051 + *
35052 + * Overview:
35053 + *   Generic Reed Solomon encoder / decoder library
35054 + *   
35055 + * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
35056 + *
35057 + * Reed Solomon code lifted from reed solomon library written by Phil Karn
35058 + * Copyright 2002 Phil Karn, KA9Q
35059 + *
35060 + * $Id: rslib.c,v 1.1 2004/09/16 23:58:56 gleixner Exp $
35061 + *
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.
35065 + *
35066 + * Description:
35067 + *     
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
35078 + * on exit.
35079 + * The encoding puts the calculated syndrome into a given syndrom 
35080 + * buffer. 
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.
35086 + *
35087 + */
35088 +
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>
35096 +
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);
35101 +
35102 +/** 
35103 + * rs_init - Initialize a Reed-Solomon codec
35104 + *
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)
35110 + *
35111 + * Allocate a control structure and the polynom arrays for faster
35112 + * en/decoding. Fill the arrays according to the given parameters
35113 + */
35114 +static struct rs_control *rs_init (int symsize, int gfpoly, int fcr, int prim, int nroots)
35115 +{
35116 +       struct rs_control *rs;
35117 +       int i, j, sr, root, iprim;
35118 +
35119 +       /* Allocate the control structure */
35120 +       rs = (struct rs_control *) kmalloc (sizeof (struct rs_control), GFP_KERNEL);
35121 +       if (rs == NULL)
35122 +               return NULL;
35123 +
35124 +       INIT_LIST_HEAD(&rs->list);
35125 +
35126 +       rs->mm = symsize;
35127 +       rs->nn = (1 << symsize) - 1;
35128 +       rs->fcr = fcr;
35129 +       rs->prim = prim;
35130 +       rs->nroots = nroots;
35131 +       rs->gfpoly = gfpoly;
35132 +
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)
35136 +               goto errrs;
35137 +
35138 +       rs->index_of = (uint16_t *) kmalloc (sizeof (uint16_t) * (rs->nn + 1), GFP_KERNEL);
35139 +       if (rs->index_of == NULL)
35140 +               goto erralp;
35141 +
35142 +       rs->genpoly = (uint16_t *) kmalloc (sizeof (uint16_t) * (rs->nroots + 1), GFP_KERNEL);
35143 +       if (rs->genpoly == NULL)
35144 +               goto erridx;
35145 +
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 */
35149 +       sr = 1;
35150 +       for (i = 0; i < rs->nn; i++) {
35151 +               rs->index_of[sr] = i;
35152 +               rs->alpha_to[i] = sr;
35153 +               sr <<= 1;
35154 +               if (sr & (1 << symsize))
35155 +                       sr ^= gfpoly;
35156 +               sr &= rs->nn;
35157 +       }
35158 +       /* If it's not primitive, exit */
35159 +       if (sr != 1)
35160 +               goto errpol;
35161 +
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;
35166 +
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;
35171 +
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];
35176 +                       else
35177 +                               rs->genpoly[j] = rs->genpoly[j - 1];
35178 +               }
35179 +               /* rs->genpoly[0] can never be zero */
35180 +               rs->genpoly[0] = rs->alpha_to[(rs->index_of[rs->genpoly[0]] + root) % rs->nn];
35181 +       }
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]];
35185 +       return rs;
35186 +
35187 +       /* Error exit */
35188 +errpol:
35189 +       kfree (rs->genpoly);
35190 +erridx:
35191 +       kfree (rs->index_of);
35192 +erralp:
35193 +       kfree (rs->alpha_to);
35194 +errrs:
35195 +       kfree (rs);
35196 +       return NULL;
35197 +}
35198 +
35199 +
35200 +/** 
35201 + *  free_rs - Free the rs control structure, if its not longer used
35202 + *
35203 + *  @rs:       the control structure which is not longer used by the
35204 + *             caller
35205 + */
35206 +void free_rs (struct rs_control *rs)
35207 +{
35208 +       down (&rslistlock);
35209 +       rs->users--;
35210 +       if (!rs->users) {
35211 +               list_del (&rs->list);
35212 +               kfree (rs->alpha_to);
35213 +               kfree (rs->index_of);
35214 +               kfree (rs->genpoly);
35215 +               kfree (rs);
35216 +       }
35217 +       up (&rslistlock);
35218 +}
35219 +
35220 +/** 
35221 + * init_rs - Find a matching or allocate a new rs control structure
35222 + *
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 
35228 + *             in index form
35229 + *  @prim:     primitive element to generate polynomial roots
35230 + *  @nroots:   RS code generator polynomial degree (number of roots)
35231 + */
35232 +struct rs_control *init_rs (int symsize, int gfpoly, int fcr, int prim, int nroots)
35233 +{
35234 +       struct list_head        *tmp;
35235 +       struct rs_control       *rs;
35236 +
35237 +       /* Sanity checks */
35238 +       if (symsize < 1)
35239 +               return NULL;
35240 +       if (fcr < 0 || fcr >= (1<<symsize))
35241 +               return NULL;
35242 +       if (prim <= 0 || prim >= (1<<symsize))
35243 +               return NULL;
35244 +       if (nroots < 0 || nroots >= (1<<symsize))
35245 +               return NULL;
35246 +       
35247 +       down (&rslistlock);
35248 +
35249 +#ifdef __KERNEL__      
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)
35254 +                       continue;
35255 +               if (gfpoly != rs->gfpoly)
35256 +                       continue;
35257 +               if (fcr != rs->fcr)
35258 +                       continue;       
35259 +               if (prim != rs->prim)
35260 +                       continue;       
35261 +               if (nroots != rs->nroots)
35262 +                       continue;
35263 +               /* We have a matching one already */
35264 +               rs->users++;
35265 +               goto out;
35266 +       }
35267 +#endif
35268 +
35269 +       /* Create a new one */
35270 +       rs = rs_init (symsize, gfpoly, fcr, prim, nroots);
35271 +       if (rs) {
35272 +               rs->users = 1;
35273 +               list_add (&rs->list, &rslist);
35274 +       }
35275 +out:   
35276 +       up (&rslistlock);
35277 +       return rs;
35278 +}
35279 +
35280 +/** 
35281 + *  encode_rs8 - Calculate the parity for data values (8bit data width)
35282 + *
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
35288 + *
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.
35292 + */
35293 +int encode_rs8 (struct rs_control *rs, uint8_t *data, int len, uint16_t *par, uint16_t invmsk)
35294 +{
35295 +#define RSINVMSK 0xFF
35296 +#include "encode_rs.c"
35297 +}
35298 +
35299 +/** 
35300 + *  decode_rs8 - Decode codeword (8bit data width)
35301 + *
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
35310 + *
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.
35314 + */
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)
35317 +{
35318 +#include "decode_rs.c"
35319 +}
35320 +
35321 +/**
35322 + *  encode_rs16 - Calculate the parity for data values (16bit data width)
35323 + *
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
35329 + *
35330 + *  Each field in the data array contains up to symbol size bits of valid data.
35331 + */
35332 +int encode_rs16 (struct rs_control *rs, uint16_t *data, int len, uint16_t *par, uint16_t invmsk)
35333 +{
35334 +#undef RSINVMSK
35335 +#define RSINVMSK 0xFFFF
35336 +#include "encode_rs.c"
35337 +}
35338 +
35339 +/** 
35340 + *  decode_rs16 - Decode codeword (16bit data width)
35341 + *
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
35350 + *
35351 + *  Each field in the data array contains up to symbol size bits of valid data.
35352 + */
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)
35355 +{
35356 +#include "decode_rs.c"
35357 +}
35358 +
35359 +/** 
35360 + *  encode_rs32 - Calculate the parity for data values (32bit data width)
35361 + *
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
35367 + *
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.
35372 + */
35373 +int encode_rs32 (struct rs_control *rs, uint32_t *data, int len, uint16_t *par, uint16_t invmsk)
35374 +{
35375 +#include "encode_rs.c"
35376 +}
35377 +
35378 +/** 
35379 + *  decode_rs32 - Decode codeword (32bit data width)
35380 + *
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
35389 + *
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.
35396 + */
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)
35399 +{
35400 +#include "decode_rs.c"
35401 +}
35402 +
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);
35411 +
35412 +MODULE_LICENSE("GPL");
35413 +MODULE_DESCRIPTION("Reed Solomon encoder/decoder");
35414 +MODULE_AUTHOR("Phil Karn, Thomas Gleixner");