summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/flash.patch
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap2-git/beagleboard/flash.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadpoky-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap2-git/beagleboard/flash.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap2-git/beagleboard/flash.patch558
1 files changed, 558 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/flash.patch b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/flash.patch
new file mode 100644
index 0000000000..4c76cd97bd
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/flash.patch
@@ -0,0 +1,558 @@
1diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
2index 13d0043..d582b8f 100644
3--- a/arch/arm/mach-omap2/Makefile
4+++ b/arch/arm/mach-omap2/Makefile
5@@ -44,7 +44,8 @@ obj-$(CONFIG_MACH_OMAP3EVM) += board-omap3evm.o \
6 board-omap3evm-flash.o
7 obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \
8 usb-musb.o usb-ehci.o \
9- hsmmc.o
10+ hsmmc.o \
11+ board-omap3beagle-flash.o
12 obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o \
13 hsmmc.o \
14 usb-musb.o
15diff --git a/arch/arm/mach-omap2/board-omap3beagle-flash.c b/arch/arm/mach-omap2/board-omap3beagle-flash.c
16new file mode 100644
17index 0000000..5346df0
18--- /dev/null
19+++ b/arch/arm/mach-omap2/board-omap3beagle-flash.c
20@@ -0,0 +1,119 @@
21+/*
22+ * board-omap3beagle-flash.c
23+ *
24+ * Copyright (c) 2008 Texas Instruments
25+ *
26+ * Modified from board-omap3evm-flash.c
27+ *
28+ * This program is free software; you can redistribute it and/or modify
29+ * it under the terms of the GNU General Public License version 2 as
30+ * published by the Free Software Foundation.
31+ */
32+
33+#include <linux/kernel.h>
34+#include <linux/platform_device.h>
35+#include <linux/mtd/mtd.h>
36+#include <linux/mtd/partitions.h>
37+#include <linux/mtd/nand.h>
38+#include <linux/types.h>
39+#include <linux/io.h>
40+
41+#include <asm/mach/flash.h>
42+#include <asm/arch/board.h>
43+#include <asm/arch/gpmc.h>
44+#include <asm/arch/nand.h>
45+
46+#define GPMC_CS0_BASE 0x60
47+#define GPMC_CS_SIZE 0x30
48+
49+static struct mtd_partition omap3beagle_nand_partitions[] = {
50+ /* All the partition sizes are listed in terms of NAND block size */
51+ {
52+ .name = "X-Loader",
53+ .offset = 0,
54+ .size = 4*(64 * 2048),
55+ .mask_flags = MTD_WRITEABLE, /* force read-only */
56+ },
57+ {
58+ .name = "U-Boot",
59+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
60+ .size = 15*(64 * 2048),
61+ .mask_flags = MTD_WRITEABLE, /* force read-only */
62+ },
63+ {
64+ .name = "U-Boot Env",
65+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x260000 */
66+ .size = 1*(64 * 2048),
67+ },
68+ {
69+ .name = "Kernel",
70+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */
71+ .size = 32*(64 * 2048),
72+ },
73+ {
74+ .name = "File System",
75+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */
76+ .size = MTDPART_SIZ_FULL,
77+ },
78+};
79+
80+static struct omap_nand_platform_data omap3beagle_nand_data = {
81+ .parts = omap3beagle_nand_partitions,
82+ .nr_parts = ARRAY_SIZE(omap3beagle_nand_partitions),
83+ .dma_channel = -1, /* disable DMA in OMAP NAND driver */
84+ .nand_setup = NULL,
85+ .dev_ready = NULL,
86+};
87+
88+static struct resource omap3beagle_nand_resource = {
89+ .flags = IORESOURCE_MEM,
90+};
91+
92+static struct platform_device omap3beagle_nand_device = {
93+ .name = "omap2-nand",
94+ .id = -1,
95+ .dev = {
96+ .platform_data = &omap3beagle_nand_data,
97+ },
98+ .num_resources = 1,
99+ .resource = &omap3beagle_nand_resource,
100+};
101+
102+
103+void __init omap3beagle_flash_init(void)
104+{
105+ u8 cs = 0;
106+ u8 nandcs = GPMC_CS_NUM + 1;
107+
108+ u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
109+
110+ /* find out the chip-select on which NAND exists */
111+ while (cs < GPMC_CS_NUM) {
112+ u32 ret = 0;
113+ ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
114+
115+ if ((ret & 0xC00) == 0x800) {
116+ printk(KERN_INFO "Found NAND on CS%d\n", cs);
117+ if (nandcs > GPMC_CS_NUM)
118+ nandcs = cs;
119+ }
120+ cs++;
121+ }
122+
123+ if (nandcs > GPMC_CS_NUM) {
124+ printk(KERN_INFO "NAND: Unable to find configuration "
125+ "in GPMC\n ");
126+ return;
127+ }
128+
129+ if (nandcs < GPMC_CS_NUM) {
130+ omap3beagle_nand_data.cs = nandcs;
131+ omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)(gpmc_base_add +
132+ GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
133+ omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
134+
135+ printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
136+ if (platform_device_register(&omap3beagle_nand_device) < 0)
137+ printk(KERN_ERR "Unable to register NAND device\n");
138+ }
139+}
140diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
141index c992cc7..99e042e 100644
142--- a/arch/arm/mach-omap2/board-omap3beagle.c
143+++ b/arch/arm/mach-omap2/board-omap3beagle.c
144@@ -94,6 +94,7 @@ static void __init omap3_beagle_init(void)
145 hsmmc_init();
146 usb_musb_init();
147 usb_ehci_init();
148+ omap3beagle_flash_init();
149 }
150
151 arch_initcall(omap3_beagle_i2c_init);
152diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
153index 3d5e432..02b9ced 100644
154--- a/drivers/mtd/nand/Kconfig
155+++ b/drivers/mtd/nand/Kconfig
156@@ -71,7 +71,7 @@ config MTD_NAND_AMS_DELTA
157
158 config MTD_NAND_OMAP2
159 tristate "NAND Flash device on OMAP 2420H4/2430SDP boards"
160- depends on (ARM && ARCH_OMAP2 && MTD_NAND)
161+ depends on ARM && MTD_NAND && (ARCH_OMAP2 || ARCH_OMAP3)
162 help
163 Support for NAND flash on Texas Instruments 2430SDP/2420H4 platforms.
164
165diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
166index 3b7307c..3aac1d2 100644
167--- a/drivers/mtd/nand/omap2.c
168+++ b/drivers/mtd/nand/omap2.c
169@@ -111,15 +111,6 @@
170 static const char *part_probes[] = { "cmdlinepart", NULL };
171 #endif
172
173-static int hw_ecc = 1;
174-
175-/* new oob placement block for use with hardware ecc generation */
176-static struct nand_ecclayout omap_hw_eccoob = {
177- .eccbytes = 12,
178- .eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
179- .oobfree = {{16, 32}, {33, 63} },
180-};
181-
182 struct omap_nand_info {
183 struct nand_hw_control controller;
184 struct omap_nand_platform_data *pdata;
185@@ -133,6 +124,13 @@ struct omap_nand_info {
186 void __iomem *gpmc_cs_baseaddr;
187 void __iomem *gpmc_baseaddr;
188 };
189+
190+/*
191+ * omap_nand_wp - This function enable or disable the Write Protect feature on
192+ * NAND device
193+ * @mtd: MTD device structure
194+ * @mode: WP ON/OFF
195+ */
196 static void omap_nand_wp(struct mtd_info *mtd, int mode)
197 {
198 struct omap_nand_info *info = container_of(mtd,
199@@ -189,11 +187,11 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
200 }
201
202 /*
203-* omap_read_buf - read data from NAND controller into buffer
204-* @mtd: MTD device structure
205-* @buf: buffer to store date
206-* @len: number of bytes to read
207-*/
208+ * omap_read_buf - read data from NAND controller into buffer
209+ * @mtd: MTD device structure
210+ * @buf: buffer to store date
211+ * @len: number of bytes to read
212+ */
213 static void omap_read_buf(struct mtd_info *mtd, u_char *buf, int len)
214 {
215 struct omap_nand_info *info = container_of(mtd,
216@@ -207,11 +205,11 @@ static void omap_read_buf(struct mtd_info *mtd, u_char *buf, int len)
217 }
218
219 /*
220-* omap_write_buf - write buffer to NAND controller
221-* @mtd: MTD device structure
222-* @buf: data buffer
223-* @len: number of bytes to write
224-*/
225+ * omap_write_buf - write buffer to NAND controller
226+ * @mtd: MTD device structure
227+ * @buf: data buffer
228+ * @len: number of bytes to write
229+ */
230 static void omap_write_buf(struct mtd_info *mtd, const u_char * buf, int len)
231 {
232 struct omap_nand_info *info = container_of(mtd,
233@@ -250,10 +248,16 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
234 return 0;
235 }
236
237+#ifdef CONFIG_MTD_NAND_OMAP_HWECC
238+/*
239+ * omap_hwecc_init-Initialize the Hardware ECC for NAND flash in GPMC controller
240+ * @mtd: MTD device structure
241+ */
242 static void omap_hwecc_init(struct mtd_info *mtd)
243 {
244 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
245 mtd);
246+ register struct nand_chip *chip = mtd->priv;
247 unsigned long val = 0x0;
248
249 /* Read from ECC Control Register */
250@@ -264,16 +268,15 @@ static void omap_hwecc_init(struct mtd_info *mtd)
251
252 /* Read from ECC Size Config Register */
253 val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
254- /* ECCSIZE1=512 | ECCSIZE0=8bytes | Select eccResultsize[0123] */
255- val = ((0x000000FF<<22) | (0x00000003<<12) | (0x0000000F));
256+ /* ECCSIZE1=512 | Select eccResultsize[0-3] */
257+ val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F));
258 __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
259-
260-
261 }
262
263 /*
264- * This function will generate true ECC value, which can be used
265+ * gen_true_ecc - This function will generate true ECC value, which can be used
266 * when correcting data read from NAND flash memory core
267+ * @ecc_buf: buffer to store ecc code
268 */
269 static void gen_true_ecc(u8 *ecc_buf)
270 {
271@@ -289,8 +292,12 @@ static void gen_true_ecc(u8 *ecc_buf)
272 }
273
274 /*
275- * This function compares two ECC's and indicates if there is an error.
276- * If the error can be corrected it will be corrected to the buffer
277+ * omap_compare_ecc - This function compares two ECC's and indicates if there
278+ * is an error. If the error can be corrected it will be corrected to the
279+ * buffer
280+ * @ecc_data1: ecc code from nand spare area
281+ * @ecc_data2: ecc code from hardware register obtained from hardware ecc
282+ * @page_data: page data
283 */
284 static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
285 u8 *ecc_data2, /* read from register */
286@@ -409,6 +416,14 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
287 }
288 }
289
290+/*
291+ * omap_correct_data - Compares the ecc read from nand spare area with ECC
292+ * registers values and corrects one bit error if it has occured
293+ * @mtd: MTD device structure
294+ * @dat: page data
295+ * @read_ecc: ecc read from nand flash
296+ * @calc_ecc: ecc read from ECC registers
297+ */
298 static int omap_correct_data(struct mtd_info *mtd, u_char * dat,
299 u_char * read_ecc, u_char * calc_ecc)
300 {
301@@ -436,65 +451,64 @@ static int omap_correct_data(struct mtd_info *mtd, u_char * dat,
302 }
303
304 /*
305-** Generate non-inverted ECC bytes.
306-**
307-** Using noninverted ECC can be considered ugly since writing a blank
308-** page ie. padding will clear the ECC bytes. This is no problem as long
309-** nobody is trying to write data on the seemingly unused page.
310-**
311-** Reading an erased page will produce an ECC mismatch between
312-** generated and read ECC bytes that has to be dealt with separately.
313-*/
314+ * omap_calcuate_ecc - Generate non-inverted ECC bytes.
315+ * Using noninverted ECC can be considered ugly since writing a blank
316+ * page ie. padding will clear the ECC bytes. This is no problem as long
317+ * nobody is trying to write data on the seemingly unused page. Reading
318+ * an erased page will produce an ECC mismatch between generated and read
319+ * ECC bytes that has to be dealt with separately.
320+ * @mtd: MTD device structure
321+ * @dat: The pointer to data on which ecc is computed
322+ * @ecc_code: The ecc_code buffer
323+ */
324 static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
325 u_char *ecc_code)
326 {
327 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
328 mtd);
329 unsigned long val = 0x0;
330- unsigned long reg, n;
331-
332- /* Ex NAND_ECC_HW12_2048 */
333- if ((info->nand.ecc.mode == NAND_ECC_HW) &&
334- (info->nand.ecc.size == 2048))
335- n = 4;
336- else
337- n = 1;
338+ unsigned long reg;
339
340 /* Start Reading from HW ECC1_Result = 0x200 */
341 reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT);
342- while (n--) {
343- val = __raw_readl(reg);
344- *ecc_code++ = val; /* P128e, ..., P1e */
345- *ecc_code++ = val >> 16; /* P128o, ..., P1o */
346- /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
347- *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
348- reg += 4;
349- }
350+ val = __raw_readl(reg);
351+ *ecc_code++ = val; /* P128e, ..., P1e */
352+ *ecc_code++ = val >> 16; /* P128o, ..., P1o */
353+ /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
354+ *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
355+ reg += 4;
356
357 return 0;
358-} /* omap_calculate_ecc */
359+}
360
361+/*
362+ * omap_enable_hwecc - This function enables the hardware ecc functionality
363+ * @mtd: MTD device structure
364+ * @mode: Read/Write mode
365+ */
366 static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
367 {
368 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
369 mtd);
370+ register struct nand_chip *chip = mtd->priv;
371+ unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
372 unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG);
373
374 switch (mode) {
375 case NAND_ECC_READ :
376 __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
377- /* ECC 16 bit col) | ( CS 0 ) | ECC Enable */
378- val = (1 << 7) | (0x0) | (0x1) ;
379+ /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
380+ val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
381 break;
382 case NAND_ECC_READSYN :
383- __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
384- /* ECC 16 bit col) | ( CS 0 ) | ECC Enable */
385- val = (1 << 7) | (0x0) | (0x1) ;
386+ __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
387+ /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
388+ val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
389 break;
390 case NAND_ECC_WRITE :
391 __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
392- /* ECC 16 bit col) | ( CS 0 ) | ECC Enable */
393- val = (1 << 7) | (0x0) | (0x1) ;
394+ /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
395+ val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
396 break;
397 default:
398 DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n",
399@@ -504,7 +518,38 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
400
401 __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
402 }
403+#endif
404
405+/*
406+ * omap_wait - Wait function is called during Program and erase
407+ * operations and the way it is called from MTD layer, we should wait
408+ * till the NAND chip is ready after the programming/erase operation
409+ * has completed.
410+ * @mtd: MTD device structure
411+ * @chip: NAND Chip structure
412+ */
413+static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
414+{
415+ register struct nand_chip *this = mtd->priv;
416+ struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
417+ mtd);
418+ int status = 0;
419+
420+ this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr +
421+ GPMC_CS_NAND_COMMAND;
422+ this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA;
423+
424+ while (!(status & 0x40)) {
425+ __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
426+ status = __raw_readb(this->IO_ADDR_R);
427+ }
428+ return status;
429+}
430+
431+/*
432+ * omap_dev_ready - calls the platform specific dev_ready function
433+ * @mtd: MTD device structure
434+ */
435 static int omap_dev_ready(struct mtd_info *mtd)
436 {
437 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
438@@ -534,7 +579,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
439 struct omap_nand_info *info;
440 struct omap_nand_platform_data *pdata;
441 int err;
442- unsigned long val;
443+ unsigned long val;
444
445
446 pdata = pdev->dev.platform_data;
447@@ -568,15 +613,20 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
448 }
449
450 /* Enable RD PIN Monitoring Reg */
451- val = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1);
452- val |= WR_RD_PIN_MONITORING;
453- gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG1, val);
454+ if (pdata->dev_ready) {
455+ val = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1);
456+ val |= WR_RD_PIN_MONITORING;
457+ gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG1, val);
458+ }
459
460 val = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG7);
461 val &= ~(0xf << 8);
462 val |= (0xc & 0xf) << 8;
463 gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG7, val);
464
465+ /* NAND write protect off */
466+ omap_nand_wp(&info->mtd, NAND_WP_OFF);
467+
468 if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
469 pdev->dev.driver->name)) {
470 err = -EBUSY;
471@@ -597,29 +647,39 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
472 info->nand.write_buf = omap_write_buf;
473 info->nand.verify_buf = omap_verify_buf;
474
475- info->nand.dev_ready = omap_dev_ready;
476- info->nand.chip_delay = 0;
477-
478- /* Options */
479- info->nand.options = NAND_BUSWIDTH_16;
480- info->nand.options |= NAND_SKIP_BBTSCAN;
481-
482- if (hw_ecc) {
483- /* init HW ECC */
484- omap_hwecc_init(&info->mtd);
485-
486- info->nand.ecc.calculate = omap_calculate_ecc;
487- info->nand.ecc.hwctl = omap_enable_hwecc;
488- info->nand.ecc.correct = omap_correct_data;
489- info->nand.ecc.mode = NAND_ECC_HW;
490- info->nand.ecc.bytes = 12;
491- info->nand.ecc.size = 2048;
492- info->nand.ecc.layout = &omap_hw_eccoob;
493-
494+ /*
495+ * If RDY/BSY line is connected to OMAP then use the omap ready funcrtion
496+ * and the generic nand_wait function which reads the status register
497+ * after monitoring the RDY/BSY line.Otherwise use a standard chip delay
498+ * which is slightly more than tR (AC Timing) of the NAND device and read
499+ * status register until you get a failure or success
500+ */
501+ if (pdata->dev_ready) {
502+ info->nand.dev_ready = omap_dev_ready;
503+ info->nand.chip_delay = 0;
504 } else {
505- info->nand.ecc.mode = NAND_ECC_SOFT;
506+ info->nand.waitfunc = omap_wait;
507+ info->nand.chip_delay = 50;
508 }
509
510+ info->nand.options |= NAND_SKIP_BBTSCAN;
511+ if ((gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1) & 0x3000)
512+ == 0x1000)
513+ info->nand.options |= NAND_BUSWIDTH_16;
514+
515+#ifdef CONFIG_MTD_NAND_OMAP_HWECC
516+ info->nand.ecc.bytes = 3;
517+ info->nand.ecc.size = 512;
518+ info->nand.ecc.calculate = omap_calculate_ecc;
519+ info->nand.ecc.hwctl = omap_enable_hwecc;
520+ info->nand.ecc.correct = omap_correct_data;
521+ info->nand.ecc.mode = NAND_ECC_HW;
522+
523+ /* init HW ECC */
524+ omap_hwecc_init(&info->mtd);
525+#else
526+ info->nand.ecc.mode = NAND_ECC_SOFT;
527+#endif
528
529 /* DIP switches on some boards change between 8 and 16 bit
530 * bus widths for flash. Try the other width if the first try fails.
531@@ -636,14 +696,12 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
532 err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
533 if (err > 0)
534 add_mtd_partitions(&info->mtd, info->parts, err);
535- else if (err < 0 && pdata->parts)
536+ else if (err <= 0 && pdata->parts)
537 add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
538 else
539 #endif
540 add_mtd_device(&info->mtd);
541
542- omap_nand_wp(&info->mtd, NAND_WP_OFF);
543-
544 platform_set_drvdata(pdev, &info->mtd);
545
546 return 0;
547diff --git a/include/asm-arm/arch-omap/board-omap3beagle.h b/include/asm-arm/arch-omap/board-omap3beagle.h
548index 46dff31..26ecfb8 100644
549--- a/include/asm-arm/arch-omap/board-omap3beagle.h
550+++ b/include/asm-arm/arch-omap/board-omap3beagle.h
551@@ -29,5 +29,7 @@
552 #ifndef __ASM_ARCH_OMAP3_BEAGLE_H
553 #define __ASM_ARCH_OMAP3_BEAGLE_H
554
555+extern void omap3beagle_flash_init(void);
556+
557 #endif /* __ASM_ARCH_OMAP3_BEAGLE_H */
558