aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/Kconfig28
-rw-r--r--drivers/mtd/nand/Makefile3
-rw-r--r--drivers/mtd/nand/atmel_nand.c (renamed from drivers/mtd/nand/at91_nand.c)278
-rw-r--r--drivers/mtd/nand/atmel_nand_ecc.h36
-rw-r--r--drivers/mtd/nand/au1550nd.c4
-rw-r--r--drivers/mtd/nand/autcpu12.c2
-rw-r--r--drivers/mtd/nand/cafe_nand.c6
-rw-r--r--drivers/mtd/nand/diskonchip.c4
-rw-r--r--drivers/mtd/nand/edb7312.c2
-rw-r--r--drivers/mtd/nand/excite_nandflash.c2
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c63
-rw-r--r--drivers/mtd/nand/h1910.c2
-rw-r--r--drivers/mtd/nand/nand_base.c87
-rw-r--r--drivers/mtd/nand/nand_bbt.c2
-rw-r--r--drivers/mtd/nand/nand_ecc.c2
-rw-r--r--drivers/mtd/nand/nand_ids.c2
-rw-r--r--drivers/mtd/nand/nandsim.c41
-rw-r--r--drivers/mtd/nand/ppchameleonevb.c2
-rw-r--r--drivers/mtd/nand/rtc_from4.c2
-rw-r--r--drivers/mtd/nand/s3c2410.c168
-rw-r--r--drivers/mtd/nand/sharpsl.c2
-rw-r--r--drivers/mtd/nand/spia.c2
-rw-r--r--drivers/mtd/nand/toto.c2
-rw-r--r--drivers/mtd/nand/ts7250.c2
24 files changed, 512 insertions, 232 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 5076faf9ca66..71406e517857 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,5 +1,4 @@
1# drivers/mtd/nand/Kconfig 1# drivers/mtd/nand/Kconfig
2# $Id: Kconfig,v 1.35 2005/11/07 11:14:30 gleixner Exp $
3 2
4menuconfig MTD_NAND 3menuconfig MTD_NAND
5 tristate "NAND Device Support" 4 tristate "NAND Device Support"
@@ -272,22 +271,23 @@ config MTD_NAND_CS553X
272 271
273 If you say "m", the module will be called "cs553x_nand.ko". 272 If you say "m", the module will be called "cs553x_nand.ko".
274 273
275config MTD_NAND_AT91 274config MTD_NAND_ATMEL
276 bool "Support for NAND Flash / SmartMedia on AT91" 275 tristate "Support for NAND Flash / SmartMedia on AT91 and AVR32"
277 depends on ARCH_AT91 276 depends on ARCH_AT91 || AVR32
278 help 277 help
279 Enables support for NAND Flash / Smart Media Card interface 278 Enables support for NAND Flash / Smart Media Card interface
280 on Atmel AT91 processors. 279 on Atmel AT91 and AVR32 processors.
281choice 280choice
282 prompt "ECC management for NAND Flash / SmartMedia on AT91" 281 prompt "ECC management for NAND Flash / SmartMedia on AT91 / AVR32"
283 depends on MTD_NAND_AT91 282 depends on MTD_NAND_ATMEL
284 283
285config MTD_NAND_AT91_ECC_HW 284config MTD_NAND_ATMEL_ECC_HW
286 bool "Hardware ECC" 285 bool "Hardware ECC"
287 depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260 286 depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260 || AVR32
288 help 287 help
289 Uses hardware ECC provided by the at91sam9260/at91sam9263 chip 288 Use hardware ECC instead of software ECC when the chip
290 instead of software ECC. 289 supports it.
290
291 The hardware ECC controller is capable of single bit error 291 The hardware ECC controller is capable of single bit error
292 correction and 2-bit random detection per page. 292 correction and 2-bit random detection per page.
293 293
@@ -297,16 +297,16 @@ config MTD_NAND_AT91_ECC_HW
297 297
298 If unsure, say Y 298 If unsure, say Y
299 299
300config MTD_NAND_AT91_ECC_SOFT 300config MTD_NAND_ATMEL_ECC_SOFT
301 bool "Software ECC" 301 bool "Software ECC"
302 help 302 help
303 Uses software ECC. 303 Use software ECC.
304 304
305 NB : hardware and software ECC schemes are incompatible. 305 NB : hardware and software ECC schemes are incompatible.
306 If you switch from one to another, you'll have to erase your 306 If you switch from one to another, you'll have to erase your
307 mtd partition. 307 mtd partition.
308 308
309config MTD_NAND_AT91_ECC_NONE 309config MTD_NAND_ATMEL_ECC_NONE
310 bool "No ECC (testing only, DANGEROUS)" 310 bool "No ECC (testing only, DANGEROUS)"
311 depends on DEBUG_KERNEL 311 depends on DEBUG_KERNEL
312 help 312 help
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index a6e74a46992a..d772581de573 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -1,7 +1,6 @@
1# 1#
2# linux/drivers/nand/Makefile 2# linux/drivers/nand/Makefile
3# 3#
4# $Id: Makefile.common,v 1.15 2004/11/26 12:28:22 dedekind Exp $
5 4
6obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o 5obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o
7obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o 6obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
@@ -24,7 +23,7 @@ obj-$(CONFIG_MTD_NAND_TS7250) += ts7250.o
24obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o 23obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
25obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o 24obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
26obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o 25obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
27obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o 26obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o
28obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o 27obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
29obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o 28obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
30obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o 29obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/atmel_nand.c
index 0adb287027a2..99aec46e2145 100644
--- a/drivers/mtd/nand/at91_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -1,6 +1,4 @@
1/* 1/*
2 * drivers/mtd/nand/at91_nand.c
3 *
4 * Copyright (C) 2003 Rick Bronson 2 * Copyright (C) 2003 Rick Bronson
5 * 3 *
6 * Derived from drivers/mtd/nand/autcpu12.c 4 * Derived from drivers/mtd/nand/autcpu12.c
@@ -31,20 +29,19 @@
31#include <linux/mtd/nand.h> 29#include <linux/mtd/nand.h>
32#include <linux/mtd/partitions.h> 30#include <linux/mtd/partitions.h>
33 31
34#include <asm/io.h> 32#include <linux/gpio.h>
35#include <asm/sizes.h> 33#include <linux/io.h>
36 34
37#include <asm/hardware.h>
38#include <asm/arch/board.h> 35#include <asm/arch/board.h>
39#include <asm/arch/gpio.h> 36#include <asm/arch/cpu.h>
40 37
41#ifdef CONFIG_MTD_NAND_AT91_ECC_HW 38#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
42#define hard_ecc 1 39#define hard_ecc 1
43#else 40#else
44#define hard_ecc 0 41#define hard_ecc 0
45#endif 42#endif
46 43
47#ifdef CONFIG_MTD_NAND_AT91_ECC_NONE 44#ifdef CONFIG_MTD_NAND_ATMEL_ECC_NONE
48#define no_ecc 1 45#define no_ecc 1
49#else 46#else
50#define no_ecc 0 47#define no_ecc 0
@@ -52,18 +49,18 @@
52 49
53/* Register access macros */ 50/* Register access macros */
54#define ecc_readl(add, reg) \ 51#define ecc_readl(add, reg) \
55 __raw_readl(add + AT91_ECC_##reg) 52 __raw_readl(add + ATMEL_ECC_##reg)
56#define ecc_writel(add, reg, value) \ 53#define ecc_writel(add, reg, value) \
57 __raw_writel((value), add + AT91_ECC_##reg) 54 __raw_writel((value), add + ATMEL_ECC_##reg)
58 55
59#include <asm/arch/at91_ecc.h> /* AT91SAM9260/3 ECC registers */ 56#include "atmel_nand_ecc.h" /* Hardware ECC registers */
60 57
61/* oob layout for large page size 58/* oob layout for large page size
62 * bad block info is on bytes 0 and 1 59 * bad block info is on bytes 0 and 1
63 * the bytes have to be consecutives to avoid 60 * the bytes have to be consecutives to avoid
64 * several NAND_CMD_RNDOUT during read 61 * several NAND_CMD_RNDOUT during read
65 */ 62 */
66static struct nand_ecclayout at91_oobinfo_large = { 63static struct nand_ecclayout atmel_oobinfo_large = {
67 .eccbytes = 4, 64 .eccbytes = 4,
68 .eccpos = {60, 61, 62, 63}, 65 .eccpos = {60, 61, 62, 63},
69 .oobfree = { 66 .oobfree = {
@@ -76,7 +73,7 @@ static struct nand_ecclayout at91_oobinfo_large = {
76 * the bytes have to be consecutives to avoid 73 * the bytes have to be consecutives to avoid
77 * several NAND_CMD_RNDOUT during read 74 * several NAND_CMD_RNDOUT during read
78 */ 75 */
79static struct nand_ecclayout at91_oobinfo_small = { 76static struct nand_ecclayout atmel_oobinfo_small = {
80 .eccbytes = 4, 77 .eccbytes = 4,
81 .eccpos = {0, 1, 2, 3}, 78 .eccpos = {0, 1, 2, 3},
82 .oobfree = { 79 .oobfree = {
@@ -84,11 +81,11 @@ static struct nand_ecclayout at91_oobinfo_small = {
84 }, 81 },
85}; 82};
86 83
87struct at91_nand_host { 84struct atmel_nand_host {
88 struct nand_chip nand_chip; 85 struct nand_chip nand_chip;
89 struct mtd_info mtd; 86 struct mtd_info mtd;
90 void __iomem *io_base; 87 void __iomem *io_base;
91 struct at91_nand_data *board; 88 struct atmel_nand_data *board;
92 struct device *dev; 89 struct device *dev;
93 void __iomem *ecc; 90 void __iomem *ecc;
94}; 91};
@@ -96,34 +93,34 @@ struct at91_nand_host {
96/* 93/*
97 * Enable NAND. 94 * Enable NAND.
98 */ 95 */
99static void at91_nand_enable(struct at91_nand_host *host) 96static void atmel_nand_enable(struct atmel_nand_host *host)
100{ 97{
101 if (host->board->enable_pin) 98 if (host->board->enable_pin)
102 at91_set_gpio_value(host->board->enable_pin, 0); 99 gpio_set_value(host->board->enable_pin, 0);
103} 100}
104 101
105/* 102/*
106 * Disable NAND. 103 * Disable NAND.
107 */ 104 */
108static void at91_nand_disable(struct at91_nand_host *host) 105static void atmel_nand_disable(struct atmel_nand_host *host)
109{ 106{
110 if (host->board->enable_pin) 107 if (host->board->enable_pin)
111 at91_set_gpio_value(host->board->enable_pin, 1); 108 gpio_set_value(host->board->enable_pin, 1);
112} 109}
113 110
114/* 111/*
115 * Hardware specific access to control-lines 112 * Hardware specific access to control-lines
116 */ 113 */
117static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) 114static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
118{ 115{
119 struct nand_chip *nand_chip = mtd->priv; 116 struct nand_chip *nand_chip = mtd->priv;
120 struct at91_nand_host *host = nand_chip->priv; 117 struct atmel_nand_host *host = nand_chip->priv;
121 118
122 if (ctrl & NAND_CTRL_CHANGE) { 119 if (ctrl & NAND_CTRL_CHANGE) {
123 if (ctrl & NAND_NCE) 120 if (ctrl & NAND_NCE)
124 at91_nand_enable(host); 121 atmel_nand_enable(host);
125 else 122 else
126 at91_nand_disable(host); 123 atmel_nand_disable(host);
127 } 124 }
128 if (cmd == NAND_CMD_NONE) 125 if (cmd == NAND_CMD_NONE)
129 return; 126 return;
@@ -137,18 +134,49 @@ static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
137/* 134/*
138 * Read the Device Ready pin. 135 * Read the Device Ready pin.
139 */ 136 */
140static int at91_nand_device_ready(struct mtd_info *mtd) 137static int atmel_nand_device_ready(struct mtd_info *mtd)
141{ 138{
142 struct nand_chip *nand_chip = mtd->priv; 139 struct nand_chip *nand_chip = mtd->priv;
143 struct at91_nand_host *host = nand_chip->priv; 140 struct atmel_nand_host *host = nand_chip->priv;
144 141
145 return at91_get_gpio_value(host->board->rdy_pin); 142 return gpio_get_value(host->board->rdy_pin);
143}
144
145/*
146 * Minimal-overhead PIO for data access.
147 */
148static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
149{
150 struct nand_chip *nand_chip = mtd->priv;
151
152 __raw_readsb(nand_chip->IO_ADDR_R, buf, len);
153}
154
155static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
156{
157 struct nand_chip *nand_chip = mtd->priv;
158
159 __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
160}
161
162static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
163{
164 struct nand_chip *nand_chip = mtd->priv;
165
166 __raw_writesb(nand_chip->IO_ADDR_W, buf, len);
167}
168
169static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
170{
171 struct nand_chip *nand_chip = mtd->priv;
172
173 __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
146} 174}
147 175
148/* 176/*
149 * write oob for small pages 177 * write oob for small pages
150 */ 178 */
151static int at91_nand_write_oob_512(struct mtd_info *mtd, 179static int atmel_nand_write_oob_512(struct mtd_info *mtd,
152 struct nand_chip *chip, int page) 180 struct nand_chip *chip, int page)
153{ 181{
154 int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; 182 int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -176,7 +204,7 @@ static int at91_nand_write_oob_512(struct mtd_info *mtd,
176/* 204/*
177 * read oob for small pages 205 * read oob for small pages
178 */ 206 */
179static int at91_nand_read_oob_512(struct mtd_info *mtd, 207static int atmel_nand_read_oob_512(struct mtd_info *mtd,
180 struct nand_chip *chip, int page, int sndcmd) 208 struct nand_chip *chip, int page, int sndcmd)
181{ 209{
182 if (sndcmd) { 210 if (sndcmd) {
@@ -196,11 +224,11 @@ static int at91_nand_read_oob_512(struct mtd_info *mtd,
196 * dat: raw data (unused) 224 * dat: raw data (unused)
197 * ecc_code: buffer for ECC 225 * ecc_code: buffer for ECC
198 */ 226 */
199static int at91_nand_calculate(struct mtd_info *mtd, 227static int atmel_nand_calculate(struct mtd_info *mtd,
200 const u_char *dat, unsigned char *ecc_code) 228 const u_char *dat, unsigned char *ecc_code)
201{ 229{
202 struct nand_chip *nand_chip = mtd->priv; 230 struct nand_chip *nand_chip = mtd->priv;
203 struct at91_nand_host *host = nand_chip->priv; 231 struct atmel_nand_host *host = nand_chip->priv;
204 uint32_t *eccpos = nand_chip->ecc.layout->eccpos; 232 uint32_t *eccpos = nand_chip->ecc.layout->eccpos;
205 unsigned int ecc_value; 233 unsigned int ecc_value;
206 234
@@ -211,7 +239,7 @@ static int at91_nand_calculate(struct mtd_info *mtd,
211 ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF; 239 ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;
212 240
213 /* get the last 2 ECC bytes */ 241 /* get the last 2 ECC bytes */
214 ecc_value = ecc_readl(host->ecc, NPR) & AT91_ECC_NPARITY; 242 ecc_value = ecc_readl(host->ecc, NPR) & ATMEL_ECC_NPARITY;
215 243
216 ecc_code[eccpos[2]] = ecc_value & 0xFF; 244 ecc_code[eccpos[2]] = ecc_value & 0xFF;
217 ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF; 245 ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF;
@@ -226,7 +254,7 @@ static int at91_nand_calculate(struct mtd_info *mtd,
226 * chip: nand chip info structure 254 * chip: nand chip info structure
227 * buf: buffer to store read data 255 * buf: buffer to store read data
228 */ 256 */
229static int at91_nand_read_page(struct mtd_info *mtd, 257static int atmel_nand_read_page(struct mtd_info *mtd,
230 struct nand_chip *chip, uint8_t *buf) 258 struct nand_chip *chip, uint8_t *buf)
231{ 259{
232 int eccsize = chip->ecc.size; 260 int eccsize = chip->ecc.size;
@@ -237,6 +265,19 @@ static int at91_nand_read_page(struct mtd_info *mtd,
237 uint8_t *ecc_pos; 265 uint8_t *ecc_pos;
238 int stat; 266 int stat;
239 267
268 /*
269 * Errata: ALE is incorrectly wired up to the ECC controller
270 * on the AP7000, so it will include the address cycles in the
271 * ECC calculation.
272 *
273 * Workaround: Reset the parity registers before reading the
274 * actual data.
275 */
276 if (cpu_is_at32ap7000()) {
277 struct atmel_nand_host *host = chip->priv;
278 ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
279 }
280
240 /* read the page */ 281 /* read the page */
241 chip->read_buf(mtd, p, eccsize); 282 chip->read_buf(mtd, p, eccsize);
242 283
@@ -285,11 +326,11 @@ static int at91_nand_read_page(struct mtd_info *mtd,
285 * 326 *
286 * Detect and correct a 1 bit error for a page 327 * Detect and correct a 1 bit error for a page
287 */ 328 */
288static int at91_nand_correct(struct mtd_info *mtd, u_char *dat, 329static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
289 u_char *read_ecc, u_char *isnull) 330 u_char *read_ecc, u_char *isnull)
290{ 331{
291 struct nand_chip *nand_chip = mtd->priv; 332 struct nand_chip *nand_chip = mtd->priv;
292 struct at91_nand_host *host = nand_chip->priv; 333 struct atmel_nand_host *host = nand_chip->priv;
293 unsigned int ecc_status; 334 unsigned int ecc_status;
294 unsigned int ecc_word, ecc_bit; 335 unsigned int ecc_word, ecc_bit;
295 336
@@ -297,43 +338,43 @@ static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
297 ecc_status = ecc_readl(host->ecc, SR); 338 ecc_status = ecc_readl(host->ecc, SR);
298 339
299 /* if there's no error */ 340 /* if there's no error */
300 if (likely(!(ecc_status & AT91_ECC_RECERR))) 341 if (likely(!(ecc_status & ATMEL_ECC_RECERR)))
301 return 0; 342 return 0;
302 343
303 /* get error bit offset (4 bits) */ 344 /* get error bit offset (4 bits) */
304 ecc_bit = ecc_readl(host->ecc, PR) & AT91_ECC_BITADDR; 345 ecc_bit = ecc_readl(host->ecc, PR) & ATMEL_ECC_BITADDR;
305 /* get word address (12 bits) */ 346 /* get word address (12 bits) */
306 ecc_word = ecc_readl(host->ecc, PR) & AT91_ECC_WORDADDR; 347 ecc_word = ecc_readl(host->ecc, PR) & ATMEL_ECC_WORDADDR;
307 ecc_word >>= 4; 348 ecc_word >>= 4;
308 349
309 /* if there are multiple errors */ 350 /* if there are multiple errors */
310 if (ecc_status & AT91_ECC_MULERR) { 351 if (ecc_status & ATMEL_ECC_MULERR) {
311 /* check if it is a freshly erased block 352 /* check if it is a freshly erased block
312 * (filled with 0xff) */ 353 * (filled with 0xff) */
313 if ((ecc_bit == AT91_ECC_BITADDR) 354 if ((ecc_bit == ATMEL_ECC_BITADDR)
314 && (ecc_word == (AT91_ECC_WORDADDR >> 4))) { 355 && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) {
315 /* the block has just been erased, return OK */ 356 /* the block has just been erased, return OK */
316 return 0; 357 return 0;
317 } 358 }
318 /* it doesn't seems to be a freshly 359 /* it doesn't seems to be a freshly
319 * erased block. 360 * erased block.
320 * We can't correct so many errors */ 361 * We can't correct so many errors */
321 dev_dbg(host->dev, "at91_nand : multiple errors detected." 362 dev_dbg(host->dev, "atmel_nand : multiple errors detected."
322 " Unable to correct.\n"); 363 " Unable to correct.\n");
323 return -EIO; 364 return -EIO;
324 } 365 }
325 366
326 /* if there's a single bit error : we can correct it */ 367 /* if there's a single bit error : we can correct it */
327 if (ecc_status & AT91_ECC_ECCERR) { 368 if (ecc_status & ATMEL_ECC_ECCERR) {
328 /* there's nothing much to do here. 369 /* there's nothing much to do here.
329 * the bit error is on the ECC itself. 370 * the bit error is on the ECC itself.
330 */ 371 */
331 dev_dbg(host->dev, "at91_nand : one bit error on ECC code." 372 dev_dbg(host->dev, "atmel_nand : one bit error on ECC code."
332 " Nothing to correct\n"); 373 " Nothing to correct\n");
333 return 0; 374 return 0;
334 } 375 }
335 376
336 dev_dbg(host->dev, "at91_nand : one bit error on data." 377 dev_dbg(host->dev, "atmel_nand : one bit error on data."
337 " (word offset in the page :" 378 " (word offset in the page :"
338 " 0x%x bit offset : 0x%x)\n", 379 " 0x%x bit offset : 0x%x)\n",
339 ecc_word, ecc_bit); 380 ecc_word, ecc_bit);
@@ -345,14 +386,21 @@ static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
345 /* 8 bits words */ 386 /* 8 bits words */
346 dat[ecc_word] ^= (1 << ecc_bit); 387 dat[ecc_word] ^= (1 << ecc_bit);
347 } 388 }
348 dev_dbg(host->dev, "at91_nand : error corrected\n"); 389 dev_dbg(host->dev, "atmel_nand : error corrected\n");
349 return 1; 390 return 1;
350} 391}
351 392
352/* 393/*
353 * Enable HW ECC : unsused 394 * Enable HW ECC : unused on most chips
354 */ 395 */
355static void at91_nand_hwctl(struct mtd_info *mtd, int mode) { ; } 396static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
397{
398 if (cpu_is_at32ap7000()) {
399 struct nand_chip *nand_chip = mtd->priv;
400 struct atmel_nand_host *host = nand_chip->priv;
401 ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
402 }
403}
356 404
357#ifdef CONFIG_MTD_PARTITIONS 405#ifdef CONFIG_MTD_PARTITIONS
358static const char *part_probes[] = { "cmdlinepart", NULL }; 406static const char *part_probes[] = { "cmdlinepart", NULL };
@@ -361,9 +409,9 @@ static const char *part_probes[] = { "cmdlinepart", NULL };
361/* 409/*
362 * Probe for the NAND device. 410 * Probe for the NAND device.
363 */ 411 */
364static int __init at91_nand_probe(struct platform_device *pdev) 412static int __init atmel_nand_probe(struct platform_device *pdev)
365{ 413{
366 struct at91_nand_host *host; 414 struct atmel_nand_host *host;
367 struct mtd_info *mtd; 415 struct mtd_info *mtd;
368 struct nand_chip *nand_chip; 416 struct nand_chip *nand_chip;
369 struct resource *regs; 417 struct resource *regs;
@@ -375,24 +423,24 @@ static int __init at91_nand_probe(struct platform_device *pdev)
375 int num_partitions = 0; 423 int num_partitions = 0;
376#endif 424#endif
377 425
378 /* Allocate memory for the device structure (and zero it) */
379 host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL);
380 if (!host) {
381 printk(KERN_ERR "at91_nand: failed to allocate device structure.\n");
382 return -ENOMEM;
383 }
384
385 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 426 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
386 if (!mem) { 427 if (!mem) {
387 printk(KERN_ERR "at91_nand: can't get I/O resource mem\n"); 428 printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n");
388 return -ENXIO; 429 return -ENXIO;
389 } 430 }
390 431
432 /* Allocate memory for the device structure (and zero it) */
433 host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL);
434 if (!host) {
435 printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n");
436 return -ENOMEM;
437 }
438
391 host->io_base = ioremap(mem->start, mem->end - mem->start + 1); 439 host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
392 if (host->io_base == NULL) { 440 if (host->io_base == NULL) {
393 printk(KERN_ERR "at91_nand: ioremap failed\n"); 441 printk(KERN_ERR "atmel_nand: ioremap failed\n");
394 kfree(host); 442 res = -EIO;
395 return -EIO; 443 goto err_nand_ioremap;
396 } 444 }
397 445
398 mtd = &host->mtd; 446 mtd = &host->mtd;
@@ -407,14 +455,14 @@ static int __init at91_nand_probe(struct platform_device *pdev)
407 /* Set address of NAND IO lines */ 455 /* Set address of NAND IO lines */
408 nand_chip->IO_ADDR_R = host->io_base; 456 nand_chip->IO_ADDR_R = host->io_base;
409 nand_chip->IO_ADDR_W = host->io_base; 457 nand_chip->IO_ADDR_W = host->io_base;
410 nand_chip->cmd_ctrl = at91_nand_cmd_ctrl; 458 nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
411 459
412 if (host->board->rdy_pin) 460 if (host->board->rdy_pin)
413 nand_chip->dev_ready = at91_nand_device_ready; 461 nand_chip->dev_ready = atmel_nand_device_ready;
414 462
415 regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); 463 regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
416 if (!regs && hard_ecc) { 464 if (!regs && hard_ecc) {
417 printk(KERN_ERR "at91_nand: can't get I/O resource " 465 printk(KERN_ERR "atmel_nand: can't get I/O resource "
418 "regs\nFalling back on software ECC\n"); 466 "regs\nFalling back on software ECC\n");
419 } 467 }
420 468
@@ -424,15 +472,15 @@ static int __init at91_nand_probe(struct platform_device *pdev)
424 if (hard_ecc && regs) { 472 if (hard_ecc && regs) {
425 host->ecc = ioremap(regs->start, regs->end - regs->start + 1); 473 host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
426 if (host->ecc == NULL) { 474 if (host->ecc == NULL) {
427 printk(KERN_ERR "at91_nand: ioremap failed\n"); 475 printk(KERN_ERR "atmel_nand: ioremap failed\n");
428 res = -EIO; 476 res = -EIO;
429 goto err_ecc_ioremap; 477 goto err_ecc_ioremap;
430 } 478 }
431 nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME; 479 nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME;
432 nand_chip->ecc.calculate = at91_nand_calculate; 480 nand_chip->ecc.calculate = atmel_nand_calculate;
433 nand_chip->ecc.correct = at91_nand_correct; 481 nand_chip->ecc.correct = atmel_nand_correct;
434 nand_chip->ecc.hwctl = at91_nand_hwctl; 482 nand_chip->ecc.hwctl = atmel_nand_hwctl;
435 nand_chip->ecc.read_page = at91_nand_read_page; 483 nand_chip->ecc.read_page = atmel_nand_read_page;
436 nand_chip->ecc.bytes = 4; 484 nand_chip->ecc.bytes = 4;
437 nand_chip->ecc.prepad = 0; 485 nand_chip->ecc.prepad = 0;
438 nand_chip->ecc.postpad = 0; 486 nand_chip->ecc.postpad = 0;
@@ -440,24 +488,30 @@ static int __init at91_nand_probe(struct platform_device *pdev)
440 488
441 nand_chip->chip_delay = 20; /* 20us command delay time */ 489 nand_chip->chip_delay = 20; /* 20us command delay time */
442 490
443 if (host->board->bus_width_16) /* 16-bit bus width */ 491 if (host->board->bus_width_16) { /* 16-bit bus width */
444 nand_chip->options |= NAND_BUSWIDTH_16; 492 nand_chip->options |= NAND_BUSWIDTH_16;
493 nand_chip->read_buf = atmel_read_buf16;
494 nand_chip->write_buf = atmel_write_buf16;
495 } else {
496 nand_chip->read_buf = atmel_read_buf;
497 nand_chip->write_buf = atmel_write_buf;
498 }
445 499
446 platform_set_drvdata(pdev, host); 500 platform_set_drvdata(pdev, host);
447 at91_nand_enable(host); 501 atmel_nand_enable(host);
448 502
449 if (host->board->det_pin) { 503 if (host->board->det_pin) {
450 if (at91_get_gpio_value(host->board->det_pin)) { 504 if (gpio_get_value(host->board->det_pin)) {
451 printk ("No SmartMedia card inserted.\n"); 505 printk("No SmartMedia card inserted.\n");
452 res = ENXIO; 506 res = ENXIO;
453 goto out; 507 goto err_no_card;
454 } 508 }
455 } 509 }
456 510
457 /* first scan to find the device and get the page size */ 511 /* first scan to find the device and get the page size */
458 if (nand_scan_ident(mtd, 1)) { 512 if (nand_scan_ident(mtd, 1)) {
459 res = -ENXIO; 513 res = -ENXIO;
460 goto out; 514 goto err_scan_ident;
461 } 515 }
462 516
463 if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) { 517 if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) {
@@ -467,22 +521,22 @@ static int __init at91_nand_probe(struct platform_device *pdev)
467 /* set ECC page size and oob layout */ 521 /* set ECC page size and oob layout */
468 switch (mtd->writesize) { 522 switch (mtd->writesize) {
469 case 512: 523 case 512:
470 nand_chip->ecc.layout = &at91_oobinfo_small; 524 nand_chip->ecc.layout = &atmel_oobinfo_small;
471 nand_chip->ecc.read_oob = at91_nand_read_oob_512; 525 nand_chip->ecc.read_oob = atmel_nand_read_oob_512;
472 nand_chip->ecc.write_oob = at91_nand_write_oob_512; 526 nand_chip->ecc.write_oob = atmel_nand_write_oob_512;
473 ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_528); 527 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
474 break; 528 break;
475 case 1024: 529 case 1024:
476 nand_chip->ecc.layout = &at91_oobinfo_large; 530 nand_chip->ecc.layout = &atmel_oobinfo_large;
477 ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_1056); 531 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
478 break; 532 break;
479 case 2048: 533 case 2048:
480 nand_chip->ecc.layout = &at91_oobinfo_large; 534 nand_chip->ecc.layout = &atmel_oobinfo_large;
481 ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_2112); 535 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
482 break; 536 break;
483 case 4096: 537 case 4096:
484 nand_chip->ecc.layout = &at91_oobinfo_large; 538 nand_chip->ecc.layout = &atmel_oobinfo_large;
485 ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_4224); 539 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
486 break; 540 break;
487 default: 541 default:
488 /* page size not handled by HW ECC */ 542 /* page size not handled by HW ECC */
@@ -502,12 +556,12 @@ static int __init at91_nand_probe(struct platform_device *pdev)
502 /* second phase scan */ 556 /* second phase scan */
503 if (nand_scan_tail(mtd)) { 557 if (nand_scan_tail(mtd)) {
504 res = -ENXIO; 558 res = -ENXIO;
505 goto out; 559 goto err_scan_tail;
506 } 560 }
507 561
508#ifdef CONFIG_MTD_PARTITIONS 562#ifdef CONFIG_MTD_PARTITIONS
509#ifdef CONFIG_MTD_CMDLINE_PARTS 563#ifdef CONFIG_MTD_CMDLINE_PARTS
510 mtd->name = "at91_nand"; 564 mtd->name = "atmel_nand";
511 num_partitions = parse_mtd_partitions(mtd, part_probes, 565 num_partitions = parse_mtd_partitions(mtd, part_probes,
512 &partitions, 0); 566 &partitions, 0);
513#endif 567#endif
@@ -516,9 +570,9 @@ static int __init at91_nand_probe(struct platform_device *pdev)
516 &num_partitions); 570 &num_partitions);
517 571
518 if ((!partitions) || (num_partitions == 0)) { 572 if ((!partitions) || (num_partitions == 0)) {
519 printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n"); 573 printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n");
520 res = ENXIO; 574 res = ENXIO;
521 goto release; 575 goto err_no_partitions;
522 } 576 }
523 577
524 res = add_mtd_partitions(mtd, partitions, num_partitions); 578 res = add_mtd_partitions(mtd, partitions, num_partitions);
@@ -530,17 +584,19 @@ static int __init at91_nand_probe(struct platform_device *pdev)
530 return res; 584 return res;
531 585
532#ifdef CONFIG_MTD_PARTITIONS 586#ifdef CONFIG_MTD_PARTITIONS
533release: 587err_no_partitions:
534#endif 588#endif
535 nand_release(mtd); 589 nand_release(mtd);
536 590err_scan_tail:
537out: 591err_scan_ident:
538 iounmap(host->ecc); 592err_no_card:
539 593 atmel_nand_disable(host);
540err_ecc_ioremap:
541 at91_nand_disable(host);
542 platform_set_drvdata(pdev, NULL); 594 platform_set_drvdata(pdev, NULL);
595 if (host->ecc)
596 iounmap(host->ecc);
597err_ecc_ioremap:
543 iounmap(host->io_base); 598 iounmap(host->io_base);
599err_nand_ioremap:
544 kfree(host); 600 kfree(host);
545 return res; 601 return res;
546} 602}
@@ -548,47 +604,47 @@ err_ecc_ioremap:
548/* 604/*
549 * Remove a NAND device. 605 * Remove a NAND device.
550 */ 606 */
551static int __devexit at91_nand_remove(struct platform_device *pdev) 607static int __exit atmel_nand_remove(struct platform_device *pdev)
552{ 608{
553 struct at91_nand_host *host = platform_get_drvdata(pdev); 609 struct atmel_nand_host *host = platform_get_drvdata(pdev);
554 struct mtd_info *mtd = &host->mtd; 610 struct mtd_info *mtd = &host->mtd;
555 611
556 nand_release(mtd); 612 nand_release(mtd);
557 613
558 at91_nand_disable(host); 614 atmel_nand_disable(host);
559 615
616 if (host->ecc)
617 iounmap(host->ecc);
560 iounmap(host->io_base); 618 iounmap(host->io_base);
561 iounmap(host->ecc);
562 kfree(host); 619 kfree(host);
563 620
564 return 0; 621 return 0;
565} 622}
566 623
567static struct platform_driver at91_nand_driver = { 624static struct platform_driver atmel_nand_driver = {
568 .probe = at91_nand_probe, 625 .remove = __exit_p(atmel_nand_remove),
569 .remove = at91_nand_remove,
570 .driver = { 626 .driver = {
571 .name = "at91_nand", 627 .name = "atmel_nand",
572 .owner = THIS_MODULE, 628 .owner = THIS_MODULE,
573 }, 629 },
574}; 630};
575 631
576static int __init at91_nand_init(void) 632static int __init atmel_nand_init(void)
577{ 633{
578 return platform_driver_register(&at91_nand_driver); 634 return platform_driver_probe(&atmel_nand_driver, atmel_nand_probe);
579} 635}
580 636
581 637
582static void __exit at91_nand_exit(void) 638static void __exit atmel_nand_exit(void)
583{ 639{
584 platform_driver_unregister(&at91_nand_driver); 640 platform_driver_unregister(&atmel_nand_driver);
585} 641}
586 642
587 643
588module_init(at91_nand_init); 644module_init(atmel_nand_init);
589module_exit(at91_nand_exit); 645module_exit(atmel_nand_exit);
590 646
591MODULE_LICENSE("GPL"); 647MODULE_LICENSE("GPL");
592MODULE_AUTHOR("Rick Bronson"); 648MODULE_AUTHOR("Rick Bronson");
593MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200 / AT91SAM9"); 649MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91 / AVR32");
594MODULE_ALIAS("platform:at91_nand"); 650MODULE_ALIAS("platform:atmel_nand");
diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h
new file mode 100644
index 000000000000..1ee7f993db1c
--- /dev/null
+++ b/drivers/mtd/nand/atmel_nand_ecc.h
@@ -0,0 +1,36 @@
1/*
2 * Error Corrected Code Controller (ECC) - System peripherals regsters.
3 * Based on AT91SAM9260 datasheet revision B.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 */
10
11#ifndef ATMEL_NAND_ECC_H
12#define ATMEL_NAND_ECC_H
13
14#define ATMEL_ECC_CR 0x00 /* Control register */
15#define ATMEL_ECC_RST (1 << 0) /* Reset parity */
16
17#define ATMEL_ECC_MR 0x04 /* Mode register */
18#define ATMEL_ECC_PAGESIZE (3 << 0) /* Page Size */
19#define ATMEL_ECC_PAGESIZE_528 (0)
20#define ATMEL_ECC_PAGESIZE_1056 (1)
21#define ATMEL_ECC_PAGESIZE_2112 (2)
22#define ATMEL_ECC_PAGESIZE_4224 (3)
23
24#define ATMEL_ECC_SR 0x08 /* Status register */
25#define ATMEL_ECC_RECERR (1 << 0) /* Recoverable Error */
26#define ATMEL_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */
27#define ATMEL_ECC_MULERR (1 << 2) /* Multiple Errors */
28
29#define ATMEL_ECC_PR 0x0c /* Parity register */
30#define ATMEL_ECC_BITADDR (0xf << 0) /* Bit Error Address */
31#define ATMEL_ECC_WORDADDR (0xfff << 4) /* Word Error Address */
32
33#define ATMEL_ECC_NPR 0x10 /* NParity register */
34#define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */
35
36#endif
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 09e421a96893..761946ea45b1 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -3,8 +3,6 @@
3 * 3 *
4 * Copyright (C) 2004 Embedded Edge, LLC 4 * Copyright (C) 2004 Embedded Edge, LLC
5 * 5 *
6 * $Id: au1550nd.c,v 1.13 2005/11/07 11:14:30 gleixner Exp $
7 *
8 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
@@ -604,8 +602,6 @@ module_init(au1xxx_nand_init);
604 */ 602 */
605static void __exit au1550_cleanup(void) 603static void __exit au1550_cleanup(void)
606{ 604{
607 struct nand_chip *this = (struct nand_chip *)&au1550_mtd[1];
608
609 /* Release resources, unregister device */ 605 /* Release resources, unregister device */
610 nand_release(au1550_mtd); 606 nand_release(au1550_mtd);
611 607
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
index dd38011ee0b7..553dd7e9b41c 100644
--- a/drivers/mtd/nand/autcpu12.c
+++ b/drivers/mtd/nand/autcpu12.c
@@ -6,8 +6,6 @@
6 * Derived from drivers/mtd/spia.c 6 * Derived from drivers/mtd/spia.c
7 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) 7 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
8 * 8 *
9 * $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $
10 *
11 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index da6ceaa80ba1..95345d051579 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -626,10 +626,12 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
626{ 626{
627 struct mtd_info *mtd; 627 struct mtd_info *mtd;
628 struct cafe_priv *cafe; 628 struct cafe_priv *cafe;
629 struct mtd_partition *parts;
630 uint32_t ctrl; 629 uint32_t ctrl;
631 int nr_parts;
632 int err = 0; 630 int err = 0;
631#ifdef CONFIG_MTD_PARTITIONS
632 struct mtd_partition *parts;
633 int nr_parts;
634#endif
633 635
634 /* Very old versions shared the same PCI ident for all three 636 /* Very old versions shared the same PCI ident for all three
635 functions on the chip. Verify the class too... */ 637 functions on the chip. Verify the class too... */
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 0e72153b3297..765d4f0f7c86 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -15,8 +15,6 @@
15 * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de> 15 * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de>
16 * 16 *
17 * Interface to generic NAND code for M-Systems DiskOnChip devices 17 * Interface to generic NAND code for M-Systems DiskOnChip devices
18 *
19 * $Id: diskonchip.c,v 1.55 2005/11/07 11:14:30 gleixner Exp $
20 */ 18 */
21 19
22#include <linux/kernel.h> 20#include <linux/kernel.h>
@@ -54,8 +52,6 @@ static unsigned long __initdata doc_locations[] = {
54 0xe0000, 0xe2000, 0xe4000, 0xe6000, 52 0xe0000, 0xe2000, 0xe4000, 0xe6000,
55 0xe8000, 0xea000, 0xec000, 0xee000, 53 0xe8000, 0xea000, 0xec000, 0xee000,
56#endif /* CONFIG_MTD_DOCPROBE_HIGH */ 54#endif /* CONFIG_MTD_DOCPROBE_HIGH */
57#elif defined(__PPC__)
58 0xe4000000,
59#else 55#else
60#warning Unknown architecture for DiskOnChip. No default probe locations defined 56#warning Unknown architecture for DiskOnChip. No default probe locations defined
61#endif 57#endif
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index ba67bbec20d3..387e4352903e 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -6,8 +6,6 @@
6 * Derived from drivers/mtd/nand/autcpu12.c 6 * Derived from drivers/mtd/nand/autcpu12.c
7 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) 7 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
8 * 8 *
9 * $Id: edb7312.c,v 1.12 2005/11/07 11:14:30 gleixner Exp $
10 *
11 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
diff --git a/drivers/mtd/nand/excite_nandflash.c b/drivers/mtd/nand/excite_nandflash.c
index bed87290decc..ced14b5294d5 100644
--- a/drivers/mtd/nand/excite_nandflash.c
+++ b/drivers/mtd/nand/excite_nandflash.c
@@ -209,7 +209,7 @@ static int __init excite_nand_probe(struct device *dev)
209 if (likely(!scan_res)) { 209 if (likely(!scan_res)) {
210 DEBUG(MTD_DEBUG_LEVEL2, "%s: register partitions\n", module_id); 210 DEBUG(MTD_DEBUG_LEVEL2, "%s: register partitions\n", module_id);
211 add_mtd_partitions(&drvdata->board_mtd, partition_info, 211 add_mtd_partitions(&drvdata->board_mtd, partition_info,
212 sizeof partition_info / sizeof partition_info[0]); 212 ARRAY_SIZE(partition_info));
213 } else { 213 } else {
214 iounmap(drvdata->regs); 214 iounmap(drvdata->regs);
215 kfree(drvdata); 215 kfree(drvdata);
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 4b69aacdf5ca..9dff51351f4f 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -89,7 +89,6 @@ static struct nand_ecclayout fsl_elbc_oob_sp_eccm0 = {
89 .eccbytes = 3, 89 .eccbytes = 3,
90 .eccpos = {6, 7, 8}, 90 .eccpos = {6, 7, 8},
91 .oobfree = { {0, 5}, {9, 7} }, 91 .oobfree = { {0, 5}, {9, 7} },
92 .oobavail = 12,
93}; 92};
94 93
95/* Small Page FLASH with FMR[ECCM] = 1 */ 94/* Small Page FLASH with FMR[ECCM] = 1 */
@@ -97,7 +96,6 @@ static struct nand_ecclayout fsl_elbc_oob_sp_eccm1 = {
97 .eccbytes = 3, 96 .eccbytes = 3,
98 .eccpos = {8, 9, 10}, 97 .eccpos = {8, 9, 10},
99 .oobfree = { {0, 5}, {6, 2}, {11, 5} }, 98 .oobfree = { {0, 5}, {6, 2}, {11, 5} },
100 .oobavail = 12,
101}; 99};
102 100
103/* Large Page FLASH with FMR[ECCM] = 0 */ 101/* Large Page FLASH with FMR[ECCM] = 0 */
@@ -105,7 +103,6 @@ static struct nand_ecclayout fsl_elbc_oob_lp_eccm0 = {
105 .eccbytes = 12, 103 .eccbytes = 12,
106 .eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56}, 104 .eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56},
107 .oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} }, 105 .oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} },
108 .oobavail = 48,
109}; 106};
110 107
111/* Large Page FLASH with FMR[ECCM] = 1 */ 108/* Large Page FLASH with FMR[ECCM] = 1 */
@@ -113,7 +110,48 @@ static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = {
113 .eccbytes = 12, 110 .eccbytes = 12,
114 .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, 111 .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
115 .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} }, 112 .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} },
116 .oobavail = 48, 113};
114
115/*
116 * fsl_elbc_oob_lp_eccm* specify that LP NAND's OOB free area starts at offset
117 * 1, so we have to adjust bad block pattern. This pattern should be used for
118 * x8 chips only. So far hardware does not support x16 chips anyway.
119 */
120static u8 scan_ff_pattern[] = { 0xff, };
121
122static struct nand_bbt_descr largepage_memorybased = {
123 .options = 0,
124 .offs = 0,
125 .len = 1,
126 .pattern = scan_ff_pattern,
127};
128
129/*
130 * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt,
131 * interfere with ECC positions, that's why we implement our own descriptors.
132 * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0.
133 */
134static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
135static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
136
137static struct nand_bbt_descr bbt_main_descr = {
138 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
139 NAND_BBT_2BIT | NAND_BBT_VERSION,
140 .offs = 11,
141 .len = 4,
142 .veroffs = 15,
143 .maxblocks = 4,
144 .pattern = bbt_pattern,
145};
146
147static struct nand_bbt_descr bbt_mirror_descr = {
148 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
149 NAND_BBT_2BIT | NAND_BBT_VERSION,
150 .offs = 11,
151 .len = 4,
152 .veroffs = 15,
153 .maxblocks = 4,
154 .pattern = mirror_pattern,
117}; 155};
118 156
119/*=================================*/ 157/*=================================*/
@@ -687,8 +725,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
687 chip->ecc.layout = (priv->fmr & FMR_ECCM) ? 725 chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
688 &fsl_elbc_oob_lp_eccm1 : 726 &fsl_elbc_oob_lp_eccm1 :
689 &fsl_elbc_oob_lp_eccm0; 727 &fsl_elbc_oob_lp_eccm0;
690 mtd->ecclayout = chip->ecc.layout; 728 chip->badblock_pattern = &largepage_memorybased;
691 mtd->oobavail = chip->ecc.layout->oobavail;
692 } 729 }
693 } else { 730 } else {
694 dev_err(ctrl->dev, 731 dev_err(ctrl->dev,
@@ -752,8 +789,12 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
752 chip->cmdfunc = fsl_elbc_cmdfunc; 789 chip->cmdfunc = fsl_elbc_cmdfunc;
753 chip->waitfunc = fsl_elbc_wait; 790 chip->waitfunc = fsl_elbc_wait;
754 791
792 chip->bbt_td = &bbt_main_descr;
793 chip->bbt_md = &bbt_mirror_descr;
794
755 /* set up nand options */ 795 /* set up nand options */
756 chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR; 796 chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
797 NAND_USE_FLASH_BBT;
757 798
758 chip->controller = &ctrl->controller; 799 chip->controller = &ctrl->controller;
759 chip->priv = priv; 800 chip->priv = priv;
@@ -795,8 +836,8 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
795 return 0; 836 return 0;
796} 837}
797 838
798static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, 839static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
799 struct device_node *node) 840 struct device_node *node)
800{ 841{
801 struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 842 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
802 struct fsl_elbc_mtd *priv; 843 struct fsl_elbc_mtd *priv;
@@ -917,7 +958,7 @@ static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
917 return 0; 958 return 0;
918} 959}
919 960
920static int __devexit fsl_elbc_ctrl_remove(struct of_device *ofdev) 961static int fsl_elbc_ctrl_remove(struct of_device *ofdev)
921{ 962{
922 struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev); 963 struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
923 int i; 964 int i;
@@ -1041,7 +1082,7 @@ static struct of_platform_driver fsl_elbc_ctrl_driver = {
1041 }, 1082 },
1042 .match_table = fsl_elbc_match, 1083 .match_table = fsl_elbc_match,
1043 .probe = fsl_elbc_ctrl_probe, 1084 .probe = fsl_elbc_ctrl_probe,
1044 .remove = __devexit_p(fsl_elbc_ctrl_remove), 1085 .remove = fsl_elbc_ctrl_remove,
1045}; 1086};
1046 1087
1047static int __init fsl_elbc_init(void) 1088static int __init fsl_elbc_init(void)
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index 2d585d2d090c..9e59de501c2e 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -7,8 +7,6 @@
7 * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) 7 * Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
8 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) 8 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
9 * 9 *
10 * $Id: h1910.c,v 1.6 2005/11/07 11:14:30 gleixner Exp $
11 *
12 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ba1bdf787323..d1129bae6c27 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -798,6 +798,87 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
798} 798}
799 799
800/** 800/**
801 * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
802 * @mtd: mtd info structure
803 * @chip: nand chip info structure
804 * @dataofs offset of requested data within the page
805 * @readlen data length
806 * @buf: buffer to store read data
807 */
808static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
809{
810 int start_step, end_step, num_steps;
811 uint32_t *eccpos = chip->ecc.layout->eccpos;
812 uint8_t *p;
813 int data_col_addr, i, gaps = 0;
814 int datafrag_len, eccfrag_len, aligned_len, aligned_pos;
815 int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
816
817 /* Column address wihin the page aligned to ECC size (256bytes). */
818 start_step = data_offs / chip->ecc.size;
819 end_step = (data_offs + readlen - 1) / chip->ecc.size;
820 num_steps = end_step - start_step + 1;
821
822 /* Data size aligned to ECC ecc.size*/
823 datafrag_len = num_steps * chip->ecc.size;
824 eccfrag_len = num_steps * chip->ecc.bytes;
825
826 data_col_addr = start_step * chip->ecc.size;
827 /* If we read not a page aligned data */
828 if (data_col_addr != 0)
829 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
830
831 p = bufpoi + data_col_addr;
832 chip->read_buf(mtd, p, datafrag_len);
833
834 /* Calculate ECC */
835 for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
836 chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
837
838 /* The performance is faster if to position offsets
839 according to ecc.pos. Let make sure here that
840 there are no gaps in ecc positions */
841 for (i = 0; i < eccfrag_len - 1; i++) {
842 if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
843 eccpos[i + start_step * chip->ecc.bytes + 1]) {
844 gaps = 1;
845 break;
846 }
847 }
848 if (gaps) {
849 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
850 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
851 } else {
852 /* send the command to read the particular ecc bytes */
853 /* take care about buswidth alignment in read_buf */
854 aligned_pos = eccpos[start_step * chip->ecc.bytes] & ~(busw - 1);
855 aligned_len = eccfrag_len;
856 if (eccpos[start_step * chip->ecc.bytes] & (busw - 1))
857 aligned_len++;
858 if (eccpos[(start_step + num_steps) * chip->ecc.bytes] & (busw - 1))
859 aligned_len++;
860
861 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize + aligned_pos, -1);
862 chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
863 }
864
865 for (i = 0; i < eccfrag_len; i++)
866 chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + start_step * chip->ecc.bytes]];
867
868 p = bufpoi + data_col_addr;
869 for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) {
870 int stat;
871
872 stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
873 if (stat == -1)
874 mtd->ecc_stats.failed++;
875 else
876 mtd->ecc_stats.corrected += stat;
877 }
878 return 0;
879}
880
881/**
801 * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function 882 * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
802 * @mtd: mtd info structure 883 * @mtd: mtd info structure
803 * @chip: nand chip info structure 884 * @chip: nand chip info structure
@@ -994,6 +1075,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
994 /* Now read the page into the buffer */ 1075 /* Now read the page into the buffer */
995 if (unlikely(ops->mode == MTD_OOB_RAW)) 1076 if (unlikely(ops->mode == MTD_OOB_RAW))
996 ret = chip->ecc.read_page_raw(mtd, chip, bufpoi); 1077 ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
1078 else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
1079 ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);
997 else 1080 else
998 ret = chip->ecc.read_page(mtd, chip, bufpoi); 1081 ret = chip->ecc.read_page(mtd, chip, bufpoi);
999 if (ret < 0) 1082 if (ret < 0)
@@ -1001,7 +1084,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1001 1084
1002 /* Transfer not aligned data */ 1085 /* Transfer not aligned data */
1003 if (!aligned) { 1086 if (!aligned) {
1004 chip->pagebuf = realpage; 1087 if (!NAND_SUBPAGE_READ(chip) && !oob)
1088 chip->pagebuf = realpage;
1005 memcpy(buf, chip->buffers->databuf + col, bytes); 1089 memcpy(buf, chip->buffers->databuf + col, bytes);
1006 } 1090 }
1007 1091
@@ -2521,6 +2605,7 @@ int nand_scan_tail(struct mtd_info *mtd)
2521 chip->ecc.calculate = nand_calculate_ecc; 2605 chip->ecc.calculate = nand_calculate_ecc;
2522 chip->ecc.correct = nand_correct_data; 2606 chip->ecc.correct = nand_correct_data;
2523 chip->ecc.read_page = nand_read_page_swecc; 2607 chip->ecc.read_page = nand_read_page_swecc;
2608 chip->ecc.read_subpage = nand_read_subpage;
2524 chip->ecc.write_page = nand_write_page_swecc; 2609 chip->ecc.write_page = nand_write_page_swecc;
2525 chip->ecc.read_oob = nand_read_oob_std; 2610 chip->ecc.read_oob = nand_read_oob_std;
2526 chip->ecc.write_oob = nand_write_oob_std; 2611 chip->ecc.write_oob = nand_write_oob_std;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 5e121ceaa598..0b1c48595f12 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -6,8 +6,6 @@
6 * 6 *
7 * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) 7 * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
8 * 8 *
9 * $Id: nand_bbt.c,v 1.36 2005/11/07 11:14:30 gleixner Exp $
10 *
11 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index 9003a135e050..918a806a8471 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -9,8 +9,6 @@
9 * 9 *
10 * Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de> 10 * Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
11 * 11 *
12 * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $
13 *
14 * This file is free software; you can redistribute it and/or modify it 12 * This file is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the 13 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 or (at your option) any 14 * Free Software Foundation; either version 2 or (at your option) any
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index a3e3ab0185d5..69ee2c90eb0b 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -3,8 +3,6 @@
3 * 3 *
4 * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) 4 * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
5 * 5 *
6 * $Id: nand_ids.c,v 1.16 2005/11/07 11:14:31 gleixner Exp $
7 *
8 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index bb885d1fcab5..ecd70e2504f6 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -21,8 +21,6 @@
21 * You should have received a copy of the GNU General Public License 21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software 22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
24 *
25 * $Id: nandsim.c,v 1.8 2005/03/19 15:33:56 dedekind Exp $
26 */ 24 */
27 25
28#include <linux/init.h> 26#include <linux/init.h>
@@ -39,6 +37,7 @@
39#include <linux/delay.h> 37#include <linux/delay.h>
40#include <linux/list.h> 38#include <linux/list.h>
41#include <linux/random.h> 39#include <linux/random.h>
40#include <asm/div64.h>
42 41
43/* Default simulator parameters values */ 42/* Default simulator parameters values */
44#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ 43#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
@@ -298,11 +297,11 @@ struct nandsim {
298 297
299 /* NAND flash "geometry" */ 298 /* NAND flash "geometry" */
300 struct nandsin_geometry { 299 struct nandsin_geometry {
301 uint32_t totsz; /* total flash size, bytes */ 300 uint64_t totsz; /* total flash size, bytes */
302 uint32_t secsz; /* flash sector (erase block) size, bytes */ 301 uint32_t secsz; /* flash sector (erase block) size, bytes */
303 uint pgsz; /* NAND flash page size, bytes */ 302 uint pgsz; /* NAND flash page size, bytes */
304 uint oobsz; /* page OOB area size, bytes */ 303 uint oobsz; /* page OOB area size, bytes */
305 uint32_t totszoob; /* total flash size including OOB, bytes */ 304 uint64_t totszoob; /* total flash size including OOB, bytes */
306 uint pgszoob; /* page size including OOB , bytes*/ 305 uint pgszoob; /* page size including OOB , bytes*/
307 uint secszoob; /* sector size including OOB, bytes */ 306 uint secszoob; /* sector size including OOB, bytes */
308 uint pgnum; /* total number of pages */ 307 uint pgnum; /* total number of pages */
@@ -459,6 +458,12 @@ static char *get_partition_name(int i)
459 return kstrdup(buf, GFP_KERNEL); 458 return kstrdup(buf, GFP_KERNEL);
460} 459}
461 460
461static u_int64_t divide(u_int64_t n, u_int32_t d)
462{
463 do_div(n, d);
464 return n;
465}
466
462/* 467/*
463 * Initialize the nandsim structure. 468 * Initialize the nandsim structure.
464 * 469 *
@@ -469,8 +474,8 @@ static int init_nandsim(struct mtd_info *mtd)
469 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 474 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
470 struct nandsim *ns = (struct nandsim *)(chip->priv); 475 struct nandsim *ns = (struct nandsim *)(chip->priv);
471 int i, ret = 0; 476 int i, ret = 0;
472 u_int32_t remains; 477 u_int64_t remains;
473 u_int32_t next_offset; 478 u_int64_t next_offset;
474 479
475 if (NS_IS_INITIALIZED(ns)) { 480 if (NS_IS_INITIALIZED(ns)) {
476 NS_ERR("init_nandsim: nandsim is already initialized\n"); 481 NS_ERR("init_nandsim: nandsim is already initialized\n");
@@ -487,8 +492,8 @@ static int init_nandsim(struct mtd_info *mtd)
487 ns->geom.oobsz = mtd->oobsize; 492 ns->geom.oobsz = mtd->oobsize;
488 ns->geom.secsz = mtd->erasesize; 493 ns->geom.secsz = mtd->erasesize;
489 ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; 494 ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz;
490 ns->geom.pgnum = ns->geom.totsz / ns->geom.pgsz; 495 ns->geom.pgnum = divide(ns->geom.totsz, ns->geom.pgsz);
491 ns->geom.totszoob = ns->geom.totsz + ns->geom.pgnum * ns->geom.oobsz; 496 ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz;
492 ns->geom.secshift = ffs(ns->geom.secsz) - 1; 497 ns->geom.secshift = ffs(ns->geom.secsz) - 1;
493 ns->geom.pgshift = chip->page_shift; 498 ns->geom.pgshift = chip->page_shift;
494 ns->geom.oobshift = ffs(ns->geom.oobsz) - 1; 499 ns->geom.oobshift = ffs(ns->geom.oobsz) - 1;
@@ -511,7 +516,7 @@ static int init_nandsim(struct mtd_info *mtd)
511 } 516 }
512 517
513 if (ns->options & OPT_SMALLPAGE) { 518 if (ns->options & OPT_SMALLPAGE) {
514 if (ns->geom.totsz < (32 << 20)) { 519 if (ns->geom.totsz <= (32 << 20)) {
515 ns->geom.pgaddrbytes = 3; 520 ns->geom.pgaddrbytes = 3;
516 ns->geom.secaddrbytes = 2; 521 ns->geom.secaddrbytes = 2;
517 } else { 522 } else {
@@ -537,15 +542,16 @@ static int init_nandsim(struct mtd_info *mtd)
537 remains = ns->geom.totsz; 542 remains = ns->geom.totsz;
538 next_offset = 0; 543 next_offset = 0;
539 for (i = 0; i < parts_num; ++i) { 544 for (i = 0; i < parts_num; ++i) {
540 unsigned long part = parts[i]; 545 u_int64_t part_sz = (u_int64_t)parts[i] * ns->geom.secsz;
541 if (!part || part > remains / ns->geom.secsz) { 546
547 if (!part_sz || part_sz > remains) {
542 NS_ERR("bad partition size.\n"); 548 NS_ERR("bad partition size.\n");
543 ret = -EINVAL; 549 ret = -EINVAL;
544 goto error; 550 goto error;
545 } 551 }
546 ns->partitions[i].name = get_partition_name(i); 552 ns->partitions[i].name = get_partition_name(i);
547 ns->partitions[i].offset = next_offset; 553 ns->partitions[i].offset = next_offset;
548 ns->partitions[i].size = part * ns->geom.secsz; 554 ns->partitions[i].size = part_sz;
549 next_offset += ns->partitions[i].size; 555 next_offset += ns->partitions[i].size;
550 remains -= ns->partitions[i].size; 556 remains -= ns->partitions[i].size;
551 } 557 }
@@ -573,7 +579,7 @@ static int init_nandsim(struct mtd_info *mtd)
573 if (ns->busw == 16) 579 if (ns->busw == 16)
574 NS_WARN("16-bit flashes support wasn't tested\n"); 580 NS_WARN("16-bit flashes support wasn't tested\n");
575 581
576 printk("flash size: %u MiB\n", ns->geom.totsz >> 20); 582 printk("flash size: %llu MiB\n", ns->geom.totsz >> 20);
577 printk("page size: %u bytes\n", ns->geom.pgsz); 583 printk("page size: %u bytes\n", ns->geom.pgsz);
578 printk("OOB area size: %u bytes\n", ns->geom.oobsz); 584 printk("OOB area size: %u bytes\n", ns->geom.oobsz);
579 printk("sector size: %u KiB\n", ns->geom.secsz >> 10); 585 printk("sector size: %u KiB\n", ns->geom.secsz >> 10);
@@ -583,7 +589,7 @@ static int init_nandsim(struct mtd_info *mtd)
583 printk("bits in sector size: %u\n", ns->geom.secshift); 589 printk("bits in sector size: %u\n", ns->geom.secshift);
584 printk("bits in page size: %u\n", ns->geom.pgshift); 590 printk("bits in page size: %u\n", ns->geom.pgshift);
585 printk("bits in OOB size: %u\n", ns->geom.oobshift); 591 printk("bits in OOB size: %u\n", ns->geom.oobshift);
586 printk("flash size with OOB: %u KiB\n", ns->geom.totszoob >> 10); 592 printk("flash size with OOB: %llu KiB\n", ns->geom.totszoob >> 10);
587 printk("page address bytes: %u\n", ns->geom.pgaddrbytes); 593 printk("page address bytes: %u\n", ns->geom.pgaddrbytes);
588 printk("sector address bytes: %u\n", ns->geom.secaddrbytes); 594 printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
589 printk("options: %#x\n", ns->options); 595 printk("options: %#x\n", ns->options);
@@ -825,7 +831,7 @@ static int setup_wear_reporting(struct mtd_info *mtd)
825 831
826 if (!rptwear) 832 if (!rptwear)
827 return 0; 833 return 0;
828 wear_eb_count = mtd->size / mtd->erasesize; 834 wear_eb_count = divide(mtd->size, mtd->erasesize);
829 mem = wear_eb_count * sizeof(unsigned long); 835 mem = wear_eb_count * sizeof(unsigned long);
830 if (mem / sizeof(unsigned long) != wear_eb_count) { 836 if (mem / sizeof(unsigned long) != wear_eb_count) {
831 NS_ERR("Too many erase blocks for wear reporting\n"); 837 NS_ERR("Too many erase blocks for wear reporting\n");
@@ -2013,7 +2019,7 @@ static int __init ns_init_module(void)
2013 } 2019 }
2014 2020
2015 if (overridesize) { 2021 if (overridesize) {
2016 u_int32_t new_size = nsmtd->erasesize << overridesize; 2022 u_int64_t new_size = (u_int64_t)nsmtd->erasesize << overridesize;
2017 if (new_size >> overridesize != nsmtd->erasesize) { 2023 if (new_size >> overridesize != nsmtd->erasesize) {
2018 NS_ERR("overridesize is too big\n"); 2024 NS_ERR("overridesize is too big\n");
2019 goto err_exit; 2025 goto err_exit;
@@ -2021,7 +2027,8 @@ static int __init ns_init_module(void)
2021 /* N.B. This relies on nand_scan not doing anything with the size before we change it */ 2027 /* N.B. This relies on nand_scan not doing anything with the size before we change it */
2022 nsmtd->size = new_size; 2028 nsmtd->size = new_size;
2023 chip->chipsize = new_size; 2029 chip->chipsize = new_size;
2024 chip->chip_shift = ffs(new_size) - 1; 2030 chip->chip_shift = ffs(nsmtd->erasesize) + overridesize - 1;
2031 chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
2025 } 2032 }
2026 2033
2027 if ((retval = setup_wear_reporting(nsmtd)) != 0) 2034 if ((retval = setup_wear_reporting(nsmtd)) != 0)
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index 082073acf20f..cc8658431851 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -6,8 +6,6 @@
6 * Derived from drivers/mtd/nand/edb7312.c 6 * Derived from drivers/mtd/nand/edb7312.c
7 * 7 *
8 * 8 *
9 * $Id: ppchameleonevb.c,v 1.7 2005/11/07 11:14:31 gleixner Exp $
10 *
11 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index 26f88215bc47..a033c4cd8e16 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -6,8 +6,6 @@
6 * Derived from drivers/mtd/nand/spia.c 6 * Derived from drivers/mtd/nand/spia.c
7 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) 7 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
8 * 8 *
9 * $Id: rtc_from4.c,v 1.10 2005/11/07 11:14:31 gleixner Exp $
10 *
11 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index b34a460ab679..556139ed1fdf 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -1,26 +1,10 @@
1/* linux/drivers/mtd/nand/s3c2410.c 1/* linux/drivers/mtd/nand/s3c2410.c
2 * 2 *
3 * Copyright (c) 2004,2005 Simtec Electronics 3 * Copyright © 2004-2008 Simtec Electronics
4 * http://www.simtec.co.uk/products/SWLINUX/ 4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@simtec.co.uk> 5 * Ben Dooks <ben@simtec.co.uk>
6 * 6 *
7 * Samsung S3C2410/S3C240 NAND driver 7 * Samsung S3C2410/S3C2440/S3C2412 NAND driver
8 *
9 * Changelog:
10 * 21-Sep-2004 BJD Initial version
11 * 23-Sep-2004 BJD Multiple device support
12 * 28-Sep-2004 BJD Fixed ECC placement for Hardware mode
13 * 12-Oct-2004 BJD Fixed errors in use of platform data
14 * 18-Feb-2005 BJD Fix sparse errors
15 * 14-Mar-2005 BJD Applied tglx's code reduction patch
16 * 02-May-2005 BJD Fixed s3c2440 support
17 * 02-May-2005 BJD Reduced hwcontrol decode
18 * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug
19 * 08-Jul-2005 BJD Fix OOPS when no platform data supplied
20 * 20-Oct-2005 BJD Fix timing calculation bug
21 * 14-Jan-2006 BJD Allow clock to be stopped when idle
22 *
23 * $Id: s3c2410.c,v 1.23 2006/04/01 18:06:29 bjd Exp $
24 * 8 *
25 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -52,6 +36,7 @@
52#include <linux/err.h> 36#include <linux/err.h>
53#include <linux/slab.h> 37#include <linux/slab.h>
54#include <linux/clk.h> 38#include <linux/clk.h>
39#include <linux/cpufreq.h>
55 40
56#include <linux/mtd/mtd.h> 41#include <linux/mtd/mtd.h>
57#include <linux/mtd/nand.h> 42#include <linux/mtd/nand.h>
@@ -120,8 +105,13 @@ struct s3c2410_nand_info {
120 int sel_bit; 105 int sel_bit;
121 int mtd_count; 106 int mtd_count;
122 unsigned long save_sel; 107 unsigned long save_sel;
108 unsigned long clk_rate;
123 109
124 enum s3c_cpu_type cpu_type; 110 enum s3c_cpu_type cpu_type;
111
112#ifdef CONFIG_CPU_FREQ
113 struct notifier_block freq_transition;
114#endif
125}; 115};
126 116
127/* conversion functions */ 117/* conversion functions */
@@ -179,17 +169,18 @@ static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
179 169
180/* controller setup */ 170/* controller setup */
181 171
182static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, 172static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
183 struct platform_device *pdev)
184{ 173{
185 struct s3c2410_platform_nand *plat = to_nand_plat(pdev); 174 struct s3c2410_platform_nand *plat = info->platform;
186 unsigned long clkrate = clk_get_rate(info->clk);
187 int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4; 175 int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
188 int tacls, twrph0, twrph1; 176 int tacls, twrph0, twrph1;
189 unsigned long cfg = 0; 177 unsigned long clkrate = clk_get_rate(info->clk);
178 unsigned long set, cfg, mask;
179 unsigned long flags;
190 180
191 /* calculate the timing information for the controller */ 181 /* calculate the timing information for the controller */
192 182
183 info->clk_rate = clkrate;
193 clkrate /= 1000; /* turn clock into kHz for ease of use */ 184 clkrate /= 1000; /* turn clock into kHz for ease of use */
194 185
195 if (plat != NULL) { 186 if (plat != NULL) {
@@ -211,28 +202,69 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
211 dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n", 202 dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
212 tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate)); 203 tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));
213 204
205 switch (info->cpu_type) {
206 case TYPE_S3C2410:
207 mask = (S3C2410_NFCONF_TACLS(3) |
208 S3C2410_NFCONF_TWRPH0(7) |
209 S3C2410_NFCONF_TWRPH1(7));
210 set = S3C2410_NFCONF_EN;
211 set |= S3C2410_NFCONF_TACLS(tacls - 1);
212 set |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
213 set |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
214 break;
215
216 case TYPE_S3C2440:
217 case TYPE_S3C2412:
218 mask = (S3C2410_NFCONF_TACLS(tacls_max - 1) |
219 S3C2410_NFCONF_TWRPH0(7) |
220 S3C2410_NFCONF_TWRPH1(7));
221
222 set = S3C2440_NFCONF_TACLS(tacls - 1);
223 set |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
224 set |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
225 break;
226
227 default:
228 /* keep compiler happy */
229 mask = 0;
230 set = 0;
231 BUG();
232 }
233
234 dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
235
236 local_irq_save(flags);
237
238 cfg = readl(info->regs + S3C2410_NFCONF);
239 cfg &= ~mask;
240 cfg |= set;
241 writel(cfg, info->regs + S3C2410_NFCONF);
242
243 local_irq_restore(flags);
244
245 return 0;
246}
247
248static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
249{
250 int ret;
251
252 ret = s3c2410_nand_setrate(info);
253 if (ret < 0)
254 return ret;
255
214 switch (info->cpu_type) { 256 switch (info->cpu_type) {
215 case TYPE_S3C2410: 257 case TYPE_S3C2410:
216 cfg = S3C2410_NFCONF_EN; 258 default:
217 cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
218 cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
219 cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
220 break; 259 break;
221 260
222 case TYPE_S3C2440: 261 case TYPE_S3C2440:
223 case TYPE_S3C2412: 262 case TYPE_S3C2412:
224 cfg = S3C2440_NFCONF_TACLS(tacls - 1);
225 cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
226 cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
227
228 /* enable the controller and de-assert nFCE */ 263 /* enable the controller and de-assert nFCE */
229 264
230 writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT); 265 writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
231 } 266 }
232 267
233 dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
234
235 writel(cfg, info->regs + S3C2410_NFCONF);
236 return 0; 268 return 0;
237} 269}
238 270
@@ -513,6 +545,52 @@ static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int
513 writesl(info->regs + S3C2440_NFDATA, buf, len / 4); 545 writesl(info->regs + S3C2440_NFDATA, buf, len / 4);
514} 546}
515 547
548/* cpufreq driver support */
549
550#ifdef CONFIG_CPU_FREQ
551
552static int s3c2410_nand_cpufreq_transition(struct notifier_block *nb,
553 unsigned long val, void *data)
554{
555 struct s3c2410_nand_info *info;
556 unsigned long newclk;
557
558 info = container_of(nb, struct s3c2410_nand_info, freq_transition);
559 newclk = clk_get_rate(info->clk);
560
561 if ((val == CPUFREQ_POSTCHANGE && newclk < info->clk_rate) ||
562 (val == CPUFREQ_PRECHANGE && newclk > info->clk_rate)) {
563 s3c2410_nand_setrate(info);
564 }
565
566 return 0;
567}
568
569static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
570{
571 info->freq_transition.notifier_call = s3c2410_nand_cpufreq_transition;
572
573 return cpufreq_register_notifier(&info->freq_transition,
574 CPUFREQ_TRANSITION_NOTIFIER);
575}
576
577static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
578{
579 cpufreq_unregister_notifier(&info->freq_transition,
580 CPUFREQ_TRANSITION_NOTIFIER);
581}
582
583#else
584static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
585{
586 return 0;
587}
588
589static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
590{
591}
592#endif
593
516/* device management functions */ 594/* device management functions */
517 595
518static int s3c2410_nand_remove(struct platform_device *pdev) 596static int s3c2410_nand_remove(struct platform_device *pdev)
@@ -524,9 +602,10 @@ static int s3c2410_nand_remove(struct platform_device *pdev)
524 if (info == NULL) 602 if (info == NULL)
525 return 0; 603 return 0;
526 604
527 /* first thing we need to do is release all our mtds 605 s3c2410_nand_cpufreq_deregister(info);
528 * and their partitions, then go through freeing the 606
529 * resources used 607 /* Release all our mtds and their partitions, then go through
608 * freeing the resources used
530 */ 609 */
531 610
532 if (info->mtds != NULL) { 611 if (info->mtds != NULL) {
@@ -691,7 +770,8 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
691{ 770{
692 struct nand_chip *chip = &nmtd->chip; 771 struct nand_chip *chip = &nmtd->chip;
693 772
694 printk("%s: chip %p: %d\n", __func__, chip, chip->page_shift); 773 dev_dbg(info->device, "chip %p => page shift %d\n",
774 chip, chip->page_shift);
695 775
696 if (hardware_ecc) { 776 if (hardware_ecc) {
697 /* change the behaviour depending on wether we are using 777 /* change the behaviour depending on wether we are using
@@ -784,7 +864,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
784 864
785 /* initialise the hardware */ 865 /* initialise the hardware */
786 866
787 err = s3c2410_nand_inithw(info, pdev); 867 err = s3c2410_nand_inithw(info);
788 if (err != 0) 868 if (err != 0)
789 goto exit_error; 869 goto exit_error;
790 870
@@ -827,6 +907,12 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
827 sets++; 907 sets++;
828 } 908 }
829 909
910 err = s3c2410_nand_cpufreq_register(info);
911 if (err < 0) {
912 dev_err(&pdev->dev, "failed to init cpufreq support\n");
913 goto exit_error;
914 }
915
830 if (allow_clk_stop(info)) { 916 if (allow_clk_stop(info)) {
831 dev_info(&pdev->dev, "clock idle support enabled\n"); 917 dev_info(&pdev->dev, "clock idle support enabled\n");
832 clk_disable(info->clk); 918 clk_disable(info->clk);
@@ -874,7 +960,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
874 960
875 if (info) { 961 if (info) {
876 clk_enable(info->clk); 962 clk_enable(info->clk);
877 s3c2410_nand_inithw(info, dev); 963 s3c2410_nand_inithw(info);
878 964
879 /* Restore the state of the nFCE line. */ 965 /* Restore the state of the nFCE line. */
880 966
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 033f8800b1e6..6dba2fb66ae5 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -3,8 +3,6 @@
3 * 3 *
4 * Copyright (C) 2004 Richard Purdie 4 * Copyright (C) 2004 Richard Purdie
5 * 5 *
6 * $Id: sharpsl.c,v 1.7 2005/11/07 11:14:31 gleixner Exp $
7 *
8 * Based on Sharp's NAND driver sharp_sl.c 6 * Based on Sharp's NAND driver sharp_sl.c
9 * 7 *
10 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c
index 1f6d429b1583..0cc6d0acb8fe 100644
--- a/drivers/mtd/nand/spia.c
+++ b/drivers/mtd/nand/spia.c
@@ -8,8 +8,6 @@
8 * to controllines (due to change in nand.c) 8 * to controllines (due to change in nand.c)
9 * page_cache added 9 * page_cache added
10 * 10 *
11 * $Id: spia.c,v 1.25 2005/11/07 11:14:31 gleixner Exp $
12 *
13 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation. 13 * published by the Free Software Foundation.
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c
index f9e2d4a0ab8c..bbf492e6830d 100644
--- a/drivers/mtd/nand/toto.c
+++ b/drivers/mtd/nand/toto.c
@@ -14,8 +14,6 @@
14 * Overview: 14 * Overview:
15 * This is a device driver for the NAND flash device found on the 15 * This is a device driver for the NAND flash device found on the
16 * TI fido board. It supports 32MiB and 64MiB cards 16 * TI fido board. It supports 32MiB and 64MiB cards
17 *
18 * $Id: toto.c,v 1.5 2005/11/07 11:14:31 gleixner Exp $
19 */ 17 */
20 18
21#include <linux/slab.h> 19#include <linux/slab.h>
diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c
index f40081069ab2..807a72752eeb 100644
--- a/drivers/mtd/nand/ts7250.c
+++ b/drivers/mtd/nand/ts7250.c
@@ -9,8 +9,6 @@
9 * Derived from drivers/mtd/nand/autcpu12.c 9 * Derived from drivers/mtd/nand/autcpu12.c
10 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) 10 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
11 * 11 *
12 * $Id: ts7250.c,v 1.4 2004/12/30 22:02:07 joff Exp $
13 *
14 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as 13 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation. 14 * published by the Free Software Foundation.