Browse Source

Update of new NAND code
Patch by Ladislav Michl, 13 Sep 2005

Wolfgang Denk 19 years ago
parent
commit
ac7eb8a315

+ 12 - 0
Makefile

@@ -118,6 +118,7 @@ LIBS += disk/libdisk.a
 LIBS += rtc/librtc.a
 LIBS += rtc/librtc.a
 LIBS += dtt/libdtt.a
 LIBS += dtt/libdtt.a
 LIBS += drivers/libdrivers.a
 LIBS += drivers/libdrivers.a
+LIBS += drivers/nand/libnand.a
 LIBS += drivers/sk98lin/libsk98lin.a
 LIBS += drivers/sk98lin/libsk98lin.a
 LIBS += post/libpost.a post/cpu/libcpu.a
 LIBS += post/libpost.a post/cpu/libcpu.a
 LIBS += common/libcommon.a
 LIBS += common/libcommon.a
@@ -1391,6 +1392,17 @@ mx1ads_config	:	unconfig
 mx1fs2_config	:	unconfig
 mx1fs2_config	:	unconfig
 	@./mkconfig $(@:_config=) arm arm920t mx1fs2 NULL imx
 	@./mkconfig $(@:_config=) arm arm920t mx1fs2 NULL imx
 
 
+netstar_32_config	\
+netstar_config:		unconfig
+	@if [ "$(findstring _32_,$@)" ] ; then \
+		echo "... 32MB SDRAM" ; \
+		echo "#define PHYS_SDRAM_1_SIZE SZ_32M" >>include/config.h ; \
+	else \
+		echo "... 64MB SDRAM" ; \
+		echo "#define PHYS_SDRAM_1_SIZE SZ_64M" >>include/config.h ; \
+	fi
+	@./mkconfig -a netstar arm arm925t netstar
+
 omap1510inn_config :	unconfig
 omap1510inn_config :	unconfig
 	@./mkconfig $(@:_config=) arm arm925t omap1510inn
 	@./mkconfig $(@:_config=) arm arm925t omap1510inn
 
 

+ 85 - 0
board/netstar/Makefile

@@ -0,0 +1,85 @@
+#
+# (C) Copyright 2005
+# Ladislav Michl, 2N Telekomunikace, michl@2n.cz
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= lib$(BOARD).a
+
+OBJS	:= netstar.o flash.o nand.o
+SOBJS	:= setup.o crcek.o
+
+gcclibdir := $(shell dirname `$(CC) -print-libgcc-file-name`)
+
+LOAD_ADDR = 0x10400000
+LDSCRIPT = $(TOPDIR)/board/$(BOARDDIR)/eeprom.lds
+
+HOST_CFLAGS = -Wall -pedantic -I$(TOPDIR)/include
+
+all:	$(LIB) eeprom.srec eeprom.bin crcek.srec crcek.bin crcit
+
+$(LIB):	$(OBJS) $(SOBJS)
+	$(AR) crv $@ $^
+
+eeprom.srec:	eeprom.o eeprom_start.o
+	$(LD) -T $(LDSCRIPT) -g -Ttext $(LOAD_ADDR) \
+		-o $(<:.o=) -e $(<:.o=) $^ \
+		-L../../examples -lstubs \
+		-L../../lib_generic -lgeneric \
+		-L$(gcclibdir) -lgcc
+	$(OBJCOPY) -O srec $(<:.o=) $@
+
+eeprom.bin:	eeprom.srec
+	$(OBJCOPY) -I srec -O binary $< $@ 2>/dev/null
+
+crcek.srec:	crcek.o
+	$(LD) -g -Ttext 0x00000000 \
+		-o $(<:.o=) -e $(<:.o=) $^
+	$(OBJCOPY) -O srec $(<:.o=) $@
+
+crcek.bin:	crcek.srec
+	$(OBJCOPY) -I srec -O binary $< $@ 2>/dev/null
+
+crcit:		crcit.o crc32.o
+	$(HOSTCC) $(HOST_CFLAGS) -o $@ $^
+
+crcit.o:	crcit.c
+	$(HOSTCC) $(HOST_CFLAGS) -c $<
+
+crc32.o:	$(TOPDIR)/tools/crc32.c
+	$(HOSTCC) $(HOST_CFLAGS) -DUSE_HOSTCC -c $<
+
+clean:
+	rm -f $(SOBJS) $(OBJS) eeprom eeprom.srec eeprom.bin \
+		crcek crcek.srec crcek.bin
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+		$(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+-include .depend
+
+#########################################################################

+ 11 - 0
board/netstar/config.mk

@@ -0,0 +1,11 @@
+#
+# Linux-Kernel is expected to be at 1000'8000,
+# entry 1000'8000 (mem base + reserved)
+#
+# We load ourself to internal RAM at 2001'2000
+# Check map file when changing TEXT_BASE.
+# Everything has fit into 192kB internal SRAM!
+#
+
+# XXX TEXT_BASE = 0x20012000
+TEXT_BASE = 0x13FC0000

+ 177 - 0
board/netstar/crcek.S

@@ -0,0 +1,177 @@
+/**
+ * (C) Copyright 2005
+ * 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2.
+ *
+ * Image layout looks like following:
+ *	u32 - size
+ *	u32 - version
+ *	... - data
+ *	u32 - crc32
+ */
+
+#include "crcek.h"
+
+/**
+ * do_crc32 - calculate CRC32 of given buffer
+ * r0 - crc
+ * r1 - pointer to buffer
+ * r2 - buffer len
+ */
+	.macro	do_crc32
+	ldr	r5, FFFFFFFF
+	eor	r0, r0, r5
+	adr	r3, CRC32_TABLE
+1:
+	ldrb    r4, [r1], #1
+	eor	r4, r4, r0
+	and	r4, r4, #0xff
+	ldr	r4, [r3, r4, lsl#2]
+	eor	r0, r4, r0, lsr#8
+	subs	r2, r2, #0x1
+	bne 	1b
+	eor	r0, r0, r5
+	.endm
+
+	.macro crcuj, offset, size
+	mov	r0, #0
+	ldr	r1, \offset
+	ldr	r2, [r1]
+	cmp	r2, r0		@ no data, no problem
+	beq	2f
+	tst	r2, #3		@ unaligned size
+	bne	2f
+	ldr	r3, \size
+	cmp	r2, r3		@ bogus size
+	bhi	2f
+	add	r1, r1, #4
+	do_crc32
+	ldr	r1, [r1]
+2:
+	cmp	r0, r1
+	.endm
+
+	.macro wait, reg
+	mov	\reg, #0x1000
+3:
+	subs	\reg, \reg, #0x1
+	bne 	3b
+
+	.endm
+.text
+.globl crcek
+crcek:
+	b	crc2_bad
+	mov	r6, #0
+	crcuj	_LOADER1_OFFSET, _LOADER_SIZE
+	bne	crc1_bad
+	orr	r6, r6, #1
+crc1_bad:
+	crcuj	_LOADER2_OFFSET, _LOADER_SIZE
+	bne	crc2_bad
+	orr	r6, r6, #2
+crc2_bad:
+	ldr	r3, _LOADER1_OFFSET
+	ldr	r4, _LOADER2_OFFSET
+	b	boot_2nd
+	tst	r6, #3
+	beq	one_is_bad	@ one of them (or both) has bad crc
+	ldr	r1, [r3, #4]
+	ldr	r2, [r4, #4]
+	cmp	r1, r2		@ boot 2nd loader if versions differ
+	beq	boot_1st
+	b	boot_2nd
+one_is_bad:
+	tst	r6, #1
+	bne	boot_1st
+	tst	r6, #2
+	bne	boot_2nd
+@ We are doomed, so let user know.
+	ldr	r0, GPIO_BASE	@ configure GPIO pins
+	ldr	r1, GPIO_DIRECTION
+	strh	r1, [r0, #0x08]
+blink_loop:
+	mov	r1, #0x08
+	strh    r1, [r0, #0x04]
+	wait	r3
+	mov	r1, #0x10
+	strh    r1, [r0, #0x04]
+	wait	r3
+	b blink_loop
+boot_1st:
+	add	pc, r3, #8
+boot_2nd:
+	add	pc, r4, #8
+
+_LOADER_SIZE:
+	.word LOADER_SIZE - 8	@ minus size and crc32
+_LOADER1_OFFSET:
+	.word LOADER1_OFFSET
+_LOADER2_OFFSET:
+	.word LOADER2_OFFSET
+
+FFFFFFFF:
+	.word 0xffffffff
+CRC32_TABLE:
+	.word 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419
+	.word 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4
+	.word 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07
+	.word 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de
+	.word 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856
+	.word 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9
+	.word 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4
+	.word 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b
+	.word 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3
+	.word 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a
+	.word 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599
+	.word 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924
+	.word 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190
+	.word 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f
+	.word 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e
+	.word 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01
+	.word 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed
+	.word 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950
+	.word 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3
+	.word 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2
+	.word 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a
+	.word 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5
+	.word 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010
+	.word 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f
+	.word 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17
+	.word 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6
+	.word 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615
+	.word 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8
+	.word 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344
+	.word 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb
+	.word 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a
+	.word 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5
+	.word 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1
+	.word 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c
+	.word 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef
+	.word 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236
+	.word 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe
+	.word 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31
+	.word 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c
+	.word 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713
+	.word 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b
+	.word 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242
+	.word 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1
+	.word 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c
+	.word 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278
+	.word 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7
+	.word 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66
+	.word 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9
+	.word 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605
+	.word 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8
+	.word 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b
+	.word 0x2d02ef8d
+
+GPIO_BASE:
+	.word 0xfffce000
+GPIO_DIRECTION:
+	.word 0x0000ffe7
+
+.end

+ 3 - 0
board/netstar/crcek.h

@@ -0,0 +1,3 @@
+#define LOADER_SIZE	(448 * 1024)
+#define LOADER1_OFFSET	(128 * 1024)
+#define LOADER2_OFFSET	(LOADER1_OFFSET + LOADER_SIZE)

+ 86 - 0
board/netstar/crcit.c

@@ -0,0 +1,86 @@
+/*
+ * (C) Copyright 2005
+ * 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "crcek.h"
+
+extern unsigned long crc32(unsigned long, const unsigned char *, unsigned int);
+
+uint32_t data[LOADER_SIZE/4 + 3];
+
+int doit(char *path, unsigned version)
+{
+	uint32_t *p;
+	ssize_t size;
+	int fd;
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1) {
+		perror("Error opening file");
+		return EXIT_FAILURE;
+	}
+	p = data + 2;
+	size = read(fd, p, LOADER_SIZE + 4);
+	if (size == -1) {
+		perror("Error reading file");
+		return EXIT_FAILURE;
+	}
+	if (size > LOADER_SIZE) {
+		fprintf(stderr, "File too large\n");
+		return EXIT_FAILURE;
+	}
+	size = (((size - 1) >> 2) + 1) << 2;
+	data[0] = size + 4;	/* add size of version field */
+	data[1] = version;
+	data[(size >> 2) + 2] = crc32(0, (unsigned char *)(data + 1), data[0]);
+	close(fd);
+
+	if (write(STDOUT_FILENO, data, size + 3*4) == -1) {
+		perror("Error writing file");
+		return EXIT_FAILURE;
+	}
+
+	return EXIT_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+	if (argc == 2) {
+		return doit(argv[1], 0);
+	} else if ((argc == 4) && (strcmp(argv[1], "-v") == 0)) {
+		char *endptr, *nptr = argv[2];
+		unsigned ver = strtoul(nptr, &endptr, 0);
+		if (nptr != '\0' && endptr == '\0')
+			return doit(argv[3], ver);
+	}
+	fprintf(stderr, "Usage: crcit [-v version] <image>\n");
+
+	return EXIT_FAILURE;
+}

+ 215 - 0
board/netstar/eeprom.c

@@ -0,0 +1,215 @@
+/*
+ * (C) Copyright 2005
+ * Ladislav Michl, 2N Telekomunikace, michl@2n.cz
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Some code shamelessly stolen back from Robin Getz.
+ */
+
+#define DEBUG
+
+#include <common.h>
+#include <exports.h>
+#include "../drivers/smc91111.h"
+
+#define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE
+
+static u16 read_eeprom_reg(u16 reg)
+{
+	int timeout;
+
+	SMC_SELECT_BANK(2);
+	SMC_outw(reg, PTR_REG);
+
+	SMC_SELECT_BANK(1);
+	SMC_outw(SMC_inw (CTL_REG) | CTL_EEPROM_SELECT | CTL_RELOAD,
+		 CTL_REG);
+	timeout = 100;
+	while((SMC_inw (CTL_REG) & CTL_RELOAD) && --timeout)
+		udelay(100);
+	if (timeout == 0) {
+		printf("Timeout Reading EEPROM register %02x\n", reg);
+		return 0;
+	}
+
+	return SMC_inw (GP_REG);
+}
+
+static int write_eeprom_reg(u16 value, u16 reg)
+{
+	int timeout;
+
+	SMC_SELECT_BANK(2);
+	SMC_outw(reg, PTR_REG);
+
+	SMC_SELECT_BANK(1);
+	SMC_outw(value, GP_REG);
+	SMC_outw(SMC_inw (CTL_REG) | CTL_EEPROM_SELECT | CTL_STORE, CTL_REG);
+	timeout = 100;
+	while ((SMC_inw(CTL_REG) & CTL_STORE) && --timeout)
+		udelay (100);
+	if (timeout == 0) {
+		printf("Timeout Writing EEPROM register %02x\n", reg);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int write_data(u16 *buf, int len)
+{
+	u16 reg = 0x23;
+
+	while (len--)
+		write_eeprom_reg(*buf++, reg++);
+
+	return 0;
+}
+
+static int verify_macaddr(char *s)
+{
+	u16 reg;
+	int i, err = 0;
+
+	printf("MAC Address: ");
+	err = i = 0;
+	for (i = 0; i < 3; i++) {
+		reg = read_eeprom_reg(0x20 + i);
+		printf("%02x:%02x%c", reg & 0xff, reg >> 8, i != 2 ? ':' : '\n');
+		if (s)
+			err |= reg != ((u16 *)s)[i];
+	}
+
+	return err ? 0 : 1;
+}
+
+static int set_mac(char *s)
+{
+	int i;
+	char *e, eaddr[6];
+
+	/* turn string into mac value */
+	for (i = 0; i < 6; i++) {
+		eaddr[i] = simple_strtoul(s, &e, 16);
+		s = (*e) ? e+1 : e;
+	}
+
+	for (i = 0; i < 3; i++)
+		write_eeprom_reg(*(((u16 *)eaddr) + i), 0x20 + i);
+
+	return 0;
+}
+
+static int parse_element(char *s, unsigned char *buf, int len)
+{
+	int cnt;
+	char *p, num[3];
+	unsigned char id;
+
+	id = simple_strtoul(s, &p, 16);
+	if (*p++ != ':')
+		return -1;
+	cnt = 2;
+	num[2] = 0;
+	for (; *p; p += 2) {
+		if (p[1] == 0)
+			return -2;
+		if (cnt + 3 > len)
+			return -3;
+		num[0] = p[0];
+		num[1] = p[1];
+		buf[cnt++] = simple_strtoul(num, NULL, 16);
+	}
+	buf[0] = id;
+	buf[1] = cnt - 2;
+
+	return cnt;
+}
+
+extern int crcek(void);
+
+int eeprom(int argc, char *argv[])
+{
+	int i, len, ret;
+	unsigned char buf[58], *p;
+
+	app_startup(argv);
+	if (get_version() != XF_VERSION) {
+		printf("Wrong XF_VERSION.\n");
+		printf("Application expects ABI version %d\n", XF_VERSION);
+		printf("Actual U-Boot ABI version %d\n", (int)get_version());
+		return 1;
+	}
+
+	return crcek();
+
+	if ((SMC_inw (BANK_SELECT) & 0xFF00) != 0x3300) {
+		printf("SMSC91111 not found.\n");
+		return 2;
+	}
+
+	/* Called without parameters - print MAC address */
+	if (argc < 2) {
+		verify_macaddr(NULL);
+		return 0;
+	}
+
+	/* Print help message */
+	if (argv[1][1] == 'h') {
+		printf("VoiceBlue EEPROM writer\n");
+		printf("Built: %s at %s\n", __DATE__ , __TIME__ );
+		printf("Usage:\n\t<mac_address> [<element_1>] [<...>]\n");
+		return 0;
+	}
+
+	/* Try to parse information elements */
+	len = sizeof(buf);
+	p = buf;
+	for (i = 2; i < argc; i++) {
+		ret = parse_element(argv[i], p, len);
+		switch (ret) {
+		case -1:
+			printf("Element %d: malformed\n", i - 1);
+			return 3;
+		case -2:
+			printf("Element %d: odd character count\n", i - 1);
+			return 3;
+		case -3:
+			printf("Out of EEPROM memory\n");
+			return 3;
+		default:
+			p += ret;
+			len -= ret;
+		}
+	}
+
+	/* First argument (MAC) is mandatory */
+	set_mac(argv[1]);
+	if (verify_macaddr(argv[1])) {
+		printf("*** MAC address does not match! ***\n");
+		return 4;
+	}
+
+	while (len--)
+		*p++ = 0;
+
+	write_data((u16 *)buf, sizeof(buf) >> 1);
+
+	return 0;
+}

+ 51 - 0
board/netstar/eeprom.lds

@@ -0,0 +1,51 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ * (C) Copyright 2005
+ * Ladislav Michl, 2N Telekomunikace, <michl@2n.cz>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = ALIGN(4);
+	.text      :
+	{
+	  eeprom_start.o	(.text)
+	  *(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(.rodata) }
+
+	. = ALIGN(4);
+	.data : { *(.data) }
+
+	. = ALIGN(4);
+	.got : { *(.got) }
+
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss : { *(.bss) }
+	_end = .;
+}

+ 177 - 0
board/netstar/eeprom_start.S

@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2005  2N Telekomunikace
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ */
+
+.globl _start
+_start:	b       eeprom
+
+#include "crcek.h"
+
+/**
+ * do_crc32 - calculate CRC32 of given buffer
+ * r0 - crc
+ * r1 - pointer to buffer
+ * r2 - buffer len
+ */
+	.macro	do_crc32
+	ldr	r5, FFFFFFFF
+	eor	r0, r0, r5
+	adr	r3, CRC32_TABLE
+1:
+	ldrb    r4, [r1], #1
+	eor	r4, r4, r0
+	and	r4, r4, #0xff
+	ldr	r4, [r3, r4, lsl#2]
+	eor	r0, r4, r0, lsr#8
+	subs	r2, r2, #0x1
+	bne 	1b
+	eor	r0, r0, r5
+	.endm
+
+	.macro crcuj, offset, size
+	ldr	r1, \offset
+	ldr	r2, [r1]
+	cmp	r2, #0		@ no data, no problem
+	beq	2f
+	mov     r7, #1
+	tst	r2, #3		@ unaligned size
+	bne	2f
+	mov     r7, #2
+	ldr	r0, \size
+	cmp	r2, r0		@ bogus size
+	bhi	2f
+	mov     r7, #3
+	add	r1, r1, #4
+	mov	r0, #0
+	do_crc32
+	ldr	r1, [r1]
+2:
+	cmp	r0, r1
+	.endm
+
+	.macro wait, reg
+	mov	\reg, #0x1000
+3:
+	subs	\reg, \reg, #0x1
+	bne 	3b
+
+	.endm
+.text
+.globl crcek
+crcek:
+	mov	r6, #0
+@	crcuj	_LOADER1_OFFSET, _LOADER_SIZE
+@	bne	crc1_bad
+@	orr	r6, r6, #1
+crc1_bad:
+	crcuj	_LOADER2_OFFSET, _LOADER_SIZE
+	bne	crc2_bad
+	orr	r6, r6, #2
+crc2_bad:
+@	mov	r0, r6
+	mov     pc, lr
+	ldr	r3, _LOADER1_OFFSET
+	ldr	r4, _LOADER2_OFFSET
+	tst	r6, #3
+	beq	one_is_bad	@ one of them (or both) has bad crc
+	ldr	r1, [r3, #4]
+	ldr	r2, [r4, #4]
+	cmp	r1, r2		@ boot 2nd loader if versions differ
+	beq	boot_1st
+	b	boot_2nd
+one_is_bad:
+	tst	r6, #1
+	bne	boot_1st
+	tst	r6, #2
+	bne	boot_2nd
+@ We are doomed, so let user know.
+	ldr	r0, GPIO_BASE	@ configure GPIO pins
+	ldr	r1, GPIO_DIRECTION
+	strh	r1, [r0, #0x08]
+blink_loop:
+	mov	r1, #0x08
+	strh    r1, [r0, #0x04]
+	wait	r3
+	mov	r1, #0x10
+	strh    r1, [r0, #0x04]
+	wait	r3
+	b blink_loop
+boot_1st:
+	add	pc, r3, #8
+boot_2nd:
+	add	pc, r4, #8
+
+_LOADER_SIZE:
+	.word LOADER_SIZE - 8	@ minus size and crc32
+_LOADER1_OFFSET:
+	.word LOADER1_OFFSET
+_LOADER2_OFFSET:
+	.word LOADER2_OFFSET
+
+FFFFFFFF:
+	.word 0xffffffff
+CRC32_TABLE:
+	.word 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419
+	.word 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4
+	.word 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07
+	.word 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de
+	.word 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856
+	.word 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9
+	.word 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4
+	.word 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b
+	.word 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3
+	.word 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a
+	.word 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599
+	.word 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924
+	.word 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190
+	.word 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f
+	.word 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e
+	.word 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01
+	.word 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed
+	.word 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950
+	.word 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3
+	.word 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2
+	.word 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a
+	.word 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5
+	.word 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010
+	.word 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f
+	.word 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17
+	.word 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6
+	.word 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615
+	.word 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8
+	.word 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344
+	.word 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb
+	.word 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a
+	.word 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5
+	.word 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1
+	.word 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c
+	.word 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef
+	.word 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236
+	.word 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe
+	.word 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31
+	.word 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c
+	.word 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713
+	.word 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b
+	.word 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242
+	.word 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1
+	.word 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c
+	.word 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278
+	.word 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7
+	.word 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66
+	.word 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9
+	.word 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605
+	.word 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8
+	.word 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b
+	.word 0x2d02ef8d
+
+GPIO_BASE:
+	.word 0xfffce000
+GPIO_DIRECTION:
+	.word 0x0000ffe7
+
+.end

+ 343 - 0
board/netstar/flash.c

@@ -0,0 +1,343 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2005
+ * 2N Telekomunikace, a.s. <www.2n.cz>
+ * Ladislav Michl <michl@2n.cz>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+/*#if 0 */
+#if (PHYS_SDRAM_1_SIZE != SZ_32M)
+
+#include "crcek.h"
+
+#if (CFG_MAX_FLASH_BANKS > 1)
+#error There is always only _one_ flash chip
+#endif
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+#define CMD_READ_ARRAY		0x000000f0
+#define CMD_UNLOCK1		0x000000aa
+#define CMD_UNLOCK2		0x00000055
+#define CMD_ERASE_SETUP		0x00000080
+#define CMD_ERASE_CONFIRM	0x00000030
+#define CMD_PROGRAM		0x000000a0
+#define CMD_UNLOCK_BYPASS	0x00000020
+
+#define MEM_FLASH_ADDR1		(*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
+#define MEM_FLASH_ADDR2		(*(volatile u16 *)(CFG_FLASH_BASE + (0x000002aa << 1)))
+
+#define BIT_ERASE_DONE		0x00000080
+#define BIT_RDY_MASK		0x00000080
+#define BIT_PROGRAM_ERROR	0x00000020
+#define BIT_TIMEOUT		0x80000000	/* our flag */
+
+/*-----------------------------------------------------------------------
+ */
+
+ulong flash_init(void)
+{
+	int i;
+
+	flash_info[0].flash_id = (AMD_MANUFACT & FLASH_VENDMASK) |
+				 (AMD_ID_LV800B & FLASH_TYPEMASK);
+	flash_info[0].size = PHYS_FLASH_1_SIZE;
+	flash_info[0].sector_count = CFG_MAX_FLASH_SECT;
+	memset(flash_info[0].protect, 0, CFG_MAX_FLASH_SECT);
+
+	for (i = 0; i < flash_info[0].sector_count; i++) {
+		switch (i) {
+		case 0: /* 16kB */
+			flash_info[0].start[0] = CFG_FLASH_BASE;
+			break;
+		case 1: /* 8kB */
+			flash_info[0].start[1] = CFG_FLASH_BASE + 0x4000;
+			break;
+		case 2: /* 8kB */
+			flash_info[0].start[2] = CFG_FLASH_BASE + 0x4000 +
+						 0x2000;
+			break;
+		case 3: /* 32 KB */
+			flash_info[0].start[3] = CFG_FLASH_BASE + 0x4000 +
+						 2 * 0x2000;
+			break;
+		case 4:
+			flash_info[0].start[4] = CFG_FLASH_BASE + 0x4000 +
+						 2 * 0x2000 + 0x8000;
+			break;
+		default: /* 64kB */
+			flash_info[0].start[i] = flash_info[0].start[i-1] +
+						 0x10000;
+			break;
+		}
+	}
+
+	/* U-Boot */
+	flash_protect(FLAG_PROTECT_SET,
+		      LOADER1_OFFSET,
+		      LOADER1_OFFSET + LOADER_SIZE - 1, flash_info);
+	/* Protect crcek, env and r_env as well */
+	flash_protect(FLAG_PROTECT_SET, 0, 0x8000 - 1, flash_info);
+
+	return flash_info[0].size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info(flash_info_t *info)
+{
+	int i;
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case (AMD_MANUFACT & FLASH_VENDMASK):
+		puts("AMD: ");
+		break;
+	default:
+		puts("Unknown vendor ");
+		break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case (AMD_ID_LV800B & FLASH_TYPEMASK):
+		puts("AM29LV800BB (8Mb)\n");
+		break;
+	default:
+		puts("Unknown chip type\n");
+		return;
+	}
+
+	printf("  Size: %ld MB in %d sectors\n",
+	       info->size >> 20, info->sector_count);
+
+	puts("  Sector start addresses:");
+	for (i = 0; i < info->sector_count; i++) {
+		if ((i % 5) == 0)
+			puts("\n   ");
+
+		printf(" %08lX%s", info->start[i],
+		       info->protect[i] ? " (RO)" : "     ");
+	}
+	puts("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+	ushort result;
+	int prot, sect;
+	int rc = ERR_OK;
+
+	/* first look for protection bits */
+
+	if (info->flash_id == FLASH_UNKNOWN)
+		return ERR_UNKNOWN_FLASH_TYPE;
+
+	if ((s_first < 0) || (s_first > s_last))
+		return ERR_INVAL;
+
+	if ((info->flash_id & FLASH_VENDMASK) !=
+	    (AMD_MANUFACT & FLASH_VENDMASK))
+		return ERR_UNKNOWN_FLASH_VENDOR;
+
+	prot = 0;
+	for (sect = s_first; sect <= s_last; ++sect)
+		if (info->protect[sect])
+			prot++;
+
+	if (prot)
+		printf("- Warning: %d protected sectors will not be erased!\n",
+		       prot);
+	else
+		putc('\n');
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			vu_short *addr = (vu_short *) (info->start[sect]);
+
+			/* arm simple, non interrupt dependent timer */
+			reset_timer_masked();
+
+			MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+			MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+			MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
+
+			MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+			MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+			*addr = CMD_ERASE_CONFIRM;
+
+			/* wait until flash is ready */
+			while (1) {
+				result = *addr;
+
+				/* check timeout */
+				if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) {
+					MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
+					rc = ERR_TIMOUT;
+					break;
+				}
+
+				if ((result & 0xfff) & BIT_ERASE_DONE)
+					break;
+
+				if ((result & 0xffff) & BIT_PROGRAM_ERROR) {
+					rc = ERR_PROG_ERROR;
+					break;
+				}
+			}
+
+			MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
+
+			if (rc != ERR_OK)
+				goto out;
+
+			putc('.');
+		}
+	}
+out:
+	/* allow flash to settle - wait 10 ms */
+	udelay_masked(10000);
+
+	return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash
+ */
+
+volatile static int write_hword(flash_info_t *info, ulong dest, ushort data)
+{
+	vu_short *addr = (vu_short *) dest;
+	ushort result;
+	int rc = ERR_OK;
+
+	/* check if flash is (sufficiently) erased */
+	result = *addr;
+	if ((result & data) != data)
+		return ERR_NOT_ERASED;
+
+	MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+	MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+	MEM_FLASH_ADDR1 = CMD_PROGRAM;
+	*addr = data;
+
+	/* arm simple, non interrupt dependent timer */
+	reset_timer_masked();
+
+	/* wait until flash is ready */
+	while (1) {
+		result = *addr;
+
+		/* check timeout */
+		if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
+			rc = ERR_TIMOUT;
+			break;
+		}
+
+		if ((result & 0x80) == (data & 0x80))
+			break;
+
+		if ((result & 0xffff) & BIT_PROGRAM_ERROR) {
+			result = *addr;
+
+			if ((result & 0x80) != (data & 0x80))
+				rc = ERR_PROG_ERROR;
+		}
+	}
+
+	*addr = CMD_READ_ARRAY;
+
+	if (*addr != data)
+		rc = ERR_PROG_ERROR;
+
+	return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash.
+ */
+
+int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp;
+	int l;
+	int i, rc;
+	ushort data;
+
+	wp = (addr & ~1);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i = 0, cp = wp; i < l; ++i, ++cp)
+			data = (data >> 8) | (*(uchar *) cp << 8);
+		for (; i < 2 && cnt > 0; ++i) {
+			data = (data >> 8) | (*src++ << 8);
+			--cnt;
+			++cp;
+		}
+		for (; cnt == 0 && i < 2; ++i, ++cp)
+			data = (data >> 8) | (*(uchar *) cp << 8);
+
+		if ((rc = write_hword(info, wp, data)) != 0)
+			return (rc);
+		wp += 2;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 2) {
+		data = *((vu_short *) src);
+		if ((rc = write_hword(info, wp, data)) != 0)
+			return (rc);
+		src += 2;
+		wp += 2;
+		cnt -= 2;
+	}
+
+	if (cnt == 0)
+		return ERR_OK;
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
+		data = (data >> 8) | (*src++ << 8);
+		--cnt;
+	}
+	for (; i < 2; ++i, ++cp)
+		data = (data >> 8) | (*(uchar *) cp << 8);
+
+	return write_hword(info, wp, data);
+}
+
+#endif

+ 64 - 0
board/netstar/nand.c

@@ -0,0 +1,64 @@
+/*
+ * (C) Copyright 2005 2N TELEKOMUNIKACE, Ladislav Michl
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+
+#include <nand.h>
+
+/*
+ *	hardware specific access to control-lines
+ */
+#define	MASK_CLE	0x02
+#define	MASK_ALE	0x04
+
+static void netstar_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+	struct nand_chip *this = mtd->priv;
+	ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
+
+	IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
+	switch (cmd) {
+		case NAND_CTL_SETCLE: IO_ADDR_W |= MASK_CLE; break;
+		case NAND_CTL_SETALE: IO_ADDR_W |= MASK_ALE; break;
+	}
+	this->IO_ADDR_W = (void *) IO_ADDR_W;
+}
+
+/*
+ *	chip R/B detection
+ */
+static int netstar_nand_ready(struct mtd_info *mtd)
+{
+	return (*(volatile ushort *)GPIO_DATA_INPUT_REG) & 0x02;
+}
+
+void board_nand_init(struct nand_chip *nand)
+{
+	nand->options = NAND_SAMSUNG_LP_OPTIONS;
+	nand->eccmode = NAND_ECC_SOFT;
+	nand->hwcontrol = netstar_nand_hwcontrol;
+/*	nand->dev_ready = netstar_nand_ready; */
+	nand->chip_delay = 18;
+}
+#endif

+ 68 - 0
board/netstar/netstar.c

@@ -0,0 +1,68 @@
+/*
+ * (C) Copyright 2005 2N TELEKOMUNIKACE, Ladislav Michl
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+int board_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	/* arch number of NetStar board */
+	/* TODO: use define from asm/mach-types.h */
+	gd->bd->bi_arch_number = 692;
+
+	/* adress of boot parameters */
+	gd->bd->bi_boot_params = 0x10000100;
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+
+	/* Take the Ethernet controller out of reset and wait
+	 * for the EEPROM load to complete. */
+	*((volatile unsigned short *) GPIO_DATA_OUTPUT_REG) |= 0x80;
+	udelay(10);	/* doesn't work before interrupt_init call */
+	*((volatile unsigned short *) GPIO_DATA_OUTPUT_REG) &= ~0x80;
+	udelay(500);
+
+	return 0;
+}
+
+extern void partition_flash(void);
+
+int misc_init_r(void)
+{
+	return 0;
+}
+
+extern void nand_init(void);
+
+int board_late_init(void)
+{
+	return 0;
+}

+ 287 - 0
board/netstar/setup.S

@@ -0,0 +1,287 @@
+/*
+ * Board specific setup info
+ *
+ * (C) Copyright 2004 Ales Jindra <jindra@2n.cz>
+ * (C) Copyright 2005 Ladislav Michl <michl@2n.cz>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <version.h>
+
+_TEXT_BASE:
+	.word	TEXT_BASE	/* SDRAM load addr from config.mk */
+
+OMAP5910_LPG1_BASE:		.word 0xfffbd000
+OMAP5910_TIPB_SWITCHES_BASE:	.word 0xfffbc800
+OMAP5910_MPU_TC_BASE:		.word 0xfffecc00
+OMAP5910_MPU_CLKM_BASE:		.word 0xfffece00
+OMAP5910_ULPD_PWR_MNG_BASE:	.word 0xfffe0800
+OMAP5910_DPLL1_BASE:		.word 0xfffecf00
+OMAP5910_GPIO_BASE:		.word 0xfffce000
+OMAP5910_MPU_WD_TIMER_BASE:	.word 0xfffec800
+OMAP5910_MPUI_BASE:		.word 0xfffec900
+
+_OMAP5910_ARM_CKCTL:		.word OMAP5910_ARM_CKCTL
+_OMAP5910_ARM_EN_CLK:		.word OMAP5910_ARM_EN_CLK
+
+OMAP5910_MPUI_CTRL:		.word 0x0000ff1b
+
+VAL_EMIFS_CS0_CONFIG:		.word 0x00009090
+VAL_EMIFS_CS1_CONFIG:		.word 0x00003031
+VAL_EMIFS_CS2_CONFIG:		.word 0x0000a0a1
+VAL_EMIFS_CS3_CONFIG:		.word 0x0000c0c0
+VAL_EMIFS_DYN_WAIT:		.word 0x00000000
+/* autorefresh counter 0x246 ((64000000/13.4)-400)/8192) */
+				/*     SLRF       SD_RET     ARE        SDRAM_TYPE   ARCV           SDRAM_FREQUENCY PWD     CLK */
+
+#if (PHYS_SDRAM_1_SIZE == SZ_32M)
+VAL_EMIFF_SDRAM_CONFIG:		.word ((0 << 0) | (0 << 1) | (3 << 2) | (0xf << 4) | (0x246 << 8) | (0 << 24) | (0 << 26) | (0 << 27))
+#else
+VAL_EMIFF_SDRAM_CONFIG:		.word ((0 << 0) | (0 << 1) | (3 << 2) | (0xd << 4) | (0x246 << 8) | (0 << 24) | (0 << 26) | (0 << 27))
+#endif
+
+VAL_EMIFF_SDRAM_CONFIG2:	.word 0x00000003
+VAL_EMIFF_MRS:			.word 0x00000037
+
+/*
+ * GPIO04 - Green LED (Red LED is connected to LED Pulse Generator)
+ * GPIO07 - LAN91C111 reset
+ */
+GPIO_DIRECTION:
+	.word 0x0000ff6f
+/*
+ * Disable everything (green LED is connected via invertor)
+ */
+GPIO_OUTPUT:
+	.word 0x00000010
+
+MUX_CONFIG_BASE:
+	.word 0xfffe1000
+
+MUX_CONFIG_VALUES:
+	.align 4
+	.word 0x00000000	@ FUNC_MUX_CTRL_0
+	.word 0x00000000	@ FUNC_MUX_CTRL_1
+	.word 0x00000000	@ FUNC_MUX_CTRL_2
+	.word 0x00000000	@ FUNC_MUX_CTRL_3
+	.word 0x00000000	@ FUNC_MUX_CTRL_4
+	.word 0x02080480	@ FUNC_MUX_CTRL_5
+	.word 0x0100001c	@ FUNC_MUX_CTRL_6
+	.word 0x0004800b	@ FUNC_MUX_CTRL_7
+	.word 0x10001200	@ FUNC_MUX_CTRL_8
+	.word 0x01201012	@ FUNC_MUX_CTRL_9
+	.word 0x02082248	@ FUNC_MUX_CTRL_A
+	.word 0x00000248	@ FUNC_MUX_CTRL_B
+	.word 0x12240000	@ FUNC_MUX_CTRL_C
+	.word 0x00002000	@ FUNC_MUX_CTRL_D
+	.word 0x00000000	@ PULL_DWN_CTRL_0
+	.word 0x00000800	@ PULL_DWN_CTRL_1
+	.word 0x01801000	@ PULL_DWN_CTRL_2
+	.word 0x00000000	@ PULL_DWN_CTRL_3
+	.word 0x00000000	@ GATE_INH_CTRL_0
+	.word 0x00000000	@ VOLTAGE_CTRL_0
+	.word 0x00000000	@ TEST_DBG_CTRL_0
+	.word 0x00000006	@ MOD_CONF_CTRL_0
+	.word 0x0000eaef	@ COMP_MODE_CTRL_0
+
+MUX_CONFIG_OFFSETS:
+	.align 1
+	.byte 0x00		@ FUNC_MUX_CTRL_0
+	.byte 0x04		@ FUNC_MUX_CTRL_1
+	.byte 0x08		@ FUNC_MUX_CTRL_2
+	.byte 0x10		@ FUNC_MUX_CTRL_3
+	.byte 0x14		@ FUNC_MUX_CTRL_4
+	.byte 0x18		@ FUNC_MUX_CTRL_5
+	.byte 0x1c		@ FUNC_MUX_CTRL_6
+	.byte 0x20		@ FUNC_MUX_CTRL_7
+	.byte 0x24		@ FUNC_MUX_CTRL_8
+	.byte 0x28		@ FUNC_MUX_CTRL_9
+	.byte 0x2c		@ FUNC_MUX_CTRL_A
+	.byte 0x30		@ FUNC_MUX_CTRL_B
+	.byte 0x34		@ FUNC_MUX_CTRL_C
+	.byte 0x38		@ FUNC_MUX_CTRL_D
+	.byte 0x40		@ PULL_DWN_CTRL_0
+	.byte 0x44		@ PULL_DWN_CTRL_1
+	.byte 0x48		@ PULL_DWN_CTRL_2
+	.byte 0x4c		@ PULL_DWN_CTRL_3
+	.byte 0x50		@ GATE_INH_CTRL_0
+	.byte 0x60		@ VOLTAGE_CTRL_0
+	.byte 0x70		@ TEST_DBG_CTRL_0
+	.byte 0x80		@ MOD_CONF_CTRL_0
+	.byte 0x0c		@ COMP_MODE_CTRL_0
+	.byte 0xff
+
+.globl platformsetup
+platformsetup:
+	/* Improve performance a bit... */
+	mrc	p15, 0, r1, c0, c0, 0		@ read C15 ID register
+	mrc	p15, 0, r1, c0, c0, 1		@ read C15 Cache information register
+	mrc	p15, 0, r1, c1, c0, 0		@ read C15 Control register
+	orr	r1, r1, #0x1000			@ enable I-cache, map interrupt vector 0xffff0000
+	mcr	p15, 0, r1, c1, c0, 0		@ write C15 Control register
+	mov	r1, #0x00
+	mcr	p15, 0, r1, c7, c5, 0		@ Flush I-cache
+	nop
+	nop
+	nop
+	nop
+
+	/* Setup clocking mode */
+	ldr	r0, OMAP5910_MPU_CLKM_BASE	@ prepare base of CLOCK unit
+	ldrh	r1, [r0, #0x18]			@ get reset status
+	bic	r1, r1, #(7 << 11)		@ clear clock select
+	orr	r1, r1, #(2 << 11)		@ set synchronous scalable
+	mov	r2, #0				@ set wait counter to 100 clock cycles
+
+icache_loop:
+	cmp	r2, #0x01
+	streqh	r1, [r0, #0x18]
+	add	r2, r2, #0x01
+	cmp	r2, #0x10
+	bne	icache_loop
+	nop
+
+	/* Setup clock divisors */
+	ldr	r0, OMAP5910_MPU_CLKM_BASE	@ base of CLOCK unit
+	ldr	r1, _OMAP5910_ARM_CKCTL
+	orr	r1, r1, #0x2000			@ enable DSP clock
+	strh	r1, [r0, #0x00]			@ setup clock divisors
+
+	/* Setup DPLL to generate requested freq */
+	ldr	r0, OMAP5910_DPLL1_BASE		@ base of DPLL1 register
+	mov	r1, #0x0010			@ set PLL_ENABLE
+	orr	r1, r1, #0x2000			@ set IOB to new locking
+	orr	r1, r1, #(OMAP5910_DPLL_MUL << 7) @ setup multiplier CLKREF
+	orr	r1, r1, #(OMAP5910_DPLL_DIV << 5) @ setup divider CLKREF
+	strh	r1, [r0]			@ write
+
+locking:
+	ldrh	r1, [r0]			@ get DPLL value
+	tst	r1, #0x01
+	beq	locking				@ while LOCK not set
+
+	/* Enable clock */
+	ldr	r0, OMAP5910_MPU_CLKM_BASE	@ base of CLOCK unit
+	mov	r1, #(1 << 10)			@ disable idle mode do not check
+						@ nWAKEUP pin, other remain active
+	strh	r1, [r0, #0x04]
+	ldr	r1, _OMAP5910_ARM_EN_CLK
+	strh	r1, [r0, #0x08]
+	mov	r1, #0x003f			@ FLASH.RP not enabled in idle and
+						@ max delayed ( 32 x CLKIN )
+	strh	r1, [r0, #0x0c]
+
+	/* Configure 5910 pins functions to match our board. */
+	ldr     r0, MUX_CONFIG_BASE
+	adr	r1, MUX_CONFIG_VALUES
+	adr	r2, MUX_CONFIG_OFFSETS
+next_mux_cfg:
+	ldrb	r3, [r2], #1
+	ldr	r4, [r1], #4
+	cmp	r3, #0xff
+	strne	r4, [r0, r3]
+	bne	next_mux_cfg
+
+	/* Configure GPIO pins (also disables Green LED) */
+	ldr	r0, OMAP5910_GPIO_BASE
+	ldr	r1, GPIO_OUTPUT
+	strh    r1, [r0, #0x04]
+	ldr	r1, GPIO_DIRECTION
+	strh	r1, [r0, #0x08]
+
+	/* EnablePeripherals */
+	ldr	r0, OMAP5910_MPU_CLKM_BASE	@ CLOCK unit
+	mov	r1, #0x0001			@ Peripheral enable
+	strh	r1, [r0, #0x14]
+
+	/* Program LED Pulse Generator */
+	ldr	r0, OMAP5910_LPG1_BASE		@ 1st LED Pulse Generator
+	mov	r1, #0x7F			@ Set obscure frequency in
+	strb	r1, [r0, #0x00]			@ LCR
+	mov	r1, #0x01			@ Enable clock (CLK_EN) in
+	strb    r1, [r0, #0x04]			@ PMR
+
+	/* TIPB Lock UART1 */
+	ldr	r0, OMAP5910_TIPB_SWITCHES_BASE	@ prepare base of TIPB switches
+	mov	r1, #1				@ ARM allocated
+	strh	r1, [r0,#0x04]			@ clear IRQ line and status bits
+	strh	r1, [r0,#0x00]
+	ldrh	r1, [r0,#0x04]
+
+	/* Disable watchdog */
+	ldr	r0, OMAP5910_MPU_WD_TIMER_BASE
+	mov	r1, #0xf5
+	strh	r1, [r0, #0x8]
+	mov	r1, #0xa0
+	strh	r1, [r0, #0x8]
+
+	/* Enable MCLK */
+	ldr	r0, OMAP5910_ULPD_PWR_MNG_BASE
+	mov	r1, #0x6
+	strh	r1, [r0, #0x34]
+	strh	r1, [r0, #0x34]
+
+	/* Setup clock divisors */
+	ldr	r0, OMAP5910_ULPD_PWR_MNG_BASE	@ base of ULDPL DPLL1 register
+
+	mov	r1, #0x0010			@ set PLL_ENABLE
+	orr	r1, r1, #0x2000			@ set IOB to new locking
+	strh	r1, [r0]			@ write
+
+ulocking:
+	ldrh	r1, [r0]			@ get DPLL value
+	tst	r1, #1
+	beq	ulocking			@ while LOCK not set
+
+	/* EMIF init */
+	ldr	r0, OMAP5910_MPU_TC_BASE
+	ldrh	r1, [r0, #0x0c]			@ EMIFS_CONFIG_REG
+	bic	r1, r1, #0x0c			@ pwr down disabled, flash WP
+	orr	r1, r1, #0x01
+	str	r1, [r0, #0x0c]
+
+	ldr	r1, VAL_EMIFS_CS0_CONFIG
+	str	r1, [r0, #0x10]			@ EMIFS_CS0_CONFIG
+	ldr	r1, VAL_EMIFS_CS1_CONFIG
+	str	r1, [r0, #0x14]			@ EMIFS_CS1_CONFIG
+	ldr	r1, VAL_EMIFS_CS2_CONFIG
+	str	r1, [r0, #0x18]			@ EMIFS_CS2_CONFIG
+	ldr	r1, VAL_EMIFS_CS3_CONFIG
+	str	r1, [r0, #0x1c]			@ EMIFS_CS3_CONFIG
+	ldr	r1, VAL_EMIFS_DYN_WAIT
+	str	r1, [r0, #0x40]			@ EMIFS_CFG_DYN_WAIT
+
+	/* Setup SDRAM */
+	ldr	r1, VAL_EMIFF_SDRAM_CONFIG
+	str	r1, [r0, #0x20]			@ EMIFF_SDRAM_CONFIG
+	ldr	r1, VAL_EMIFF_SDRAM_CONFIG2
+	str	r1, [r0, #0x3c]			@ EMIFF_SDRAM_CONFIG2
+	ldr	r1, VAL_EMIFF_MRS
+	str	r1, [r0, #0x24]			@ EMIFF_MRS
+	/* SDRAM needs 100us to stabilize */
+	mov	r0, #0x4000
+sdelay:
+	subs	r0, r0, #0x1
+	bne 	sdelay
+
+	/* back to arch calling code */
+	mov	pc, lr
+.end

+ 55 - 0
board/netstar/u-boot.lds

@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text      :
+	{
+	  cpu/arm925t/start.o	(.text)
+	  *(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(.rodata) }
+
+	. = ALIGN(4);
+	.data : { *(.data) }
+
+	. = ALIGN(4);
+	.got : { *(.got) }
+
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss : { *(.bss) }
+	_end = .;
+}

+ 15 - 4
common/cmd_jffs2.c

@@ -99,6 +99,10 @@
 
 
 #include <cramfs/cramfs_fs.h>
 #include <cramfs/cramfs_fs.h>
 
 
+#ifdef CONFIG_NEW_NAND_CODE
+#include <nand.h>
+#endif
+
 /* enable/disable debugging messages */
 /* enable/disable debugging messages */
 #define	DEBUG
 #define	DEBUG
 #undef	DEBUG
 #undef	DEBUG
@@ -324,10 +328,9 @@ static int part_validate_nand(struct mtdids *id, struct part_info *part)
 {
 {
 #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
 #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
 	/* info for NAND chips */
 	/* info for NAND chips */
-	extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
-	struct nand_chip *nand;
+	nand_info_t *nand;
 
 
-	nand = &nand_dev_desc[id->num];
+	nand = &nand_info[id->num];
 
 
 	if ((unsigned long)(part->offset) % nand->erasesize) {
 	if ((unsigned long)(part->offset) % nand->erasesize) {
 		printf("%s%d: partition (%s) start offset alignment incorrect\n",
 		printf("%s%d: partition (%s) start offset alignment incorrect\n",
@@ -422,8 +425,9 @@ static int part_del(struct mtd_device *dev, struct part_info *part)
 		}
 		}
 	}
 	}
 
 
-
+#ifndef CONFIG_NEW_NAND_CODE
 	jffs2_free_cache(part);
 	jffs2_free_cache(part);
+#endif
 	list_del(&part->link);
 	list_del(&part->link);
 	free(part);
 	free(part);
 	dev->num_parts--;
 	dev->num_parts--;
@@ -445,7 +449,9 @@ static void part_delall(struct list_head *head)
 	list_for_each_safe(entry, n, head) {
 	list_for_each_safe(entry, n, head) {
 		part_tmp = list_entry(entry, struct part_info, link);
 		part_tmp = list_entry(entry, struct part_info, link);
 
 
+#ifndef CONFIG_NEW_NAND_CODE
 		jffs2_free_cache(part_tmp);
 		jffs2_free_cache(part_tmp);
+#endif
 		list_del(entry);
 		list_del(entry);
 		free(part_tmp);
 		free(part_tmp);
 	}
 	}
@@ -661,6 +667,7 @@ static int device_validate(u8 type, u8 num, u32 *size)
 		if (num < CFG_MAX_FLASH_BANKS) {
 		if (num < CFG_MAX_FLASH_BANKS) {
 			extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
 			extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
 			*size = flash_info[num].size;
 			*size = flash_info[num].size;
+
 			return 0;
 			return 0;
 		}
 		}
 
 
@@ -672,8 +679,12 @@ static int device_validate(u8 type, u8 num, u32 *size)
 	} else if (type == MTD_DEV_TYPE_NAND) {
 	} else if (type == MTD_DEV_TYPE_NAND) {
 #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
 #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
 		if (num < CFG_MAX_NAND_DEVICE) {
 		if (num < CFG_MAX_NAND_DEVICE) {
+#ifdef CONFIG_NEW_NAND_CODE
+			*size = nand_info[num].size;
+#else
 			extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 			extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 			*size = nand_dev_desc[num].totlen;
 			*size = nand_dev_desc[num].totlen;
+#endif
 			return 0;
 			return 0;
 		}
 		}
 
 

+ 1763 - 277
common/cmd_nand.c

@@ -1,15 +1,18 @@
 /*
 /*
- * Rick Bronson and Pantelis Antoniou
+ * Driver for NAND support, Rick Bronson
+ * borrowed heavily from:
+ * (c) 1999 Machine Vision Holdings, Inc.
+ * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
+ *
+ * Added 16-bit nand support
+ * (C) 2004 Texas Instruments
  */
  */
 
 
 #include <common.h>
 #include <common.h>
-
-#if (CONFIG_COMMANDS & CFG_CMD_NAND)
-
 #include <command.h>
 #include <command.h>
-#include <watchdog.h>
 #include <malloc.h>
 #include <malloc.h>
-#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <watchdog.h>
 
 
 #ifdef CONFIG_SHOW_BOOT_PROGRESS
 #ifdef CONFIG_SHOW_BOOT_PROGRESS
 # include <status_led.h>
 # include <status_led.h>
@@ -18,311 +21,290 @@
 # define SHOW_BOOT_PROGRESS(arg)
 # define SHOW_BOOT_PROGRESS(arg)
 #endif
 #endif
 
 
-#include <jffs2/jffs2.h>
-#include <nand.h>
-
-extern nand_info_t nand_info[];       /* info for NAND chips */
+#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined CONFIG_NEW_NAND_CODE
 
 
-static int nand_dump_oob(nand_info_t *nand, ulong off)
-{
-	return 0;
-}
-
-static int nand_dump(nand_info_t *nand, ulong off)
-{
-	int i;
-	u_char *buf, *p;
-
-	buf = malloc(nand->oobblock + nand->oobsize);
-	if (!buf) {
-		puts("No memory for page buffer\n");
-		return 1;
-	}
-	off &= ~(nand->oobblock - 1);
-	i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
-	if (i < 0) {
-		printf("Error (%d) reading page %08x\n", i, off);
-		free(buf);
-		return 1;
-	}
-	printf("Page %08x dump:\n", off);
-	i = nand->oobblock >> 4; p = buf;
-	while (i--) {
-		printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
-			"  %02x %02x %02x %02x %02x %02x %02x %02x\n",
-			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
-			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
-		p += 16;
-	}
-	puts("OOB:\n");
-	i = nand->oobsize >> 3;
-	while (i--) {
-		printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
-			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
-		p += 8;
-	}
-	free(buf);
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ids.h>
+#include <jffs2/jffs2.h>
 
 
-	return 0;
-}
+#ifdef CONFIG_OMAP1510
+void archflashwp(void *archdata, int wp);
+#endif
 
 
-/* ------------------------------------------------------------------------- */
+#define ROUND_DOWN(value,boundary)      ((value) & (~((boundary)-1)))
 
 
-static void
-arg_off_size(int argc, char *argv[], ulong *off, ulong *size, ulong totsize)
-{
-	*off = 0;
-	*size = 0;
+/*
+ * Definition of the out of band configuration structure
+ */
+struct nand_oob_config {
+	int ecc_pos[6];		/* position of ECC bytes inside oob */
+	int badblock_pos;	/* position of bad block flag inside oob -1 = inactive */
+	int eccvalid_pos;	/* position of ECC valid flag inside oob -1 = inactive */
+} oob_config = { {0}, 0, 0};
+
+#undef	NAND_DEBUG
+#undef	PSYCHO_DEBUG
+
+/* ****************** WARNING *********************
+ * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
+ * erase (or at least attempt to erase) blocks that are marked
+ * bad. This can be very handy if you are _sure_ that the block
+ * is OK, say because you marked a good block bad to test bad
+ * block handling and you are done testing, or if you have
+ * accidentally marked blocks bad.
+ *
+ * Erasing factory marked bad blocks is a _bad_ idea. If the
+ * erase succeeds there is no reliable way to find them again,
+ * and attempting to program or erase bad blocks can affect
+ * the data in _other_ (good) blocks.
+ */
+#define	 ALLOW_ERASE_BAD_DEBUG 0
 
 
-#if defined(CONFIG_JFFS2_NAND) && defined(CFG_JFFS_CUSTOM_PART)
-	if (argc >= 1 && strcmp(argv[0], "partition") == 0) {
-		int part_num;
-		struct part_info *part;
-		const char *partstr;
+#define CONFIG_MTD_NAND_ECC  /* enable ECC */
+#define CONFIG_MTD_NAND_ECC_JFFS2
 
 
-		if (argc >= 2)
-			partstr = argv[1];
-		else
-			partstr = getenv("partition");
+/* bits for nand_rw() `cmd'; or together as needed */
+#define NANDRW_READ	0x01
+#define NANDRW_WRITE	0x00
+#define NANDRW_JFFS2	0x02
+#define NANDRW_JFFS2_SKIP	0x04
 
 
-		if (partstr)
-			part_num = (int)simple_strtoul(partstr, NULL, 10);
-		else
-			part_num = 0;
-
-		part = jffs2_part_info(part_num);
-		if (part == NULL) {
-			printf("\nInvalid partition %d\n", part_num);
-			return;
-		}
-		*size = part->size;
-		*off = (ulong)part->offset;
-	} else
+/*
+ * Function Prototypes
+ */
+static void nand_print(struct nand_chip *nand);
+int nand_rw (struct nand_chip* nand, int cmd,
+	    size_t start, size_t len,
+	    size_t * retlen, u_char * buf);
+int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean);
+static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
+		 size_t * retlen, u_char *buf, u_char *ecc_code);
+static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
+			   size_t * retlen, const u_char * buf, u_char * ecc_code);
+static void nand_print_bad(struct nand_chip *nand);
+static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
+		 size_t * retlen, u_char * buf);
+static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
+		 size_t * retlen, const u_char * buf);
+static int NanD_WaitReady(struct nand_chip *nand, int ale_wait);
+#ifdef CONFIG_MTD_NAND_ECC
+static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
+static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
 #endif
 #endif
-	{
-		if (argc >= 1)
-			*off = (ulong)simple_strtoul(argv[0], NULL, 16);
-		else
-			*off = 0;
 
 
-		if (argc >= 2)
-			*size = (ulong)simple_strtoul(argv[1], NULL, 16);
-		else
-			*size = totsize - *off;
+struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE] = {{0}};
 
 
-	}
+/* Current NAND Device	*/
+static int curr_device = -1;
 
 
-}
+/* ------------------------------------------------------------------------- */
 
 
-int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
 {
-	int i, dev, ret;
-	ulong addr, off, size;
-	char *cmd, *s;
-	nand_info_t *nand;
+    int rcode = 0;
 
 
-	/* at least two arguments please */
-	if (argc < 2)
-		goto usage;
-
-	cmd = argv[1];
+    switch (argc) {
+    case 0:
+    case 1:
+	printf ("Usage:\n%s\n", cmdtp->usage);
+	return 1;
+    case 2:
+	if (strcmp(argv[1],"info") == 0) {
+		int i;
 
 
-	if (strcmp(cmd, "info") == 0) {
+		putc ('\n');
 
 
-		putc('\n');
-		for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
-			if (nand_info[i].name)
-				printf("Device %d: %s\n", i, nand_info[i].name);
+		for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) {
+			if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN)
+				continue; /* list only known devices */
+			printf ("Device %d: ", i);
+			nand_print(&nand_dev_desc[i]);
 		}
 		}
 		return 0;
 		return 0;
-	}
 
 
-	if (strcmp(cmd, "device") == 0) {
-
-		if (argc < 3) {
-			if ((nand_curr_device < 0) ||
-			    (nand_curr_device >= CFG_MAX_NAND_DEVICE))
-				puts("\nno devices available\n");
-			else
-				printf("\nDevice %d: %s\n", nand_curr_device,
-					nand_info[nand_curr_device].name);
-			return 0;
-		}
-		dev = (int)simple_strtoul(argv[2], NULL, 10);
-		if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
-			puts("No such device\n");
+	} else if (strcmp(argv[1],"device") == 0) {
+		if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
+			puts ("\nno devices available\n");
 			return 1;
 			return 1;
 		}
 		}
-		printf("Device %d: %s", dev, nand_info[dev].name);
-		puts("... is now current device\n");
-		nand_curr_device = dev;
+		printf ("\nDevice %d: ", curr_device);
+		nand_print(&nand_dev_desc[curr_device]);
 		return 0;
 		return 0;
-	}
-
-	if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
-	    strncmp(cmd, "dump", 4) != 0 &&
-	    strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0
-#ifdef CONFIG_MTD_NAND_UNSAFE
-	    && strcmp(cmd, "scrub") != 0 && strcmp(cmd, "biterr") != 0
-	    && strcmp(cmd, "markbad") != 0
-#endif
-	    )
-		goto usage;
-
-	/* the following commands operate on the current device */
-	if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
-	    !nand_info[nand_curr_device].name) {
-		puts("\nno devices available\n");
-		return 1;
-	}
-	nand = &nand_info[nand_curr_device];
 
 
-	if (strcmp(cmd, "bad") == 0) {
-		printf("\nDevice %d bad blocks:\n", nand_curr_device);
-		for (off = 0; off < nand->size; off += nand->erasesize)
-			if (nand_block_isbad(nand, off))
-				printf("  %08x\n", off);
+	} else if (strcmp(argv[1],"bad") == 0) {
+		if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
+			puts ("\nno devices available\n");
+			return 1;
+		}
+		printf ("\nDevice %d bad blocks:\n", curr_device);
+		nand_print_bad(&nand_dev_desc[curr_device]);
 		return 0;
 		return 0;
-	}
-
-	if (strcmp(cmd, "erase") == 0
-#ifdef CONFIG_MTD_NAND_UNSAFE
-	    || strcmp(cmd, "scrub") == 0
-#endif
-	    ) {
 
 
-#ifdef CONFIG_MTD_NAND_UNSAFE
-		i = strcmp(cmd, "scrub") == 0;	/* 1 scrub, 0 = erase */
-#endif
+	}
+	printf ("Usage:\n%s\n", cmdtp->usage);
+	return 1;
+    case 3:
+	if (strcmp(argv[1],"device") == 0) {
+		int dev = (int)simple_strtoul(argv[2], NULL, 10);
 
 
-		arg_off_size(argc - 2, argv + 2, &off, &size, nand->size);
-		if (off == 0 && size == 0)
+		printf ("\nDevice %d: ", dev);
+		if (dev >= CFG_MAX_NAND_DEVICE) {
+			puts ("unknown device\n");
 			return 1;
 			return 1;
+		}
+		nand_print(&nand_dev_desc[dev]);
+		/*nand_print (dev);*/
 
 
-		printf("\nNAND %s: device %d offset 0x%x, size 0x%x ",
-#ifdef CONFIG_MTD_NAND_UNSAFE
-		       i ? "scrub" :
-#endif
-		       "erase",
-		       nand_curr_device, off, size);
+		if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {
+			return 1;
+		}
 
 
-#ifdef CONFIG_MTD_NAND_UNSAFE
-		if (i)
-			ret = nand_scrub(nand, off, size);
-		else
-#endif
-			ret = nand_erase(nand, off, size);
+		curr_device = dev;
 
 
-		printf("%s\n", ret ? "ERROR" : "OK");
+		puts ("... is now current device\n");
 
 
-		return ret == 0 ? 0 : 1;
+		return 0;
 	}
 	}
+	else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {
+		struct nand_chip* nand = &nand_dev_desc[curr_device];
+		ulong off = 0;
+		ulong size = nand->totlen;
+		int ret;
 
 
-	if (strncmp(cmd, "dump", 4) == 0) {
-		if (argc < 3)
-			goto usage;
+		printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
+			curr_device, off, size);
 
 
-		s = strchr(cmd, '.');
-		off = (int)simple_strtoul(argv[2], NULL, 16);
+		ret = nand_erase (nand, off, size, 1);
 
 
-		if (s != NULL && strcmp(s, ".oob") == 0)
-			ret = nand_dump_oob(nand, off);
-		else
-			ret = nand_dump(nand, off);
-
-		return ret == 0 ? 1 : 0;
+		printf("%s\n", ret ? "ERROR" : "OK");
 
 
+		return ret;
 	}
 	}
 
 
-	/* read write */
-	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
-		if (argc < 4)
-			goto usage;
-/*
-		s = strchr(cmd, '.');
-		clean = CLEAN_NONE;
-		if (s != NULL) {
-			if (strcmp(s, ".jffs2") == 0 || strcmp(s, ".e") == 0
-			    || strcmp(s, ".i"))
-				clean = CLEAN_JFFS2;
-		}
-*/
-		addr = (ulong)simple_strtoul(argv[2], NULL, 16);
-
-		arg_off_size(argc - 3, argv + 3, &off, &size, nand->size);
-		if (off == 0 && size == 0)
+	printf ("Usage:\n%s\n", cmdtp->usage);
+	return 1;
+    default:
+	/* at least 4 args */
+
+	if (strncmp(argv[1], "read", 4) == 0 ||
+	    strncmp(argv[1], "write", 5) == 0) {
+		ulong addr = simple_strtoul(argv[2], NULL, 16);
+		ulong off  = simple_strtoul(argv[3], NULL, 16);
+		ulong size = simple_strtoul(argv[4], NULL, 16);
+		int cmd    = (strncmp(argv[1], "read", 4) == 0) ?
+				NANDRW_READ : NANDRW_WRITE;
+		int ret, total;
+		char* cmdtail = strchr(argv[1], '.');
+
+		if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {
+			/* read out-of-band data */
+			if (cmd & NANDRW_READ) {
+				ret = nand_read_oob(nand_dev_desc + curr_device,
+						    off, size, &total,
+						    (u_char*)addr);
+			}
+			else {
+				ret = nand_write_oob(nand_dev_desc + curr_device,
+						     off, size, &total,
+						     (u_char*)addr);
+			}
+			return ret;
+		}
+		else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))
+			cmd |= NANDRW_JFFS2;	/* skip bad blocks */
+		else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) {
+			cmd |= NANDRW_JFFS2;	/* skip bad blocks (on read too) */
+			if (cmd & NANDRW_READ)
+				cmd |= NANDRW_JFFS2_SKIP;	/* skip bad blocks (on read too) */
+		}
+#ifdef SXNI855T
+		/* need ".e" same as ".j" for compatibility with older units */
+		else if (cmdtail && !strcmp(cmdtail, ".e"))
+			cmd |= NANDRW_JFFS2;	/* skip bad blocks */
+#endif
+#ifdef CFG_NAND_SKIP_BAD_DOT_I
+		/* need ".i" same as ".jffs2s" for compatibility with older units (esd) */
+		/* ".i" for image -> read skips bad block (no 0xff) */
+		else if (cmdtail && !strcmp(cmdtail, ".i")) {
+			cmd |= NANDRW_JFFS2;	/* skip bad blocks (on read too) */
+			if (cmd & NANDRW_READ)
+				cmd |= NANDRW_JFFS2_SKIP;	/* skip bad blocks (on read too) */
+		}
+#endif /* CFG_NAND_SKIP_BAD_DOT_I */
+		else if (cmdtail) {
+			printf ("Usage:\n%s\n", cmdtp->usage);
 			return 1;
 			return 1;
+		}
 
 
-		i = strncmp(cmd, "read", 4) == 0;	/* 1 = read, 0 = write */
-		printf("\nNAND %s: device %d offset %u, size %u ... ",
-		       i ? "read" : "write", nand_curr_device, off, size);
+		printf ("\nNAND %s: device %d offset %ld, size %ld ... ",
+			(cmd & NANDRW_READ) ? "read" : "write",
+			curr_device, off, size);
 
 
-		if (i)
-			ret = nand_read(nand, off, &size, (u_char *)addr);
-		else
-			ret = nand_write(nand, off, &size, (u_char *)addr);
+		ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size,
+			     &total, (u_char*)addr);
 
 
-		printf(" %d bytes %s: %s\n", size,
-		       i ? "read" : "written", ret ? "ERROR" : "OK");
+		printf (" %d bytes %s: %s\n", total,
+			(cmd & NANDRW_READ) ? "read" : "written",
+			ret ? "ERROR" : "OK");
 
 
-		return ret == 0 ? 0 : 1;
-	}
-#ifdef CONFIG_MTD_NAND_UNSAFE
-	if (strcmp(cmd, "markbad") == 0 || strcmp(cmd, "biterr") == 0) {
-		if (argc < 3)
-			goto usage;
+		return ret;
+	} else if (strcmp(argv[1],"erase") == 0 &&
+		   (argc == 4 || strcmp("clean", argv[2]) == 0)) {
+		int clean = argc == 5;
+		ulong off = simple_strtoul(argv[2 + clean], NULL, 16);
+		ulong size = simple_strtoul(argv[3 + clean], NULL, 16);
+		int ret;
 
 
-		i = strcmp(cmd, "biterr") == 0;
+		printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
+			curr_device, off, size);
 
 
-		off = (int)simple_strtoul(argv[2], NULL, 16);
+		ret = nand_erase (nand_dev_desc + curr_device, off, size, clean);
 
 
-		if (i)
-			ret = nand_make_bit_error(nand, off);
-		else
-			ret = nand_mark_bad(nand, off);
+		printf("%s\n", ret ? "ERROR" : "OK");
 
 
-		return ret == 0 ? 0 : 1;
+		return ret;
+	} else {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		rcode = 1;
 	}
 	}
-#endif
 
 
-usage:
-	printf("Usage:\n%s\n", cmdtp->usage);
-	return 1;
+	return rcode;
+    }
 }
 }
 
 
-U_BOOT_CMD(nand, 5, 1, do_nand,
+U_BOOT_CMD(
+	nand,	5,	1,	do_nand,
 	"nand    - NAND sub-system\n",
 	"nand    - NAND sub-system\n",
-	"info                  - show available NAND devices\n"
-	"nand device [dev]     - show or set current device\n"
-	"nand read[.jffs2]     - addr off size\n"
-	"nand write[.jffs2]    - addr off size - read/write `size' bytes starting\n"
+	"info  - show available NAND devices\n"
+	"nand device [dev] - show or set current device\n"
+	"nand read[.jffs2[s]]  addr off size\n"
+	"nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
 	"    at offset `off' to/from memory address `addr'\n"
 	"    at offset `off' to/from memory address `addr'\n"
 	"nand erase [clean] [off size] - erase `size' bytes from\n"
 	"nand erase [clean] [off size] - erase `size' bytes from\n"
 	"    offset `off' (entire device if not specified)\n"
 	"    offset `off' (entire device if not specified)\n"
 	"nand bad - show bad blocks\n"
 	"nand bad - show bad blocks\n"
-	"nand dump[.oob] off - dump page\n"
-	"nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
-	"nand markbad off - mark bad block at offset (UNSAFE)\n"
-	"nand biterr off - make a bit error at offset (UNSAFE)\n");
+	"nand read.oob addr off size - read out-of-band data\n"
+	"nand write.oob addr off size - read out-of-band data\n"
+);
 
 
-int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
 {
 	char *boot_device = NULL;
 	char *boot_device = NULL;
 	char *ep;
 	char *ep;
 	int dev;
 	int dev;
-	int r;
-	ulong addr, cnt, offset = 0;
+	ulong cnt;
+	ulong addr;
+	ulong offset = 0;
 	image_header_t *hdr;
 	image_header_t *hdr;
-	nand_info_t *nand;
-
+	int rcode = 0;
 	switch (argc) {
 	switch (argc) {
 	case 1:
 	case 1:
 		addr = CFG_LOAD_ADDR;
 		addr = CFG_LOAD_ADDR;
-		boot_device = getenv("bootdevice");
+		boot_device = getenv ("bootdevice");
 		break;
 		break;
 	case 2:
 	case 2:
 		addr = simple_strtoul(argv[1], NULL, 16);
 		addr = simple_strtoul(argv[1], NULL, 16);
-		boot_device = getenv("bootdevice");
+		boot_device = getenv ("bootdevice");
 		break;
 		break;
 	case 3:
 	case 3:
 		addr = simple_strtoul(argv[1], NULL, 16);
 		addr = simple_strtoul(argv[1], NULL, 16);
@@ -334,53 +316,55 @@ int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 		offset = simple_strtoul(argv[3], NULL, 16);
 		offset = simple_strtoul(argv[3], NULL, 16);
 		break;
 		break;
 	default:
 	default:
-		printf("Usage:\n%s\n", cmdtp->usage);
-		SHOW_BOOT_PROGRESS(-1);
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		SHOW_BOOT_PROGRESS (-1);
 		return 1;
 		return 1;
 	}
 	}
 
 
 	if (!boot_device) {
 	if (!boot_device) {
-		puts("\n** No boot device **\n");
-		SHOW_BOOT_PROGRESS(-1);
+		puts ("\n** No boot device **\n");
+		SHOW_BOOT_PROGRESS (-1);
 		return 1;
 		return 1;
 	}
 	}
 
 
 	dev = simple_strtoul(boot_device, &ep, 16);
 	dev = simple_strtoul(boot_device, &ep, 16);
 
 
-	if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
-		printf("\n** Device %d not available\n", dev);
-		SHOW_BOOT_PROGRESS(-1);
+	if ((dev >= CFG_MAX_NAND_DEVICE) ||
+	    (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
+		printf ("\n** Device %d not available\n", dev);
+		SHOW_BOOT_PROGRESS (-1);
 		return 1;
 		return 1;
 	}
 	}
 
 
-	nand = &nand_info[dev];
-	printf("\nLoading from device %d: %s (offset 0x%lx)\n",
-	       dev, nand->name, offset);
+	printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
+		dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
+		offset);
 
 
-	cnt = nand->oobblock;
-	r = nand_read(nand, offset, &cnt, (u_char *) addr);
-	if (r) {
-		printf("** Read error on %d\n", dev);
-		SHOW_BOOT_PROGRESS(-1);
+	if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset,
+		    SECTORSIZE, NULL, (u_char *)addr)) {
+		printf ("** Read error on %d\n", dev);
+		SHOW_BOOT_PROGRESS (-1);
 		return 1;
 		return 1;
 	}
 	}
 
 
-	hdr = (image_header_t *) addr;
+	hdr = (image_header_t *)addr;
 
 
-	if (ntohl(hdr->ih_magic) != IH_MAGIC) {
-		printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
-		SHOW_BOOT_PROGRESS(-1);
-		return 1;
-	}
+	if (ntohl(hdr->ih_magic) == IH_MAGIC) {
 
 
-	print_image_hdr(hdr);
+		print_image_hdr (hdr);
 
 
-	cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
+		cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
+		cnt -= SECTORSIZE;
+	} else {
+		printf ("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
+		SHOW_BOOT_PROGRESS (-1);
+		return 1;
+	}
 
 
-	r = nand_read(nand, offset, &cnt, (u_char *) addr);
-	if (r) {
-		printf("** Read error on %d\n", dev);
-		SHOW_BOOT_PROGRESS(-1);
+	if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset + SECTORSIZE, cnt,
+		    NULL, (u_char *)(addr+SECTORSIZE))) {
+		printf ("** Read error on %d\n", dev);
+		SHOW_BOOT_PROGRESS (-1);
 		return 1;
 		return 1;
 	}
 	}
 
 
@@ -389,24 +373,1526 @@ int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 	load_addr = addr;
 	load_addr = addr;
 
 
 	/* Check if we should attempt an auto-start */
 	/* Check if we should attempt an auto-start */
-	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
+	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
 		char *local_args[2];
 		char *local_args[2];
-		extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
+		extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
 
 
 		local_args[0] = argv[0];
 		local_args[0] = argv[0];
 		local_args[1] = NULL;
 		local_args[1] = NULL;
 
 
-		printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
+		printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
+
+		do_bootm (cmdtp, 0, 1, local_args);
+		rcode = 1;
+	}
+	return rcode;
+}
+
+U_BOOT_CMD(
+	nboot,	4,	1,	do_nandboot,
+	"nboot   - boot from NAND device\n",
+	"loadAddr dev\n"
+);
 
 
-		do_bootm(cmdtp, 0, 1, local_args);
+/* returns 0 if block containing pos is OK:
+ *		valid erase block and
+ *		not marked bad, or no bad mark position is specified
+ * returns 1 if marked bad or otherwise invalid
+ */
+int check_block (struct nand_chip *nand, unsigned long pos)
+{
+	int retlen;
+	uint8_t oob_data;
+	uint16_t oob_data16[6];
+	int page0 = pos & (-nand->erasesize);
+	int page1 = page0 + nand->oobblock;
+	int badpos = oob_config.badblock_pos;
+
+	if (pos >= nand->totlen)
 		return 1;
 		return 1;
+
+	if (badpos < 0)
+		return 0;	/* no way to check, assume OK */
+
+	if (nand->bus16) {
+		if (nand_read_oob(nand, (page0 + 0), 12, &retlen, (uint8_t *)oob_data16)
+		    || (oob_data16[2] & 0xff00) != 0xff00)
+			return 1;
+		if (nand_read_oob(nand, (page1 + 0), 12, &retlen, (uint8_t *)oob_data16)
+		    || (oob_data16[2] & 0xff00) != 0xff00)
+			return 1;
+	} else {
+		/* Note - bad block marker can be on first or second page */
+		if (nand_read_oob(nand, page0 + badpos, 1, &retlen, &oob_data)
+		    || oob_data != 0xff
+		    || nand_read_oob (nand, page1 + badpos, 1, &retlen, &oob_data)
+		    || oob_data != 0xff)
+			return 1;
 	}
 	}
+
 	return 0;
 	return 0;
 }
 }
 
 
-U_BOOT_CMD(nboot, 4, 1, do_nandboot,
-	"nboot   - boot from NAND device\n", "loadAddr dev\n");
+/* print bad blocks in NAND flash */
+static void nand_print_bad(struct nand_chip* nand)
+{
+	unsigned long pos;
+
+	for (pos = 0; pos < nand->totlen; pos += nand->erasesize) {
+		if (check_block(nand, pos))
+			printf(" 0x%8.8lx\n", pos);
+	}
+	puts("\n");
+}
+
+/* cmd: 0: NANDRW_WRITE			write, fail on bad block
+ *	1: NANDRW_READ			read, fail on bad block
+ *	2: NANDRW_WRITE | NANDRW_JFFS2	write, skip bad blocks
+ *	3: NANDRW_READ | NANDRW_JFFS2	read, data all 0xff for bad blocks
+ *      7: NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP read, skip bad blocks
+ */
+int nand_rw (struct nand_chip* nand, int cmd,
+	    size_t start, size_t len,
+	    size_t * retlen, u_char * buf)
+{
+	int ret = 0, n, total = 0;
+	char eccbuf[6];
+	/* eblk (once set) is the start of the erase block containing the
+	 * data being processed.
+	 */
+	unsigned long eblk = ~0;	/* force mismatch on first pass */
+	unsigned long erasesize = nand->erasesize;
+
+	while (len) {
+		if ((start & (-erasesize)) != eblk) {
+			/* have crossed into new erase block, deal with
+			 * it if it is sure marked bad.
+			 */
+			eblk = start & (-erasesize); /* start of block */
+			if (check_block(nand, eblk)) {
+				if (cmd == (NANDRW_READ | NANDRW_JFFS2)) {
+					while (len > 0 &&
+					       start - eblk < erasesize) {
+						*(buf++) = 0xff;
+						++start;
+						++total;
+						--len;
+					}
+					continue;
+				} else if (cmd == (NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP)) {
+					start += erasesize;
+					continue;
+				} else if (cmd == (NANDRW_WRITE | NANDRW_JFFS2)) {
+					/* skip bad block */
+					start += erasesize;
+					continue;
+				} else {
+					ret = 1;
+					break;
+				}
+			}
+		}
+		/* The ECC will not be calculated correctly if
+		   less than 512 is written or read */
+		/* Is request at least 512 bytes AND it starts on a proper boundry */
+		if((start != ROUND_DOWN(start, 0x200)) || (len < 0x200))
+			printf("Warning block writes should be at least 512 bytes and start on a 512 byte boundry\n");
+
+		if (cmd & NANDRW_READ) {
+			ret = nand_read_ecc(nand, start,
+					   min(len, eblk + erasesize - start),
+					   &n, (u_char*)buf, eccbuf);
+		} else {
+			ret = nand_write_ecc(nand, start,
+					    min(len, eblk + erasesize - start),
+					    &n, (u_char*)buf, eccbuf);
+		}
+
+		if (ret)
+			break;
+
+		start  += n;
+		buf   += n;
+		total += n;
+		len   -= n;
+	}
+	if (retlen)
+		*retlen = total;
+
+	return ret;
+}
+
+static void nand_print(struct nand_chip *nand)
+{
+	if (nand->numchips > 1) {
+		printf("%s at 0x%lx,\n"
+		       "\t  %d chips %s, size %d MB, \n"
+		       "\t  total size %ld MB, sector size %ld kB\n",
+		       nand->name, nand->IO_ADDR, nand->numchips,
+		       nand->chips_name, 1 << (nand->chipshift - 20),
+		       nand->totlen >> 20, nand->erasesize >> 10);
+	}
+	else {
+		printf("%s at 0x%lx (", nand->chips_name, nand->IO_ADDR);
+		print_size(nand->totlen, ", ");
+		print_size(nand->erasesize, " sector)\n");
+	}
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int NanD_WaitReady(struct nand_chip *nand, int ale_wait)
+{
+	/* This is inline, to optimise the common case, where it's ready instantly */
+	int ret = 0;
+
+#ifdef NAND_NO_RB	/* in config file, shorter delays currently wrap accesses */
+	if(ale_wait)
+		NAND_WAIT_READY(nand);	/* do the worst case 25us wait */
+	else
+		udelay(10);
+#else	/* has functional r/b signal */
+	NAND_WAIT_READY(nand);
+#endif
+	return ret;
+}
+
+/* NanD_Command: Send a flash command to the flash chip */
+
+static inline int NanD_Command(struct nand_chip *nand, unsigned char command)
+{
+	unsigned long nandptr = nand->IO_ADDR;
+
+	/* Assert the CLE (Command Latch Enable) line to the flash chip */
+	NAND_CTL_SETCLE(nandptr);
+
+	/* Send the command */
+	WRITE_NAND_COMMAND(command, nandptr);
+
+	/* Lower the CLE line */
+	NAND_CTL_CLRCLE(nandptr);
+
+#ifdef NAND_NO_RB
+	if(command == NAND_CMD_RESET){
+		u_char ret_val;
+		NanD_Command(nand, NAND_CMD_STATUS);
+		do {
+			ret_val = READ_NAND(nandptr);/* wait till ready */
+		} while((ret_val & 0x40) != 0x40);
+	}
+#endif
+	return NanD_WaitReady(nand, 0);
+}
+
+/* NanD_Address: Set the current address for the flash chip */
+
+static int NanD_Address(struct nand_chip *nand, int numbytes, unsigned long ofs)
+{
+	unsigned long nandptr;
+	int i;
+
+	nandptr = nand->IO_ADDR;
+
+	/* Assert the ALE (Address Latch Enable) line to the flash chip */
+	NAND_CTL_SETALE(nandptr);
+
+	/* Send the address */
+	/* Devices with 256-byte page are addressed as:
+	 * Column (bits 0-7), Page (bits 8-15, 16-23, 24-31)
+	 * there is no device on the market with page256
+	 * and more than 24 bits.
+	 * Devices with 512-byte page are addressed as:
+	 * Column (bits 0-7), Page (bits 9-16, 17-24, 25-31)
+	 * 25-31 is sent only if the chip support it.
+	 * bit 8 changes the read command to be sent
+	 * (NAND_CMD_READ0 or NAND_CMD_READ1).
+	 */
+
+	if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE)
+		WRITE_NAND_ADDRESS(ofs, nandptr);
+
+	ofs = ofs >> nand->page_shift;
+
+	if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) {
+		for (i = 0; i < nand->pageadrlen; i++, ofs = ofs >> 8) {
+			WRITE_NAND_ADDRESS(ofs, nandptr);
+		}
+	}
+
+	/* Lower the ALE line */
+	NAND_CTL_CLRALE(nandptr);
+
+	/* Wait for the chip to respond */
+	return NanD_WaitReady(nand, 1);
+}
+
+/* NanD_SelectChip: Select a given flash chip within the current floor */
+
+static inline int NanD_SelectChip(struct nand_chip *nand, int chip)
+{
+	/* Wait for it to be ready */
+	return NanD_WaitReady(nand, 0);
+}
+
+/* NanD_IdentChip: Identify a given NAND chip given {floor,chip} */
+
+static int NanD_IdentChip(struct nand_chip *nand, int floor, int chip)
+{
+	int mfr, id, i;
+
+	NAND_ENABLE_CE(nand);  /* set pin low */
+	/* Reset the chip */
+	if (NanD_Command(nand, NAND_CMD_RESET)) {
+#ifdef NAND_DEBUG
+		printf("NanD_Command (reset) for %d,%d returned true\n",
+		       floor, chip);
+#endif
+		NAND_DISABLE_CE(nand);  /* set pin high */
+		return 0;
+	}
+
+	/* Read the NAND chip ID: 1. Send ReadID command */
+	if (NanD_Command(nand, NAND_CMD_READID)) {
+#ifdef NAND_DEBUG
+		printf("NanD_Command (ReadID) for %d,%d returned true\n",
+		       floor, chip);
+#endif
+		NAND_DISABLE_CE(nand);  /* set pin high */
+		return 0;
+	}
+
+	/* Read the NAND chip ID: 2. Send address byte zero */
+	NanD_Address(nand, ADDR_COLUMN, 0);
+
+	/* Read the manufacturer and device id codes from the device */
+
+	mfr = READ_NAND(nand->IO_ADDR);
+
+	id = READ_NAND(nand->IO_ADDR);
+
+	NAND_DISABLE_CE(nand);  /* set pin high */
+
+#ifdef NAND_DEBUG
+	printf("NanD_Command (ReadID) got %x %x\n", mfr, id);
+#endif
+	if (mfr == 0xff || mfr == 0) {
+		/* No response - return failure */
+		return 0;
+	}
+
+	/* Check it's the same as the first chip we identified.
+	 * M-Systems say that any given nand_chip device should only
+	 * contain _one_ type of flash part, although that's not a
+	 * hardware restriction. */
+	if (nand->mfr) {
+		if (nand->mfr == mfr && nand->id == id) {
+			return 1;	/* This is another the same the first */
+		} else {
+			printf("Flash chip at floor %d, chip %d is different:\n",
+			       floor, chip);
+		}
+	}
+
+	/* Print and store the manufacturer and ID codes. */
+	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+		if (mfr == nand_flash_ids[i].manufacture_id &&
+		    id == nand_flash_ids[i].model_id) {
+#ifdef NAND_DEBUG
+			printf("Flash chip found:\n\t Manufacturer ID: 0x%2.2X, "
+			       "Chip ID: 0x%2.2X (%s)\n", mfr, id,
+			       nand_flash_ids[i].name);
+#endif
+			if (!nand->mfr) {
+				nand->mfr = mfr;
+				nand->id = id;
+				nand->chipshift =
+				    nand_flash_ids[i].chipshift;
+				nand->page256 = nand_flash_ids[i].page256;
+				nand->eccsize = 256;
+				if (nand->page256) {
+					nand->oobblock = 256;
+					nand->oobsize = 8;
+					nand->page_shift = 8;
+				} else {
+					nand->oobblock = 512;
+					nand->oobsize = 16;
+					nand->page_shift = 9;
+				}
+				nand->pageadrlen = nand_flash_ids[i].pageadrlen;
+				nand->erasesize  = nand_flash_ids[i].erasesize;
+				nand->chips_name = nand_flash_ids[i].name;
+				nand->bus16	 = nand_flash_ids[i].bus16;
+ 				return 1;
+			}
+			return 0;
+		}
+	}
+
+
+#ifdef NAND_DEBUG
+	/* We haven't fully identified the chip. Print as much as we know. */
+	printf("Unknown flash chip found: %2.2X %2.2X\n",
+	       id, mfr);
+#endif
+
+	return 0;
+}
+
+/* NanD_ScanChips: Find all NAND chips present in a nand_chip, and identify them */
+
+static void NanD_ScanChips(struct nand_chip *nand)
+{
+	int floor, chip;
+	int numchips[NAND_MAX_FLOORS];
+	int maxchips = NAND_MAX_CHIPS;
+	int ret = 1;
+
+	nand->numchips = 0;
+	nand->mfr = 0;
+	nand->id = 0;
+
+
+	/* For each floor, find the number of valid chips it contains */
+	for (floor = 0; floor < NAND_MAX_FLOORS; floor++) {
+		ret = 1;
+		numchips[floor] = 0;
+		for (chip = 0; chip < maxchips && ret != 0; chip++) {
+
+			ret = NanD_IdentChip(nand, floor, chip);
+			if (ret) {
+				numchips[floor]++;
+				nand->numchips++;
+			}
+		}
+	}
+
+	/* If there are none at all that we recognise, bail */
+	if (!nand->numchips) {
+#ifdef NAND_DEBUG
+		puts ("No NAND flash chips recognised.\n");
+#endif
+		return;
+	}
+
+	/* Allocate an array to hold the information for each chip */
+	nand->chips = malloc(sizeof(struct Nand) * nand->numchips);
+	if (!nand->chips) {
+		puts ("No memory for allocating chip info structures\n");
+		return;
+	}
+
+	ret = 0;
+
+	/* Fill out the chip array with {floor, chipno} for each
+	 * detected chip in the device. */
+	for (floor = 0; floor < NAND_MAX_FLOORS; floor++) {
+		for (chip = 0; chip < numchips[floor]; chip++) {
+			nand->chips[ret].floor = floor;
+			nand->chips[ret].chip = chip;
+			nand->chips[ret].curadr = 0;
+			nand->chips[ret].curmode = 0x50;
+			ret++;
+		}
+	}
+
+	/* Calculate and print the total size of the device */
+	nand->totlen = nand->numchips * (1 << nand->chipshift);
+
+#ifdef NAND_DEBUG
+	printf("%d flash chips found. Total nand_chip size: %ld MB\n",
+	       nand->numchips, nand->totlen >> 20);
+#endif
+}
+
+/* we need to be fast here, 1 us per read translates to 1 second per meg */
+static void NanD_ReadBuf (struct nand_chip *nand, u_char * data_buf, int cntr)
+{
+	unsigned long nandptr = nand->IO_ADDR;
+
+	NanD_Command (nand, NAND_CMD_READ0);
+
+	if (nand->bus16) {
+		u16 val;
+
+		while (cntr >= 16) {
+			val = READ_NAND (nandptr);
+			*data_buf++ = val & 0xff;
+			*data_buf++ = val >> 8;
+			val = READ_NAND (nandptr);
+			*data_buf++ = val & 0xff;
+			*data_buf++ = val >> 8;
+			val = READ_NAND (nandptr);
+			*data_buf++ = val & 0xff;
+			*data_buf++ = val >> 8;
+			val = READ_NAND (nandptr);
+			*data_buf++ = val & 0xff;
+			*data_buf++ = val >> 8;
+			val = READ_NAND (nandptr);
+			*data_buf++ = val & 0xff;
+			*data_buf++ = val >> 8;
+			val = READ_NAND (nandptr);
+			*data_buf++ = val & 0xff;
+			*data_buf++ = val >> 8;
+			val = READ_NAND (nandptr);
+			*data_buf++ = val & 0xff;
+			*data_buf++ = val >> 8;
+			val = READ_NAND (nandptr);
+			*data_buf++ = val & 0xff;
+			*data_buf++ = val >> 8;
+			cntr -= 16;
+		}
+
+		while (cntr > 0) {
+			val = READ_NAND (nandptr);
+			*data_buf++ = val & 0xff;
+			*data_buf++ = val >> 8;
+			cntr -= 2;
+		}
+	} else {
+		while (cntr >= 16) {
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			*data_buf++ = READ_NAND (nandptr);
+			cntr -= 16;
+		}
+
+		while (cntr > 0) {
+			*data_buf++ = READ_NAND (nandptr);
+			cntr--;
+		}
+	}
+}
+
+/*
+ * NAND read with ECC
+ */
+static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
+		 size_t * retlen, u_char *buf, u_char *ecc_code)
+{
+	int col, page;
+	int ecc_status = 0;
+#ifdef CONFIG_MTD_NAND_ECC
+	int j;
+	int ecc_failed = 0;
+	u_char *data_poi;
+	u_char ecc_calc[6];
+#endif
+
+	/* Do not allow reads past end of device */
+	if ((start + len) > nand->totlen) {
+		printf ("%s: Attempt read beyond end of device %x %x %x\n",
+			__FUNCTION__, (uint) start, (uint) len, (uint) nand->totlen);
+		*retlen = 0;
+		return -1;
+	}
+
+	/* First we calculate the starting page */
+	/*page = shr(start, nand->page_shift);*/
+	page = start >> nand->page_shift;
+
+	/* Get raw starting column */
+	col = start & (nand->oobblock - 1);
+
+	/* Initialize return value */
+	*retlen = 0;
+
+	/* Select the NAND device */
+	NAND_ENABLE_CE(nand);  /* set pin low */
+
+	/* Loop until all data read */
+	while (*retlen < len) {
+
+#ifdef CONFIG_MTD_NAND_ECC
+		/* Do we have this page in cache ? */
+		if (nand->cache_page == page)
+			goto readdata;
+		/* Send the read command */
+		NanD_Command(nand, NAND_CMD_READ0);
+		if (nand->bus16) {
+ 			NanD_Address(nand, ADDR_COLUMN_PAGE,
+				     (page << nand->page_shift) + (col >> 1));
+		} else {
+ 			NanD_Address(nand, ADDR_COLUMN_PAGE,
+				     (page << nand->page_shift) + col);
+		}
+
+		/* Read in a page + oob data */
+		NanD_ReadBuf(nand, nand->data_buf, nand->oobblock + nand->oobsize);
+
+		/* copy data into cache, for read out of cache and if ecc fails */
+		if (nand->data_cache) {
+			memcpy (nand->data_cache, nand->data_buf,
+				nand->oobblock + nand->oobsize);
+		}
+
+		/* Pick the ECC bytes out of the oob data */
+		for (j = 0; j < 6; j++) {
+			ecc_code[j] = nand->data_buf[(nand->oobblock + oob_config.ecc_pos[j])];
+		}
+
+		/* Calculate the ECC and verify it */
+		/* If block was not written with ECC, skip ECC */
+		if (oob_config.eccvalid_pos != -1 &&
+		    (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0x0f) != 0x0f) {
+
+			nand_calculate_ecc (&nand->data_buf[0], &ecc_calc[0]);
+			switch (nand_correct_data (&nand->data_buf[0], &ecc_code[0], &ecc_calc[0])) {
+			case -1:
+				printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page);
+				ecc_failed++;
+				break;
+			case 1:
+			case 2:	/* transfer ECC corrected data to cache */
+				if (nand->data_cache)
+					memcpy (nand->data_cache, nand->data_buf, 256);
+				break;
+			}
+		}
+
+		if (oob_config.eccvalid_pos != -1 &&
+		    nand->oobblock == 512 && (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0xf0) != 0xf0) {
+
+			nand_calculate_ecc (&nand->data_buf[256], &ecc_calc[3]);
+			switch (nand_correct_data (&nand->data_buf[256], &ecc_code[3], &ecc_calc[3])) {
+			case -1:
+				printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page);
+				ecc_failed++;
+				break;
+			case 1:
+			case 2:	/* transfer ECC corrected data to cache */
+				if (nand->data_cache)
+					memcpy (&nand->data_cache[256], &nand->data_buf[256], 256);
+				break;
+			}
+		}
+readdata:
+		/* Read the data from ECC data buffer into return buffer */
+		data_poi = (nand->data_cache) ? nand->data_cache : nand->data_buf;
+		data_poi += col;
+		if ((*retlen + (nand->oobblock - col)) >= len) {
+			memcpy (buf + *retlen, data_poi, len - *retlen);
+			*retlen = len;
+		} else {
+			memcpy (buf + *retlen, data_poi,  nand->oobblock - col);
+			*retlen += nand->oobblock - col;
+		}
+		/* Set cache page address, invalidate, if ecc_failed */
+		nand->cache_page = (nand->data_cache && !ecc_failed) ? page : -1;
+
+		ecc_status += ecc_failed;
+		ecc_failed = 0;
+
+#else
+		/* Send the read command */
+		NanD_Command(nand, NAND_CMD_READ0);
+		if (nand->bus16) {
+			NanD_Address(nand, ADDR_COLUMN_PAGE,
+				     (page << nand->page_shift) + (col >> 1));
+		} else {
+			NanD_Address(nand, ADDR_COLUMN_PAGE,
+				     (page << nand->page_shift) + col);
+		}
+
+		/* Read the data directly into the return buffer */
+		if ((*retlen + (nand->oobblock - col)) >= len) {
+			NanD_ReadBuf(nand, buf + *retlen, len - *retlen);
+			*retlen = len;
+			/* We're done */
+			continue;
+		} else {
+			NanD_ReadBuf(nand, buf + *retlen, nand->oobblock - col);
+			*retlen += nand->oobblock - col;
+			}
+#endif
+		/* For subsequent reads align to page boundary. */
+		col = 0;
+		/* Increment page address */
+		page++;
+	}
+
+	/* De-select the NAND device */
+	NAND_DISABLE_CE(nand);  /* set pin high */
+
+	/*
+	 * Return success, if no ECC failures, else -EIO
+	 * fs driver will take care of that, because
+	 * retlen == desired len and result == -EIO
+	 */
+	return ecc_status ? -1 : 0;
+}
+
+/*
+ *	Nand_page_program function is used for write and writev !
+ */
+static int nand_write_page (struct nand_chip *nand,
+			    int page, int col, int last, u_char * ecc_code)
+{
+
+	int i;
+	unsigned long nandptr = nand->IO_ADDR;
+
+#ifdef CONFIG_MTD_NAND_ECC
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+	int ecc_bytes = (nand->oobblock == 512) ? 6 : 3;
+#endif
+#endif
+	/* pad oob area */
+	for (i = nand->oobblock; i < nand->oobblock + nand->oobsize; i++)
+		nand->data_buf[i] = 0xff;
+
+#ifdef CONFIG_MTD_NAND_ECC
+	/* Zero out the ECC array */
+	for (i = 0; i < 6; i++)
+		ecc_code[i] = 0x00;
+
+	/* Read back previous written data, if col > 0 */
+	if (col) {
+		NanD_Command (nand, NAND_CMD_READ0);
+		if (nand->bus16) {
+			NanD_Address (nand, ADDR_COLUMN_PAGE,
+				      (page << nand->page_shift) + (col >> 1));
+		} else {
+			NanD_Address (nand, ADDR_COLUMN_PAGE,
+				      (page << nand->page_shift) + col);
+		}
+
+		if (nand->bus16) {
+			u16 val;
+
+			for (i = 0; i < col; i += 2) {
+				val = READ_NAND (nandptr);
+				nand->data_buf[i] = val & 0xff;
+				nand->data_buf[i + 1] = val >> 8;
+			}
+		} else {
+			for (i = 0; i < col; i++)
+				nand->data_buf[i] = READ_NAND (nandptr);
+		}
+	}
+
+	/* Calculate and write the ECC if we have enough data */
+	if ((col < nand->eccsize) && (last >= nand->eccsize)) {
+		nand_calculate_ecc (&nand->data_buf[0], &(ecc_code[0]));
+		for (i = 0; i < 3; i++) {
+			nand->data_buf[(nand->oobblock +
+					oob_config.ecc_pos[i])] = ecc_code[i];
+		}
+		if (oob_config.eccvalid_pos != -1) {
+			nand->data_buf[nand->oobblock +
+				       oob_config.eccvalid_pos] = 0xf0;
+		}
+	}
+
+	/* Calculate and write the second ECC if we have enough data */
+	if ((nand->oobblock == 512) && (last == nand->oobblock)) {
+		nand_calculate_ecc (&nand->data_buf[256], &(ecc_code[3]));
+		for (i = 3; i < 6; i++) {
+			nand->data_buf[(nand->oobblock +
+					oob_config.ecc_pos[i])] = ecc_code[i];
+		}
+		if (oob_config.eccvalid_pos != -1) {
+			nand->data_buf[nand->oobblock +
+				       oob_config.eccvalid_pos] &= 0x0f;
+		}
+	}
+#endif
+	/* Prepad for partial page programming !!! */
+	for (i = 0; i < col; i++)
+		nand->data_buf[i] = 0xff;
+
+	/* Postpad for partial page programming !!! oob is already padded */
+	for (i = last; i < nand->oobblock; i++)
+		nand->data_buf[i] = 0xff;
+
+	/* Send command to begin auto page programming */
+	NanD_Command (nand, NAND_CMD_READ0);
+	NanD_Command (nand, NAND_CMD_SEQIN);
+	if (nand->bus16) {
+		NanD_Address (nand, ADDR_COLUMN_PAGE,
+			      (page << nand->page_shift) + (col >> 1));
+	} else {
+		NanD_Address (nand, ADDR_COLUMN_PAGE,
+			      (page << nand->page_shift) + col);
+	}
+
+	/* Write out complete page of data */
+	if (nand->bus16) {
+		for (i = 0; i < (nand->oobblock + nand->oobsize); i += 2) {
+			WRITE_NAND (nand->data_buf[i] +
+				    (nand->data_buf[i + 1] << 8),
+				    nand->IO_ADDR);
+		}
+	} else {
+		for (i = 0; i < (nand->oobblock + nand->oobsize); i++)
+			WRITE_NAND (nand->data_buf[i], nand->IO_ADDR);
+	}
+
+	/* Send command to actually program the data */
+	NanD_Command (nand, NAND_CMD_PAGEPROG);
+	NanD_Command (nand, NAND_CMD_STATUS);
+#ifdef NAND_NO_RB
+	{
+		u_char ret_val;
+
+		do {
+			ret_val = READ_NAND (nandptr);	/* wait till ready */
+		} while ((ret_val & 0x40) != 0x40);
+	}
+#endif
+	/* See if device thinks it succeeded */
+	if (READ_NAND (nand->IO_ADDR) & 0x01) {
+		printf ("%s: Failed write, page 0x%08x, ", __FUNCTION__,
+			page);
+		return -1;
+	}
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+	/*
+	 * The NAND device assumes that it is always writing to
+	 * a cleanly erased page. Hence, it performs its internal
+	 * write verification only on bits that transitioned from
+	 * 1 to 0. The device does NOT verify the whole page on a
+	 * byte by byte basis. It is possible that the page was
+	 * not completely erased or the page is becoming unusable
+	 * due to wear. The read with ECC would catch the error
+	 * later when the ECC page check fails, but we would rather
+	 * catch it early in the page write stage. Better to write
+	 * no data than invalid data.
+	 */
+
+	/* Send command to read back the page */
+	if (col < nand->eccsize)
+		NanD_Command (nand, NAND_CMD_READ0);
+	else
+		NanD_Command (nand, NAND_CMD_READ1);
+	if (nand->bus16) {
+		NanD_Address (nand, ADDR_COLUMN_PAGE,
+			      (page << nand->page_shift) + (col >> 1));
+	} else {
+		NanD_Address (nand, ADDR_COLUMN_PAGE,
+			      (page << nand->page_shift) + col);
+	}
+
+	/* Loop through and verify the data */
+	if (nand->bus16) {
+		for (i = col; i < last; i = +2) {
+			if ((nand->data_buf[i] +
+			     (nand->data_buf[i + 1] << 8)) != READ_NAND (nand->IO_ADDR)) {
+				printf ("%s: Failed write verify, page 0x%08x ",
+					__FUNCTION__, page);
+				return -1;
+			}
+		}
+	} else {
+		for (i = col; i < last; i++) {
+			if (nand->data_buf[i] != READ_NAND (nand->IO_ADDR)) {
+				printf ("%s: Failed write verify, page 0x%08x ",
+					__FUNCTION__, page);
+				return -1;
+			}
+		}
+	}
+
+#ifdef CONFIG_MTD_NAND_ECC
+	/*
+	 * We also want to check that the ECC bytes wrote
+	 * correctly for the same reasons stated above.
+	 */
+	NanD_Command (nand, NAND_CMD_READOOB);
+	if (nand->bus16) {
+		NanD_Address (nand, ADDR_COLUMN_PAGE,
+			      (page << nand->page_shift) + (col >> 1));
+	} else {
+		NanD_Address (nand, ADDR_COLUMN_PAGE,
+			      (page << nand->page_shift) + col);
+	}
+	if (nand->bus16) {
+		for (i = 0; i < nand->oobsize; i += 2) {
+			u16 val;
+
+			val = READ_NAND (nand->IO_ADDR);
+			nand->data_buf[i] = val & 0xff;
+			nand->data_buf[i + 1] = val >> 8;
+		}
+	} else {
+		for (i = 0; i < nand->oobsize; i++) {
+			nand->data_buf[i] = READ_NAND (nand->IO_ADDR);
+		}
+	}
+	for (i = 0; i < ecc_bytes; i++) {
+		if ((nand->data_buf[(oob_config.ecc_pos[i])] != ecc_code[i]) && ecc_code[i]) {
+			printf ("%s: Failed ECC write "
+				"verify, page 0x%08x, "
+				"%6i bytes were succesful\n",
+				__FUNCTION__, page, i);
+			return -1;
+		}
+	}
+#endif	/* CONFIG_MTD_NAND_ECC */
+#endif	/* CONFIG_MTD_NAND_VERIFY_WRITE */
+	return 0;
+}
+
+static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
+			   size_t * retlen, const u_char * buf, u_char * ecc_code)
+{
+	int i, page, col, cnt, ret = 0;
+
+	/* Do not allow write past end of device */
+	if ((to + len) > nand->totlen) {
+		printf ("%s: Attempt to write past end of page\n", __FUNCTION__);
+		return -1;
+	}
+
+	/* Shift to get page */
+	page = ((int) to) >> nand->page_shift;
+
+	/* Get the starting column */
+	col = to & (nand->oobblock - 1);
+
+	/* Initialize return length value */
+	*retlen = 0;
+
+	/* Select the NAND device */
+#ifdef CONFIG_OMAP1510
+	archflashwp(0,0);
+#endif
+#ifdef CFG_NAND_WP
+	NAND_WP_OFF();
+#endif
+
+    	NAND_ENABLE_CE(nand);  /* set pin low */
+
+	/* Check the WP bit */
+	NanD_Command(nand, NAND_CMD_STATUS);
+	if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
+		printf ("%s: Device is write protected!!!\n", __FUNCTION__);
+		ret = -1;
+		goto out;
+	}
+
+	/* Loop until all data is written */
+	while (*retlen < len) {
+		/* Invalidate cache, if we write to this page */
+		if (nand->cache_page == page)
+			nand->cache_page = -1;
+
+		/* Write data into buffer */
+		if ((col + len) >= nand->oobblock) {
+			for (i = col, cnt = 0; i < nand->oobblock; i++, cnt++) {
+				nand->data_buf[i] = buf[(*retlen + cnt)];
+			}
+		} else {
+			for (i = col, cnt = 0; cnt < (len - *retlen); i++, cnt++) {
+				nand->data_buf[i] = buf[(*retlen + cnt)];
+			}
+		}
+		/* We use the same function for write and writev !) */
+		ret = nand_write_page (nand, page, col, i, ecc_code);
+		if (ret)
+			goto out;
+
+		/* Next data start at page boundary */
+		col = 0;
+
+		/* Update written bytes count */
+		*retlen += cnt;
+
+		/* Increment page address */
+		page++;
+	}
+
+	/* Return happy */
+	*retlen = len;
+
+out:
+	/* De-select the NAND device */
+	NAND_DISABLE_CE(nand);  /* set pin high */
+#ifdef CONFIG_OMAP1510
+    	archflashwp(0,1);
+#endif
+#ifdef CFG_NAND_WP
+	NAND_WP_ON();
+#endif
+
+	return ret;
+}
+
+/* read from the 16 bytes of oob data that correspond to a 512 byte
+ * page or 2 256-byte pages.
+ */
+static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
+			 size_t * retlen, u_char * buf)
+{
+	int len256 = 0;
+	struct Nand *mychip;
+	int ret = 0;
+
+	mychip = &nand->chips[ofs >> nand->chipshift];
+
+	/* update address for 2M x 8bit devices. OOB starts on the second */
+	/* page to maintain compatibility with nand_read_ecc. */
+	if (nand->page256) {
+		if (!(ofs & 0x8))
+			ofs += 0x100;
+		else
+			ofs -= 0x8;
+	}
+
+	NAND_ENABLE_CE(nand);  /* set pin low */
+	NanD_Command(nand, NAND_CMD_READOOB);
+	if (nand->bus16) {
+ 		NanD_Address(nand, ADDR_COLUMN_PAGE,
+			     ((ofs >> nand->page_shift) << nand->page_shift) +
+ 				((ofs & (nand->oobblock - 1)) >> 1));
+	} else {
+		NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
+	}
+
+	/* treat crossing 8-byte OOB data for 2M x 8bit devices */
+	/* Note: datasheet says it should automaticaly wrap to the */
+	/*       next OOB block, but it didn't work here. mf.      */
+	if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
+		len256 = (ofs | 0x7) + 1 - ofs;
+		NanD_ReadBuf(nand, buf, len256);
+
+		NanD_Command(nand, NAND_CMD_READOOB);
+		NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff));
+	}
+
+	NanD_ReadBuf(nand, &buf[len256], len - len256);
+
+	*retlen = len;
+	/* Reading the full OOB data drops us off of the end of the page,
+	 * causing the flash device to go into busy mode, so we need
+	 * to wait until ready 11.4.1 and Toshiba TC58256FT nands */
+
+	ret = NanD_WaitReady(nand, 1);
+	NAND_DISABLE_CE(nand);  /* set pin high */
+
+	return ret;
+
+}
+
+/* write to the 16 bytes of oob data that correspond to a 512 byte
+ * page or 2 256-byte pages.
+ */
+static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
+		  size_t * retlen, const u_char * buf)
+{
+	int len256 = 0;
+	int i;
+	unsigned long nandptr = nand->IO_ADDR;
+
+#ifdef PSYCHO_DEBUG
+	printf("nand_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",
+	       (long)ofs, len, buf[0], buf[1], buf[2], buf[3],
+	       buf[8], buf[9], buf[14],buf[15]);
+#endif
+
+	NAND_ENABLE_CE(nand);  /* set pin low to enable chip */
+
+	/* Reset the chip */
+	NanD_Command(nand, NAND_CMD_RESET);
+
+	/* issue the Read2 command to set the pointer to the Spare Data Area. */
+	NanD_Command(nand, NAND_CMD_READOOB);
+	if (nand->bus16) {
+ 		NanD_Address(nand, ADDR_COLUMN_PAGE,
+			     ((ofs >> nand->page_shift) << nand->page_shift) +
+ 				((ofs & (nand->oobblock - 1)) >> 1));
+	} else {
+ 		NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
+	}
+
+	/* update address for 2M x 8bit devices. OOB starts on the second */
+	/* page to maintain compatibility with nand_read_ecc. */
+	if (nand->page256) {
+		if (!(ofs & 0x8))
+			ofs += 0x100;
+		else
+			ofs -= 0x8;
+	}
+
+	/* issue the Serial Data In command to initial the Page Program process */
+	NanD_Command(nand, NAND_CMD_SEQIN);
+	if (nand->bus16) {
+ 		NanD_Address(nand, ADDR_COLUMN_PAGE,
+			     ((ofs >> nand->page_shift) << nand->page_shift) +
+ 				((ofs & (nand->oobblock - 1)) >> 1));
+	} else {
+ 		NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
+	}
+
+	/* treat crossing 8-byte OOB data for 2M x 8bit devices */
+	/* Note: datasheet says it should automaticaly wrap to the */
+	/*       next OOB block, but it didn't work here. mf.      */
+	if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
+		len256 = (ofs | 0x7) + 1 - ofs;
+		for (i = 0; i < len256; i++)
+			WRITE_NAND(buf[i], nandptr);
+
+		NanD_Command(nand, NAND_CMD_PAGEPROG);
+		NanD_Command(nand, NAND_CMD_STATUS);
+#ifdef NAND_NO_RB
+   		{ u_char ret_val;
+			do {
+				ret_val = READ_NAND(nandptr); /* wait till ready */
+			} while ((ret_val & 0x40) != 0x40);
+		}
+#endif
+		if (READ_NAND(nandptr) & 1) {
+			puts ("Error programming oob data\n");
+			/* There was an error */
+			NAND_DISABLE_CE(nand);  /* set pin high */
+			*retlen = 0;
+			return -1;
+		}
+		NanD_Command(nand, NAND_CMD_SEQIN);
+		NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff));
+	}
+
+	if (nand->bus16) {
+		for (i = len256; i < len; i += 2) {
+			WRITE_NAND(buf[i] + (buf[i+1] << 8), nandptr);
+		}
+	} else {
+		for (i = len256; i < len; i++)
+			WRITE_NAND(buf[i], nandptr);
+	}
+
+	NanD_Command(nand, NAND_CMD_PAGEPROG);
+	NanD_Command(nand, NAND_CMD_STATUS);
+#ifdef NAND_NO_RB
+	{	u_char ret_val;
+		do {
+			ret_val = READ_NAND(nandptr); /* wait till ready */
+		} while ((ret_val & 0x40) != 0x40);
+	}
+#endif
+	if (READ_NAND(nandptr) & 1) {
+		puts ("Error programming oob data\n");
+		/* There was an error */
+		NAND_DISABLE_CE(nand);  /* set pin high */
+		*retlen = 0;
+		return -1;
+	}
+
+	NAND_DISABLE_CE(nand);  /* set pin high */
+	*retlen = len;
+	return 0;
+
+}
+
+int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean)
+{
+	/* This is defined as a structure so it will work on any system
+	 * using native endian jffs2 (the default).
+	 */
+	static struct jffs2_unknown_node clean_marker = {
+		JFFS2_MAGIC_BITMASK,
+		JFFS2_NODETYPE_CLEANMARKER,
+		8		/* 8 bytes in this node */
+	};
+	unsigned long nandptr;
+	struct Nand *mychip;
+	int ret = 0;
+
+	if (ofs & (nand->erasesize-1) || len & (nand->erasesize-1)) {
+		printf ("Offset and size must be sector aligned, erasesize = %d\n",
+			(int) nand->erasesize);
+		return -1;
+	}
+
+	nandptr = nand->IO_ADDR;
+
+	/* Select the NAND device */
+#ifdef CONFIG_OMAP1510
+	archflashwp(0,0);
+#endif
+#ifdef CFG_NAND_WP
+	NAND_WP_OFF();
+#endif
+    NAND_ENABLE_CE(nand);  /* set pin low */
+
+	/* Check the WP bit */
+	NanD_Command(nand, NAND_CMD_STATUS);
+	if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
+		printf ("nand_write_ecc: Device is write protected!!!\n");
+		ret = -1;
+		goto out;
+	}
+
+	/* Check the WP bit */
+	NanD_Command(nand, NAND_CMD_STATUS);
+	if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
+		printf ("%s: Device is write protected!!!\n", __FUNCTION__);
+		ret = -1;
+		goto out;
+	}
+
+	/* FIXME: Do nand in the background. Use timers or schedule_task() */
+	while(len) {
+		/*mychip = &nand->chips[shr(ofs, nand->chipshift)];*/
+		mychip = &nand->chips[ofs >> nand->chipshift];
+
+		/* always check for bad block first, genuine bad blocks
+		 * should _never_  be erased.
+		 */
+		if (ALLOW_ERASE_BAD_DEBUG || !check_block(nand, ofs)) {
+			/* Select the NAND device */
+			NAND_ENABLE_CE(nand);  /* set pin low */
+
+			NanD_Command(nand, NAND_CMD_ERASE1);
+			NanD_Address(nand, ADDR_PAGE, ofs);
+			NanD_Command(nand, NAND_CMD_ERASE2);
+
+			NanD_Command(nand, NAND_CMD_STATUS);
+
+#ifdef NAND_NO_RB
+			{	u_char ret_val;
+				do {
+					ret_val = READ_NAND(nandptr); /* wait till ready */
+				} while ((ret_val & 0x40) != 0x40);
+			}
+#endif
+			if (READ_NAND(nandptr) & 1) {
+				printf ("%s: Error erasing at 0x%lx\n",
+					__FUNCTION__, (long)ofs);
+				/* There was an error */
+				ret = -1;
+				goto out;
+			}
+			if (clean) {
+				int n;	/* return value not used */
+				int p, l;
+
+				/* clean marker position and size depend
+				 * on the page size, since 256 byte pages
+				 * only have 8 bytes of oob data
+				 */
+				if (nand->page256) {
+					p = NAND_JFFS2_OOB8_FSDAPOS;
+					l = NAND_JFFS2_OOB8_FSDALEN;
+				} else {
+					p = NAND_JFFS2_OOB16_FSDAPOS;
+					l = NAND_JFFS2_OOB16_FSDALEN;
+				}
+
+				ret = nand_write_oob(nand, ofs + p, l, &n,
+						     (u_char *)&clean_marker);
+				/* quit here if write failed */
+				if (ret)
+					goto out;
+			}
+		}
+		ofs += nand->erasesize;
+		len -= nand->erasesize;
+	}
+
+out:
+	/* De-select the NAND device */
+	NAND_DISABLE_CE(nand);  /* set pin high */
+#ifdef CONFIG_OMAP1510
+    	archflashwp(0,1);
+#endif
+#ifdef CFG_NAND_WP
+	NAND_WP_ON();
+#endif
+
+	return ret;
+}
+
+static inline int nandcheck(unsigned long potential, unsigned long physadr)
+{
+	return 0;
+}
+
+unsigned long nand_probe(unsigned long physadr)
+{
+	struct nand_chip *nand = NULL;
+	int i = 0, ChipID = 1;
+
+#ifdef CONFIG_MTD_NAND_ECC_JFFS2
+	oob_config.ecc_pos[0] = NAND_JFFS2_OOB_ECCPOS0;
+	oob_config.ecc_pos[1] = NAND_JFFS2_OOB_ECCPOS1;
+	oob_config.ecc_pos[2] = NAND_JFFS2_OOB_ECCPOS2;
+	oob_config.ecc_pos[3] = NAND_JFFS2_OOB_ECCPOS3;
+	oob_config.ecc_pos[4] = NAND_JFFS2_OOB_ECCPOS4;
+	oob_config.ecc_pos[5] = NAND_JFFS2_OOB_ECCPOS5;
+	oob_config.eccvalid_pos = 4;
+#else
+	oob_config.ecc_pos[0] = NAND_NOOB_ECCPOS0;
+	oob_config.ecc_pos[1] = NAND_NOOB_ECCPOS1;
+	oob_config.ecc_pos[2] = NAND_NOOB_ECCPOS2;
+	oob_config.ecc_pos[3] = NAND_NOOB_ECCPOS3;
+	oob_config.ecc_pos[4] = NAND_NOOB_ECCPOS4;
+	oob_config.ecc_pos[5] = NAND_NOOB_ECCPOS5;
+	oob_config.eccvalid_pos = NAND_NOOB_ECCVPOS;
+#endif
+	oob_config.badblock_pos = 5;
+
+	for (i=0; i<CFG_MAX_NAND_DEVICE; i++) {
+		if (nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN) {
+			nand = &nand_dev_desc[i];
+			break;
+		}
+	}
+	if (!nand)
+		return (0);
+
+	memset((char *)nand, 0, sizeof(struct nand_chip));
+
+	nand->IO_ADDR = physadr;
+	nand->cache_page = -1;  /* init the cache page */
+	NanD_ScanChips(nand);
+
+	if (nand->totlen == 0) {
+		/* no chips found, clean up and quit */
+		memset((char *)nand, 0, sizeof(struct nand_chip));
+		nand->ChipID = NAND_ChipID_UNKNOWN;
+		return (0);
+	}
+
+	nand->ChipID = ChipID;
+	if (curr_device == -1)
+		curr_device = i;
+
+	nand->data_buf = malloc (nand->oobblock + nand->oobsize);
+	if (!nand->data_buf) {
+		puts ("Cannot allocate memory for data structures.\n");
+		return (0);
+	}
+
+	return (nand->totlen);
+}
+
+#ifdef CONFIG_MTD_NAND_ECC
+/*
+ * Pre-calculated 256-way 1 byte column parity
+ */
+static const u_char nand_ecc_precalc_table[] = {
+	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
+	0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
+	0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
+	0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+	0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
+	0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+	0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
+	0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+	0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
+	0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+	0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
+	0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+	0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
+	0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+	0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
+	0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+	0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
+	0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+	0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
+	0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+	0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
+	0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+	0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
+	0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+	0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
+	0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+	0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
+	0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+	0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
+	0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
+	0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
+};
+
+
+/*
+ * Creates non-inverted ECC code from line parity
+ */
+static void nand_trans_result(u_char reg2, u_char reg3,
+	u_char *ecc_code)
+{
+	u_char a, b, i, tmp1, tmp2;
+
+	/* Initialize variables */
+	a = b = 0x80;
+	tmp1 = tmp2 = 0;
+
+	/* Calculate first ECC byte */
+	for (i = 0; i < 4; i++) {
+		if (reg3 & a)		/* LP15,13,11,9 --> ecc_code[0] */
+			tmp1 |= b;
+		b >>= 1;
+		if (reg2 & a)		/* LP14,12,10,8 --> ecc_code[0] */
+			tmp1 |= b;
+		b >>= 1;
+		a >>= 1;
+	}
+
+	/* Calculate second ECC byte */
+	b = 0x80;
+	for (i = 0; i < 4; i++) {
+		if (reg3 & a)		/* LP7,5,3,1 --> ecc_code[1] */
+			tmp2 |= b;
+		b >>= 1;
+		if (reg2 & a)		/* LP6,4,2,0 --> ecc_code[1] */
+			tmp2 |= b;
+		b >>= 1;
+		a >>= 1;
+	}
+
+	/* Store two of the ECC bytes */
+	ecc_code[0] = tmp1;
+	ecc_code[1] = tmp2;
+}
+
+/*
+ * Calculate 3 byte ECC code for 256 byte block
+ */
+static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code)
+{
+	u_char idx, reg1, reg3;
+	int j;
+
+	/* Initialize variables */
+	reg1 = reg3 = 0;
+	ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
+
+	/* Build up column parity */
+	for(j = 0; j < 256; j++) {
+
+		/* Get CP0 - CP5 from table */
+		idx = nand_ecc_precalc_table[dat[j]];
+		reg1 ^= idx;
+
+		/* All bit XOR = 1 ? */
+		if (idx & 0x40) {
+			reg3 ^= (u_char) j;
+		}
+	}
+
+	/* Create non-inverted ECC code from line parity */
+	nand_trans_result((reg1 & 0x40) ? ~reg3 : reg3, reg3, ecc_code);
+
+	/* Calculate final ECC code */
+	ecc_code[0] = ~ecc_code[0];
+	ecc_code[1] = ~ecc_code[1];
+	ecc_code[2] = ((~reg1) << 2) | 0x03;
+}
+
+/*
+ * Detect and correct a 1 bit error for 256 byte block
+ */
+static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+{
+	u_char a, b, c, d1, d2, d3, add, bit, i;
+
+	/* Do error detection */
+	d1 = calc_ecc[0] ^ read_ecc[0];
+	d2 = calc_ecc[1] ^ read_ecc[1];
+	d3 = calc_ecc[2] ^ read_ecc[2];
+
+	if ((d1 | d2 | d3) == 0) {
+		/* No errors */
+		return 0;
+	} else {
+		a = (d1 ^ (d1 >> 1)) & 0x55;
+		b = (d2 ^ (d2 >> 1)) & 0x55;
+		c = (d3 ^ (d3 >> 1)) & 0x54;
+
+		/* Found and will correct single bit error in the data */
+		if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
+			c = 0x80;
+			add = 0;
+			a = 0x80;
+			for (i=0; i<4; i++) {
+				if (d1 & c)
+					add |= a;
+				c >>= 2;
+				a >>= 1;
+			}
+			c = 0x80;
+			for (i=0; i<4; i++) {
+				if (d2 & c)
+					add |= a;
+				c >>= 2;
+				a >>= 1;
+			}
+			bit = 0;
+			b = 0x04;
+			c = 0x80;
+			for (i=0; i<3; i++) {
+				if (d3 & c)
+					bit |= b;
+				c >>= 2;
+				b >>= 1;
+			}
+			b = 0x01;
+			a = dat[add];
+			a ^= (b << bit);
+			dat[add] = a;
+			return 1;
+		}
+		else {
+			i = 0;
+			while (d1) {
+				if (d1 & 0x01)
+					++i;
+				d1 >>= 1;
+			}
+			while (d2) {
+				if (d2 & 0x01)
+					++i;
+				d2 >>= 1;
+			}
+			while (d3) {
+				if (d3 & 0x01)
+					++i;
+				d3 >>= 1;
+			}
+			if (i == 1) {
+				/* ECC Code Error Correction */
+				read_ecc[0] = calc_ecc[0];
+				read_ecc[1] = calc_ecc[1];
+				read_ecc[2] = calc_ecc[2];
+				return 2;
+			}
+			else {
+				/* Uncorrectable Error */
+				return -1;
+			}
+		}
+	}
+
+	/* Should never happen */
+	return -1;
+}
+
+#endif
+
+#ifdef CONFIG_JFFS2_NAND
+
+int read_jffs2_nand(size_t start, size_t len,
+		    size_t * retlen, u_char * buf, int nanddev)
+{
+	return nand_rw(nand_dev_desc + nanddev, NANDRW_READ | NANDRW_JFFS2,
+		       start, len, retlen, buf);
+}
 
 
+#endif /* CONFIG_JFFS2_NAND */
 
 
-#endif				/* (CONFIG_COMMANDS & CFG_CMD_NAND) */
 
 
+#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */

+ 364 - 0
common/cmd_nand_new.c

@@ -0,0 +1,364 @@
+#include <common.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NAND) && defined CONFIG_NEW_NAND_CODE
+
+#include <command.h>
+#include <watchdog.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg)	show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+#include <jffs2/jffs2.h>
+#include <nand.h>
+
+extern nand_info_t nand_info[];       /* info for NAND chips */
+
+static int nand_dump_oob(nand_info_t *nand, ulong off)
+{
+	return 0;
+}
+
+static int nand_dump(nand_info_t *nand, ulong off)
+{
+	int i;
+	u_char *buf, *p;
+
+	buf = malloc(nand->oobblock + nand->oobsize);
+	if (!buf) {
+		puts("No memory for page buffer\n");
+		return 1;
+	}
+	off &= ~(nand->oobblock - 1);
+	i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
+	if (i < 0) {
+		printf("Error (%d) reading page %08x\n", i, off);
+		free(buf);
+		return 1;
+	}
+	printf("Page %08x dump:\n", off);
+	i = nand->oobblock >> 4; p = buf;
+	while (i--) {
+		printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
+			"  %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
+			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
+		p += 16;
+	}
+	puts("OOB:\n");
+	i = nand->oobsize >> 3;
+	while (i--) {
+		printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
+			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+		p += 8;
+	}
+	free(buf);
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+arg_off_size(int argc, char *argv[], ulong *off, ulong *size, ulong totsize)
+{
+	*off = 0;
+	*size = 0;
+
+#if defined(CONFIG_JFFS2_NAND) && defined(CFG_JFFS_CUSTOM_PART)
+	if (argc >= 1 && strcmp(argv[0], "partition") == 0) {
+		int part_num;
+		struct part_info *part;
+		const char *partstr;
+
+		if (argc >= 2)
+			partstr = argv[1];
+		else
+			partstr = getenv("partition");
+
+		if (partstr)
+			part_num = (int)simple_strtoul(partstr, NULL, 10);
+		else
+			part_num = 0;
+
+		part = jffs2_part_info(part_num);
+		if (part == NULL) {
+			printf("\nInvalid partition %d\n", part_num);
+			return;
+		}
+		*size = part->size;
+		*off = (ulong)part->offset;
+	} else
+#endif
+	{
+		if (argc >= 1)
+			*off = (ulong)simple_strtoul(argv[0], NULL, 16);
+		else
+			*off = 0;
+
+		if (argc >= 2)
+			*size = (ulong)simple_strtoul(argv[1], NULL, 16);
+		else
+			*size = totsize - *off;
+
+	}
+
+}
+
+int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	int i, dev, ret;
+	ulong addr, off, size;
+	char *cmd, *s;
+	nand_info_t *nand;
+
+	/* at least two arguments please */
+	if (argc < 2)
+		goto usage;
+
+	cmd = argv[1];
+
+	if (strcmp(cmd, "info") == 0) {
+
+		putc('\n');
+		for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
+			if (nand_info[i].name)
+				printf("Device %d: %s\n", i, nand_info[i].name);
+		}
+		return 0;
+	}
+
+	if (strcmp(cmd, "device") == 0) {
+
+		if (argc < 3) {
+			if ((nand_curr_device < 0) ||
+			    (nand_curr_device >= CFG_MAX_NAND_DEVICE))
+				puts("\nno devices available\n");
+			else
+				printf("\nDevice %d: %s\n", nand_curr_device,
+					nand_info[nand_curr_device].name);
+			return 0;
+		}
+		dev = (int)simple_strtoul(argv[2], NULL, 10);
+		if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
+			puts("No such device\n");
+			return 1;
+		}
+		printf("Device %d: %s", dev, nand_info[dev].name);
+		puts("... is now current device\n");
+		nand_curr_device = dev;
+		return 0;
+	}
+
+	if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
+	    strncmp(cmd, "dump", 4) != 0 &&
+	    strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0)
+		goto usage;
+
+	/* the following commands operate on the current device */
+	if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
+	    !nand_info[nand_curr_device].name) {
+		puts("\nno devices available\n");
+		return 1;
+	}
+	nand = &nand_info[nand_curr_device];
+
+	if (strcmp(cmd, "bad") == 0) {
+		printf("\nDevice %d bad blocks:\n", nand_curr_device);
+		for (off = 0; off < nand->size; off += nand->erasesize)
+			if (nand_block_isbad(nand, off))
+				printf("  %08x\n", off);
+		return 0;
+	}
+
+	if (strcmp(cmd, "erase") == 0) {
+		arg_off_size(argc - 2, argv + 2, &off, &size, nand->size);
+		if (off == 0 && size == 0)
+			return 1;
+
+		printf("\nNAND erase: device %d offset 0x%x, size 0x%x ",
+		       nand_curr_device, off, size);
+		ret = nand_erase(nand, off, size);
+		printf("%s\n", ret ? "ERROR" : "OK");
+
+		return ret == 0 ? 0 : 1;
+	}
+
+	if (strncmp(cmd, "dump", 4) == 0) {
+		if (argc < 3)
+			goto usage;
+
+		s = strchr(cmd, '.');
+		off = (int)simple_strtoul(argv[2], NULL, 16);
+
+		if (s != NULL && strcmp(s, ".oob") == 0)
+			ret = nand_dump_oob(nand, off);
+		else
+			ret = nand_dump(nand, off);
+
+		return ret == 0 ? 1 : 0;
+
+	}
+
+	/* read write */
+	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
+		if (argc < 4)
+			goto usage;
+/*
+		s = strchr(cmd, '.');
+		clean = CLEAN_NONE;
+		if (s != NULL) {
+			if (strcmp(s, ".jffs2") == 0 || strcmp(s, ".e") == 0
+			    || strcmp(s, ".i"))
+				clean = CLEAN_JFFS2;
+		}
+*/
+		addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+
+		arg_off_size(argc - 3, argv + 3, &off, &size, nand->size);
+		if (off == 0 && size == 0)
+			return 1;
+
+		i = strncmp(cmd, "read", 4) == 0;	/* 1 = read, 0 = write */
+		printf("\nNAND %s: device %d offset %u, size %u ... ",
+		       i ? "read" : "write", nand_curr_device, off, size);
+
+		if (i)
+			ret = nand_read(nand, off, &size, (u_char *)addr);
+		else
+			ret = nand_write(nand, off, &size, (u_char *)addr);
+
+		printf(" %d bytes %s: %s\n", size,
+		       i ? "read" : "written", ret ? "ERROR" : "OK");
+
+		return ret == 0 ? 0 : 1;
+	}
+usage:
+	printf("Usage:\n%s\n", cmdtp->usage);
+	return 1;
+}
+
+U_BOOT_CMD(nand, 5, 1, do_nand,
+	"nand    - NAND sub-system\n",
+	"info                  - show available NAND devices\n"
+	"nand device [dev]     - show or set current device\n"
+	"nand read[.jffs2]     - addr off size\n"
+	"nand write[.jffs2]    - addr off size - read/write `size' bytes starting\n"
+	"    at offset `off' to/from memory address `addr'\n"
+	"nand erase [clean] [off size] - erase `size' bytes from\n"
+	"    offset `off' (entire device if not specified)\n"
+	"nand bad - show bad blocks\n"
+	"nand dump[.oob] off - dump page\n"
+	"nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
+	"nand markbad off - mark bad block at offset (UNSAFE)\n"
+	"nand biterr off - make a bit error at offset (UNSAFE)\n");
+
+int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	char *boot_device = NULL;
+	char *ep;
+	int dev;
+	int r;
+	ulong addr, cnt, offset = 0;
+	image_header_t *hdr;
+	nand_info_t *nand;
+
+	switch (argc) {
+	case 1:
+		addr = CFG_LOAD_ADDR;
+		boot_device = getenv("bootdevice");
+		break;
+	case 2:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_device = getenv("bootdevice");
+		break;
+	case 3:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_device = argv[2];
+		break;
+	case 4:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_device = argv[2];
+		offset = simple_strtoul(argv[3], NULL, 16);
+		break;
+	default:
+		printf("Usage:\n%s\n", cmdtp->usage);
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	if (!boot_device) {
+		puts("\n** No boot device **\n");
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	dev = simple_strtoul(boot_device, &ep, 16);
+
+	if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
+		printf("\n** Device %d not available\n", dev);
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	nand = &nand_info[dev];
+	printf("\nLoading from device %d: %s (offset 0x%lx)\n",
+	       dev, nand->name, offset);
+
+	cnt = nand->oobblock;
+	r = nand_read(nand, offset, &cnt, (u_char *) addr);
+	if (r) {
+		printf("** Read error on %d\n", dev);
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	hdr = (image_header_t *) addr;
+
+	if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+		printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	print_image_hdr(hdr);
+
+	cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
+
+	r = nand_read(nand, offset, &cnt, (u_char *) addr);
+	if (r) {
+		printf("** Read error on %d\n", dev);
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	/* Loading ok, update default load address */
+
+	load_addr = addr;
+
+	/* Check if we should attempt an auto-start */
+	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
+		char *local_args[2];
+		extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
+
+		local_args[0] = argv[0];
+		local_args[1] = NULL;
+
+		printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
+
+		do_bootm(cmdtp, 0, 1, local_args);
+		return 1;
+	}
+	return 0;
+}
+
+U_BOOT_CMD(nboot, 4, 1, do_nandboot,
+	"nboot   - boot from NAND device\n", "loadAddr dev\n");
+
+
+#endif				/* (CONFIG_COMMANDS & CFG_CMD_NAND) */

+ 1 - 1
cpu/arm925t/config.mk

@@ -22,6 +22,6 @@
 #
 #
 
 
 PLATFORM_RELFLAGS += -fno-strict-aliasing  -fno-common -ffixed-r8 \
 PLATFORM_RELFLAGS += -fno-strict-aliasing  -fno-common -ffixed-r8 \
-	-mshort-load-bytes -msoft-float
+	-msoft-float
 
 
 PLATFORM_CPPFLAGS += -mapcs-32 -march=armv4
 PLATFORM_CPPFLAGS += -mapcs-32 -march=armv4

+ 0 - 1
drivers/nand/Makefile

@@ -14,4 +14,3 @@ $(LIB):	$(OBJS)
 		$(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@
 		$(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@
 
 
 sinclude .depend
 sinclude .depend
-

+ 99 - 99
drivers/nand/diskonchip.c

@@ -1,4 +1,4 @@
-/* 
+/*
  * drivers/mtd/nand/diskonchip.c
  * drivers/mtd/nand/diskonchip.c
  *
  *
  * (C) 2003 Red Hat, Inc.
  * (C) 2003 Red Hat, Inc.
@@ -8,12 +8,12 @@
  * Author: David Woodhouse <dwmw2@infradead.org>
  * Author: David Woodhouse <dwmw2@infradead.org>
  * Additional Diskonchip 2000 and Millennium support by Dan Brown <dan_brown@ieee.org>
  * Additional Diskonchip 2000 and Millennium support by Dan Brown <dan_brown@ieee.org>
  * Diskonchip Millennium Plus support by Kalev Lember <kalev@smartlink.ee>
  * Diskonchip Millennium Plus support by Kalev Lember <kalev@smartlink.ee>
- * 
+ *
  * Error correction code lifted from the old docecc code
  * Error correction code lifted from the old docecc code
- * Author: Fabrice Bellard (fabrice.bellard@netgem.com) 
+ * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
  * Copyright (C) 2000 Netgem S.A.
  * Copyright (C) 2000 Netgem S.A.
  * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de>
  * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de>
- *  
+ *
  * Interface to generic NAND code for M-Systems DiskOnChip devices
  * Interface to generic NAND code for M-Systems DiskOnChip devices
  *
  *
  * $Id: diskonchip.c,v 1.45 2005/01/05 18:05:14 dwmw2 Exp $
  * $Id: diskonchip.c,v 1.45 2005/01/05 18:05:14 dwmw2 Exp $
@@ -42,25 +42,25 @@
 static unsigned long __initdata doc_locations[] = {
 static unsigned long __initdata doc_locations[] = {
 #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
 #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
 #ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH
 #ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH
-	0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, 
+	0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
 	0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
 	0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
-	0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, 
-	0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, 
+	0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
+	0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
 	0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
 	0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
 #else /*  CONFIG_MTD_DOCPROBE_HIGH */
 #else /*  CONFIG_MTD_DOCPROBE_HIGH */
-	0xc8000, 0xca000, 0xcc000, 0xce000, 
+	0xc8000, 0xca000, 0xcc000, 0xce000,
 	0xd0000, 0xd2000, 0xd4000, 0xd6000,
 	0xd0000, 0xd2000, 0xd4000, 0xd6000,
-	0xd8000, 0xda000, 0xdc000, 0xde000, 
-	0xe0000, 0xe2000, 0xe4000, 0xe6000, 
+	0xd8000, 0xda000, 0xdc000, 0xde000,
+	0xe0000, 0xe2000, 0xe4000, 0xe6000,
 	0xe8000, 0xea000, 0xec000, 0xee000,
 	0xe8000, 0xea000, 0xec000, 0xee000,
 #endif /*  CONFIG_MTD_DOCPROBE_HIGH */
 #endif /*  CONFIG_MTD_DOCPROBE_HIGH */
 #elif defined(__PPC__)
 #elif defined(__PPC__)
 	0xe4000000,
 	0xe4000000,
 #elif defined(CONFIG_MOMENCO_OCELOT)
 #elif defined(CONFIG_MOMENCO_OCELOT)
 	0x2f000000,
 	0x2f000000,
-        0xff000000,
+	0xff000000,
 #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
 #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
-        0xff000000,
+	0xff000000,
 ##else
 ##else
 #warning Unknown architecture for DiskOnChip. No default probe locations defined
 #warning Unknown architecture for DiskOnChip. No default probe locations defined
 #endif
 #endif
@@ -142,7 +142,7 @@ MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe
 /* the Reed Solomon control structure */
 /* the Reed Solomon control structure */
 static struct rs_control *rs_decoder;
 static struct rs_control *rs_decoder;
 
 
-/* 
+/*
  * The HW decoder in the DoC ASIC's provides us a error syndrome,
  * The HW decoder in the DoC ASIC's provides us a error syndrome,
  * which we must convert to a standard syndrom usable by the generic
  * which we must convert to a standard syndrom usable by the generic
  * Reed-Solomon library code.
  * Reed-Solomon library code.
@@ -167,8 +167,8 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 	/* Initialize the syndrom buffer */
 	/* Initialize the syndrom buffer */
 	for (i = 0; i < NROOTS; i++)
 	for (i = 0; i < NROOTS; i++)
 		s[i] = ds[0];
 		s[i] = ds[0];
-	/* 
-	 *  Evaluate 
+	/*
+	 *  Evaluate
 	 *  s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0]
 	 *  s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0]
 	 *  where x = alpha^(FCR + i)
 	 *  where x = alpha^(FCR + i)
 	 */
 	 */
@@ -192,7 +192,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 	if (nerr < 0)
 	if (nerr < 0)
 		return nerr;
 		return nerr;
 
 
-	/* 
+	/*
 	 * Correct the errors. The bitpositions are a bit of magic,
 	 * Correct the errors. The bitpositions are a bit of magic,
 	 * but they are given by the design of the de/encoder circuit
 	 * but they are given by the design of the de/encoder circuit
 	 * in the DoC ASIC's.
 	 * in the DoC ASIC's.
@@ -209,7 +209,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 			   can be modified since pos is even */
 			   can be modified since pos is even */
 			index = (pos >> 3) ^ 1;
 			index = (pos >> 3) ^ 1;
 			bitpos = pos & 7;
 			bitpos = pos & 7;
-			if ((index >= 0 && index < SECTOR_SIZE) || 
+			if ((index >= 0 && index < SECTOR_SIZE) ||
 			    index == (SECTOR_SIZE + 1)) {
 			    index == (SECTOR_SIZE + 1)) {
 				val = (uint8_t) (errval[i] >> (2 + bitpos));
 				val = (uint8_t) (errval[i] >> (2 + bitpos));
 				parity ^= val;
 				parity ^= val;
@@ -220,7 +220,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 			bitpos = (bitpos + 10) & 7;
 			bitpos = (bitpos + 10) & 7;
 			if (bitpos == 0)
 			if (bitpos == 0)
 				bitpos = 8;
 				bitpos = 8;
-			if ((index >= 0 && index < SECTOR_SIZE) || 
+			if ((index >= 0 && index < SECTOR_SIZE) ||
 			    index == (SECTOR_SIZE + 1)) {
 			    index == (SECTOR_SIZE + 1)) {
 				val = (uint8_t)(errval[i] << (8 - bitpos));
 				val = (uint8_t)(errval[i] << (8 - bitpos));
 				parity ^= val;
 				parity ^= val;
@@ -237,7 +237,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
 {
 {
 	volatile char dummy;
 	volatile char dummy;
 	int i;
 	int i;
-	
+
 	for (i = 0; i < cycles; i++) {
 	for (i = 0; i < cycles; i++) {
 		if (DoC_is_Millennium(doc))
 		if (DoC_is_Millennium(doc))
 			dummy = ReadDOC(doc->virtadr, NOP);
 			dummy = ReadDOC(doc->virtadr, NOP);
@@ -246,7 +246,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
 		else
 		else
 			dummy = ReadDOC(doc->virtadr, DOCStatus);
 			dummy = ReadDOC(doc->virtadr, DOCStatus);
 	}
 	}
-	
+
 }
 }
 
 
 #define CDSN_CTRL_FR_B_MASK	(CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)
 #define CDSN_CTRL_FR_B_MASK	(CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)
@@ -254,7 +254,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
 /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
 /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
 static int _DoC_WaitReady(struct doc_priv *doc)
 static int _DoC_WaitReady(struct doc_priv *doc)
 {
 {
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	unsigned long timeo = jiffies + (HZ * 10);
 	unsigned long timeo = jiffies + (HZ * 10);
 
 
 	if(debug) printk("_DoC_WaitReady...\n");
 	if(debug) printk("_DoC_WaitReady...\n");
@@ -284,7 +284,7 @@ static int _DoC_WaitReady(struct doc_priv *doc)
 
 
 static inline int DoC_WaitReady(struct doc_priv *doc)
 static inline int DoC_WaitReady(struct doc_priv *doc)
 {
 {
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int ret = 0;
 	int ret = 0;
 
 
 	if (DoC_is_MillenniumPlus(doc)) {
 	if (DoC_is_MillenniumPlus(doc)) {
@@ -310,7 +310,7 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 
 	if(debug)printk("write_byte %02x\n", datum);
 	if(debug)printk("write_byte %02x\n", datum);
 	WriteDOC(datum, docptr, CDSNSlowIO);
 	WriteDOC(datum, docptr, CDSNSlowIO);
@@ -321,7 +321,7 @@ static u_char doc2000_read_byte(struct mtd_info *mtd)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	u_char ret;
 	u_char ret;
 
 
 	ReadDOC(docptr, CDSNSlowIO);
 	ReadDOC(docptr, CDSNSlowIO);
@@ -331,12 +331,12 @@ static u_char doc2000_read_byte(struct mtd_info *mtd)
 	return ret;
 	return ret;
 }
 }
 
 
-static void doc2000_writebuf(struct mtd_info *mtd, 
+static void doc2000_writebuf(struct mtd_info *mtd,
 			     const u_char *buf, int len)
 			     const u_char *buf, int len)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 	int i;
 	if (debug)printk("writebuf of %d bytes: ", len);
 	if (debug)printk("writebuf of %d bytes: ", len);
 	for (i=0; i < len; i++) {
 	for (i=0; i < len; i++) {
@@ -347,12 +347,12 @@ static void doc2000_writebuf(struct mtd_info *mtd,
 	if (debug) printk("\n");
 	if (debug) printk("\n");
 }
 }
 
 
-static void doc2000_readbuf(struct mtd_info *mtd, 
+static void doc2000_readbuf(struct mtd_info *mtd,
 			    u_char *buf, int len)
 			    u_char *buf, int len)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
  	int i;
  	int i;
 
 
 	if (debug)printk("readbuf of %d bytes: ", len);
 	if (debug)printk("readbuf of %d bytes: ", len);
@@ -362,12 +362,12 @@ static void doc2000_readbuf(struct mtd_info *mtd,
 	}
 	}
 }
 }
 
 
-static void doc2000_readbuf_dword(struct mtd_info *mtd, 
+static void doc2000_readbuf_dword(struct mtd_info *mtd,
 			    u_char *buf, int len)
 			    u_char *buf, int len)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
  	int i;
  	int i;
 
 
 	if (debug) printk("readbuf_dword of %d bytes: ", len);
 	if (debug) printk("readbuf_dword of %d bytes: ", len);
@@ -383,12 +383,12 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd,
 	}
 	}
 }
 }
 
 
-static int doc2000_verifybuf(struct mtd_info *mtd, 
+static int doc2000_verifybuf(struct mtd_info *mtd,
 			      const u_char *buf, int len)
 			      const u_char *buf, int len)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 	int i;
 
 
 	for (i=0; i < len; i++)
 	for (i=0; i < len; i++)
@@ -435,7 +435,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
 			this->read_buf = &doc2000_readbuf_dword;
 			this->read_buf = &doc2000_readbuf_dword;
 		}
 		}
 	}
 	}
-		
+
 	return ret;
 	return ret;
 }
 }
 
 
@@ -466,7 +466,7 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
 
 
 	int status;
 	int status;
-	
+
 	DoC_WaitReady(doc);
 	DoC_WaitReady(doc);
 	this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
 	this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
 	DoC_WaitReady(doc);
 	DoC_WaitReady(doc);
@@ -479,7 +479,7 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 
 	WriteDOC(datum, docptr, CDSNSlowIO);
 	WriteDOC(datum, docptr, CDSNSlowIO);
 	WriteDOC(datum, docptr, Mil_CDSN_IO);
 	WriteDOC(datum, docptr, Mil_CDSN_IO);
@@ -490,22 +490,22 @@ static u_char doc2001_read_byte(struct mtd_info *mtd)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 
-	//ReadDOC(docptr, CDSNSlowIO);
+	/*ReadDOC(docptr, CDSNSlowIO); */
 	/* 11.4.5 -- delay twice to allow extended length cycle */
 	/* 11.4.5 -- delay twice to allow extended length cycle */
 	DoC_Delay(doc, 2);
 	DoC_Delay(doc, 2);
 	ReadDOC(docptr, ReadPipeInit);
 	ReadDOC(docptr, ReadPipeInit);
-	//return ReadDOC(docptr, Mil_CDSN_IO);
+	/*return ReadDOC(docptr, Mil_CDSN_IO); */
 	return ReadDOC(docptr, LastDataRead);
 	return ReadDOC(docptr, LastDataRead);
 }
 }
 
 
-static void doc2001_writebuf(struct mtd_info *mtd, 
+static void doc2001_writebuf(struct mtd_info *mtd,
 			     const u_char *buf, int len)
 			     const u_char *buf, int len)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 	int i;
 
 
 	for (i=0; i < len; i++)
 	for (i=0; i < len; i++)
@@ -514,12 +514,12 @@ static void doc2001_writebuf(struct mtd_info *mtd,
 	WriteDOC(0x00, docptr, WritePipeTerm);
 	WriteDOC(0x00, docptr, WritePipeTerm);
 }
 }
 
 
-static void doc2001_readbuf(struct mtd_info *mtd, 
+static void doc2001_readbuf(struct mtd_info *mtd,
 			    u_char *buf, int len)
 			    u_char *buf, int len)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 	int i;
 
 
 	/* Start read pipeline */
 	/* Start read pipeline */
@@ -532,12 +532,12 @@ static void doc2001_readbuf(struct mtd_info *mtd,
 	buf[i] = ReadDOC(docptr, LastDataRead);
 	buf[i] = ReadDOC(docptr, LastDataRead);
 }
 }
 
 
-static int doc2001_verifybuf(struct mtd_info *mtd, 
+static int doc2001_verifybuf(struct mtd_info *mtd,
 			     const u_char *buf, int len)
 			     const u_char *buf, int len)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 	int i;
 
 
 	/* Start read pipeline */
 	/* Start read pipeline */
@@ -557,22 +557,22 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	u_char ret;
 	u_char ret;
 
 
-        ReadDOC(docptr, Mplus_ReadPipeInit);
-        ReadDOC(docptr, Mplus_ReadPipeInit);
-        ret = ReadDOC(docptr, Mplus_LastDataRead);
+	ReadDOC(docptr, Mplus_ReadPipeInit);
+	ReadDOC(docptr, Mplus_ReadPipeInit);
+	ret = ReadDOC(docptr, Mplus_LastDataRead);
 	if (debug) printk("read_byte returns %02x\n", ret);
 	if (debug) printk("read_byte returns %02x\n", ret);
 	return ret;
 	return ret;
 }
 }
 
 
-static void doc2001plus_writebuf(struct mtd_info *mtd, 
+static void doc2001plus_writebuf(struct mtd_info *mtd,
 			     const u_char *buf, int len)
 			     const u_char *buf, int len)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 	int i;
 
 
 	if (debug)printk("writebuf of %d bytes: ", len);
 	if (debug)printk("writebuf of %d bytes: ", len);
@@ -584,12 +584,12 @@ static void doc2001plus_writebuf(struct mtd_info *mtd,
 	if (debug) printk("\n");
 	if (debug) printk("\n");
 }
 }
 
 
-static void doc2001plus_readbuf(struct mtd_info *mtd, 
+static void doc2001plus_readbuf(struct mtd_info *mtd,
 			    u_char *buf, int len)
 			    u_char *buf, int len)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 	int i;
 
 
 	if (debug)printk("readbuf of %d bytes: ", len);
 	if (debug)printk("readbuf of %d bytes: ", len);
@@ -614,12 +614,12 @@ static void doc2001plus_readbuf(struct mtd_info *mtd,
 	if (debug) printk("\n");
 	if (debug) printk("\n");
 }
 }
 
 
-static int doc2001plus_verifybuf(struct mtd_info *mtd, 
+static int doc2001plus_verifybuf(struct mtd_info *mtd,
 			     const u_char *buf, int len)
 			     const u_char *buf, int len)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 	int i;
 
 
 	if (debug)printk("verifybuf of %d bytes: ", len);
 	if (debug)printk("verifybuf of %d bytes: ", len);
@@ -645,7 +645,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int floor = 0;
 	int floor = 0;
 
 
 	if(debug)printk("select chip (%d)\n", chip);
 	if(debug)printk("select chip (%d)\n", chip);
@@ -671,7 +671,7 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int floor = 0;
 	int floor = 0;
 
 
 	if(debug)printk("select chip (%d)\n", chip);
 	if(debug)printk("select chip (%d)\n", chip);
@@ -698,7 +698,7 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 
 	switch(cmd) {
 	switch(cmd) {
 	case NAND_CTL_SETNCE:
 	case NAND_CTL_SETNCE:
@@ -736,7 +736,7 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 
 	/*
 	/*
 	 * Must terminate write pipeline before sending any commands
 	 * Must terminate write pipeline before sending any commands
@@ -794,7 +794,7 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col
 			WriteDOC(0, docptr, Mplus_FlashControl);
 			WriteDOC(0, docptr, Mplus_FlashControl);
 	}
 	}
 
 
-	/* 
+	/*
 	 * program and erase have their own busy handlers
 	 * program and erase have their own busy handlers
 	 * status and sequential in needs no delay
 	 * status and sequential in needs no delay
 	*/
 	*/
@@ -819,7 +819,7 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col
 
 
 	/* This applies to read commands */
 	/* This applies to read commands */
 	default:
 	default:
-		/* 
+		/*
 		 * If we don't have access to the busy pin, we apply the given
 		 * If we don't have access to the busy pin, we apply the given
 		 * command delay
 		 * command delay
 		*/
 		*/
@@ -840,7 +840,7 @@ static int doc200x_dev_ready(struct mtd_info *mtd)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 
 	if (DoC_is_MillenniumPlus(doc)) {
 	if (DoC_is_MillenniumPlus(doc)) {
 		/* 11.4.2 -- must NOP four times before checking FR/B# */
 		/* 11.4.2 -- must NOP four times before checking FR/B# */
@@ -878,7 +878,7 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 
 	/* Prime the ECC engine */
 	/* Prime the ECC engine */
 	switch(mode) {
 	switch(mode) {
@@ -897,7 +897,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 
 	/* Prime the ECC engine */
 	/* Prime the ECC engine */
 	switch(mode) {
 	switch(mode) {
@@ -918,7 +918,7 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 	int i;
 	int emptymatch = 1;
 	int emptymatch = 1;
 
 
@@ -942,7 +942,7 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 	for (i = 0; i < 6; i++) {
 	for (i = 0; i < 6; i++) {
 		if (DoC_is_MillenniumPlus(doc))
 		if (DoC_is_MillenniumPlus(doc))
 			ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i);
 			ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i);
-		else 
+		else
 			ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
 			ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
 		if (ecc_code[i] != empty_write_ecc[i])
 		if (ecc_code[i] != empty_write_ecc[i])
 			emptymatch = 0;
 			emptymatch = 0;
@@ -976,10 +976,10 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
 	int i, ret = 0;
 	int i, ret = 0;
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	volatile u_char dummy;
 	volatile u_char dummy;
 	int emptymatch = 1;
 	int emptymatch = 1;
-	
+
 	/* flush the pipeline */
 	/* flush the pipeline */
 	if (DoC_is_2000(doc)) {
 	if (DoC_is_2000(doc)) {
 		dummy = ReadDOC(docptr, 2k_ECCStatus);
 		dummy = ReadDOC(docptr, 2k_ECCStatus);
@@ -994,7 +994,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
 		dummy = ReadDOC(docptr, ECCConf);
 		dummy = ReadDOC(docptr, ECCConf);
 		dummy = ReadDOC(docptr, ECCConf);
 		dummy = ReadDOC(docptr, ECCConf);
 	}
 	}
-	
+
 	/* Error occured ? */
 	/* Error occured ? */
 	if (dummy & 0x80) {
 	if (dummy & 0x80) {
 		for (i = 0; i < 6; i++) {
 		for (i = 0; i < 6; i++) {
@@ -1032,7 +1032,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
 		if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc);
 		if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc);
 		if (ret > 0)
 		if (ret > 0)
 			printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
 			printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
-	}	
+	}
 	if (DoC_is_MillenniumPlus(doc))
 	if (DoC_is_MillenniumPlus(doc))
 		WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
 		WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
 	else
 	else
@@ -1043,16 +1043,16 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
 	}
 	}
 	return ret;
 	return ret;
 }
 }
-		
-//u_char mydatabuf[528];
+
+/*u_char mydatabuf[528]; */
 
 
 static struct nand_oobinfo doc200x_oobinfo = {
 static struct nand_oobinfo doc200x_oobinfo = {
-        .useecc = MTD_NANDECC_AUTOPLACE,
-        .eccbytes = 6,
-        .eccpos = {0, 1, 2, 3, 4, 5},
-        .oobfree = { {8, 8} }
+	.useecc = MTD_NANDECC_AUTOPLACE,
+	.eccbytes = 6,
+	.eccpos = {0, 1, 2, 3, 4, 5},
+	.oobfree = { {8, 8} }
 };
 };
- 
+
 /* Find the (I)NFTL Media Header, and optionally also the mirror media header.
 /* Find the (I)NFTL Media Header, and optionally also the mirror media header.
    On sucessful return, buf will contain a copy of the media header for
    On sucessful return, buf will contain a copy of the media header for
    further processing.  id is the string to scan for, and will presumably be
    further processing.  id is the string to scan for, and will presumably be
@@ -1068,7 +1068,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
 	int ret;
 	int ret;
 	size_t retlen;
 	size_t retlen;
 
 
-	end = min(end, mtd->size); // paranoia
+	end = min(end, mtd->size); /* paranoia */
 	for (offs = 0; offs < end; offs += mtd->erasesize) {
 	for (offs = 0; offs < end; offs += mtd->erasesize) {
 		ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
 		ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
 		if (retlen != mtd->oobblock) continue;
 		if (retlen != mtd->oobblock) continue;
@@ -1122,8 +1122,8 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
 	if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out;
 	if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out;
 	mh = (struct NFTLMediaHeader *) buf;
 	mh = (struct NFTLMediaHeader *) buf;
 
 
-//#ifdef CONFIG_MTD_DEBUG_VERBOSE
-//	if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
+/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */
+/*	if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */
 	printk(KERN_INFO "    DataOrgID        = %s\n"
 	printk(KERN_INFO "    DataOrgID        = %s\n"
 			 "    NumEraseUnits    = %d\n"
 			 "    NumEraseUnits    = %d\n"
 			 "    FirstPhysicalEUN = %d\n"
 			 "    FirstPhysicalEUN = %d\n"
@@ -1132,7 +1132,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
 		mh->DataOrgID, mh->NumEraseUnits,
 		mh->DataOrgID, mh->NumEraseUnits,
 		mh->FirstPhysicalEUN, mh->FormattedSize,
 		mh->FirstPhysicalEUN, mh->FormattedSize,
 		mh->UnitSizeFactor);
 		mh->UnitSizeFactor);
-//#endif
+/*#endif */
 
 
 	blocks = mtd->size >> this->phys_erase_shift;
 	blocks = mtd->size >> this->phys_erase_shift;
 	maxblocks = min(32768U, mtd->erasesize - psize);
 	maxblocks = min(32768U, mtd->erasesize - psize);
@@ -1175,9 +1175,9 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
 	offs <<= this->page_shift;
 	offs <<= this->page_shift;
 	offs += mtd->erasesize;
 	offs += mtd->erasesize;
 
 
-	//parts[0].name = " DiskOnChip Boot / Media Header partition";
-	//parts[0].offset = 0;
-	//parts[0].size = offs;
+	/*parts[0].name = " DiskOnChip Boot / Media Header partition"; */
+	/*parts[0].offset = 0; */
+	/*parts[0].size = offs; */
 
 
 	parts[0].name = " DiskOnChip BDTL partition";
 	parts[0].name = " DiskOnChip BDTL partition";
 	parts[0].offset = offs;
 	parts[0].offset = offs;
@@ -1232,9 +1232,9 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
 	mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);
 	mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);
 	mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
 	mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
 	mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
 	mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
- 
-//#ifdef CONFIG_MTD_DEBUG_VERBOSE
-//	if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
+
+/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */
+/*	if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */
 	printk(KERN_INFO "    bootRecordID          = %s\n"
 	printk(KERN_INFO "    bootRecordID          = %s\n"
 			 "    NoOfBootImageBlocks   = %d\n"
 			 "    NoOfBootImageBlocks   = %d\n"
 			 "    NoOfBinaryPartitions  = %d\n"
 			 "    NoOfBinaryPartitions  = %d\n"
@@ -1252,7 +1252,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
 		((unsigned char *) &mh->OsakVersion)[2] & 0xf,
 		((unsigned char *) &mh->OsakVersion)[2] & 0xf,
 		((unsigned char *) &mh->OsakVersion)[3] & 0xf,
 		((unsigned char *) &mh->OsakVersion)[3] & 0xf,
 		mh->PercentUsed);
 		mh->PercentUsed);
-//#endif
+/*#endif */
 
 
 	vshift = this->phys_erase_shift + mh->BlockMultiplierBits;
 	vshift = this->phys_erase_shift + mh->BlockMultiplierBits;
 
 
@@ -1278,8 +1278,8 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
 		ip->spareUnits = le32_to_cpu(ip->spareUnits);
 		ip->spareUnits = le32_to_cpu(ip->spareUnits);
 		ip->Reserved0 = le32_to_cpu(ip->Reserved0);
 		ip->Reserved0 = le32_to_cpu(ip->Reserved0);
 
 
-//#ifdef CONFIG_MTD_DEBUG_VERBOSE
-//		if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
+/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */
+/*		if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */
 		printk(KERN_INFO	"    PARTITION[%d] ->\n"
 		printk(KERN_INFO	"    PARTITION[%d] ->\n"
 			"        virtualUnits    = %d\n"
 			"        virtualUnits    = %d\n"
 			"        firstUnit       = %d\n"
 			"        firstUnit       = %d\n"
@@ -1289,7 +1289,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
 			i, ip->virtualUnits, ip->firstUnit,
 			i, ip->virtualUnits, ip->firstUnit,
 			ip->lastUnit, ip->flags,
 			ip->lastUnit, ip->flags,
 			ip->spareUnits);
 			ip->spareUnits);
-//#endif
+/*#endif */
 
 
 /*
 /*
 		if ((i == 0) && (ip->firstUnit > 0)) {
 		if ((i == 0) && (ip->firstUnit > 0)) {
@@ -1456,7 +1456,7 @@ static inline int __init doc2001_init(struct mtd_info *mtd)
 	ReadDOC(doc->virtadr, ChipID);
 	ReadDOC(doc->virtadr, ChipID);
 	if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) {
 	if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) {
 		/* It's not a Millennium; it's one of the newer
 		/* It's not a Millennium; it's one of the newer
-		   DiskOnChip 2000 units with a similar ASIC. 
+		   DiskOnChip 2000 units with a similar ASIC.
 		   Treat it like a Millennium, except that it
 		   Treat it like a Millennium, except that it
 		   can have multiple chips. */
 		   can have multiple chips. */
 		doc2000_count_chips(mtd);
 		doc2000_count_chips(mtd);
@@ -1518,20 +1518,20 @@ static inline int __init doc_probe(unsigned long physadr)
 	 * to the DOCControl register. So we store the current contents
 	 * to the DOCControl register. So we store the current contents
 	 * of the DOCControl register's location, in case we later decide
 	 * of the DOCControl register's location, in case we later decide
 	 * that it's not a DiskOnChip, and want to put it back how we
 	 * that it's not a DiskOnChip, and want to put it back how we
-	 * found it. 
+	 * found it.
 	 */
 	 */
 	save_control = ReadDOC(virtadr, DOCControl);
 	save_control = ReadDOC(virtadr, DOCControl);
 
 
 	/* Reset the DiskOnChip ASIC */
 	/* Reset the DiskOnChip ASIC */
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, 
+	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
 		 virtadr, DOCControl);
 		 virtadr, DOCControl);
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, 
+	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
 		 virtadr, DOCControl);
 		 virtadr, DOCControl);
 
 
 	/* Enable the DiskOnChip ASIC */
 	/* Enable the DiskOnChip ASIC */
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, 
+	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
 		 virtadr, DOCControl);
 		 virtadr, DOCControl);
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, 
+	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
 		 virtadr, DOCControl);
 		 virtadr, DOCControl);
 
 
 	ChipID = ReadDOC(virtadr, ChipID);
 	ChipID = ReadDOC(virtadr, ChipID);
@@ -1614,11 +1614,11 @@ static inline int __init doc_probe(unsigned long physadr)
 		if (ChipID == DOC_ChipID_DocMilPlus16) {
 		if (ChipID == DOC_ChipID_DocMilPlus16) {
 			WriteDOC(~newval, virtadr, Mplus_AliasResolution);
 			WriteDOC(~newval, virtadr, Mplus_AliasResolution);
 			oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution);
 			oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution);
-			WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it
+			WriteDOC(newval, virtadr, Mplus_AliasResolution); /* restore it */
 		} else {
 		} else {
 			WriteDOC(~newval, virtadr, AliasResolution);
 			WriteDOC(~newval, virtadr, AliasResolution);
 			oldval = ReadDOC(doc->virtadr, AliasResolution);
 			oldval = ReadDOC(doc->virtadr, AliasResolution);
-			WriteDOC(newval, virtadr, AliasResolution); // restore it
+			WriteDOC(newval, virtadr, AliasResolution); /* restore it */
 		}
 		}
 		newval = ~newval;
 		newval = ~newval;
 		if (oldval == newval) {
 		if (oldval == newval) {
@@ -1726,7 +1726,7 @@ static int __init init_nanddoc(void)
 	int i, ret = 0;
 	int i, ret = 0;
 
 
 	/* We could create the decoder on demand, if memory is a concern.
 	/* We could create the decoder on demand, if memory is a concern.
-	 * This way we have it handy, if an error happens 
+	 * This way we have it handy, if an error happens
 	 *
 	 *
 	 * Symbolsize is 10 (bits)
 	 * Symbolsize is 10 (bits)
 	 * Primitve polynomial is x^10+x^3+1
 	 * Primitve polynomial is x^10+x^3+1

File diff suppressed because it is too large
+ 171 - 173
drivers/nand/nand_base.c


+ 121 - 121
drivers/nand/nand_bbt.c

@@ -3,7 +3,7 @@
  *
  *
  *  Overview:
  *  Overview:
  *   Bad block table support for the NAND driver
  *   Bad block table support for the NAND driver
- *   
+ *
  *  Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
  *  Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
  *
  *
  * $Id: nand_bbt.c,v 1.28 2004/11/13 10:19:09 gleixner Exp $
  * $Id: nand_bbt.c,v 1.28 2004/11/13 10:19:09 gleixner Exp $
@@ -14,23 +14,23 @@
  *
  *
  * Description:
  * Description:
  *
  *
- * When nand_scan_bbt is called, then it tries to find the bad block table 
- * depending on the options in the bbt descriptor(s). If a bbt is found 
- * then the contents are read and the memory based bbt is created. If a 
+ * When nand_scan_bbt is called, then it tries to find the bad block table
+ * depending on the options in the bbt descriptor(s). If a bbt is found
+ * then the contents are read and the memory based bbt is created. If a
  * mirrored bbt is selected then the mirror is searched too and the
  * mirrored bbt is selected then the mirror is searched too and the
- * versions are compared. If the mirror has a greater version number 
+ * versions are compared. If the mirror has a greater version number
  * than the mirror bbt is used to build the memory based bbt.
  * than the mirror bbt is used to build the memory based bbt.
  * If the tables are not versioned, then we "or" the bad block information.
  * If the tables are not versioned, then we "or" the bad block information.
- * If one of the bbt's is out of date or does not exist it is (re)created. 
- * If no bbt exists at all then the device is scanned for factory marked 
- * good / bad blocks and the bad block tables are created. 
+ * If one of the bbt's is out of date or does not exist it is (re)created.
+ * If no bbt exists at all then the device is scanned for factory marked
+ * good / bad blocks and the bad block tables are created.
  *
  *
- * For manufacturer created bbts like the one found on M-SYS DOC devices 
+ * For manufacturer created bbts like the one found on M-SYS DOC devices
  * the bbt is searched and read but never created
  * the bbt is searched and read but never created
  *
  *
- * The autogenerated bad block table is located in the last good blocks 
- * of the device. The table is mirrored, so it can be updated eventually. 
- * The table is marked in the oob area with an ident pattern and a version 
+ * The autogenerated bad block table is located in the last good blocks
+ * of the device. The table is mirrored, so it can be updated eventually.
+ * The table is marked in the oob area with an ident pattern and a version
  * number which indicates which of both tables is more up to date.
  * number which indicates which of both tables is more up to date.
  *
  *
  * The table uses 2 bits per block
  * The table uses 2 bits per block
@@ -43,13 +43,13 @@
  * 01b:		block is marked bad due to wear
  * 01b:		block is marked bad due to wear
  * 10b:		block is reserved (to protect the bbt area)
  * 10b:		block is reserved (to protect the bbt area)
  * 11b:		block is factory marked bad
  * 11b:		block is factory marked bad
- * 
+ *
  * Multichip devices like DOC store the bad block info per floor.
  * Multichip devices like DOC store the bad block info per floor.
  *
  *
  * Following assumptions are made:
  * Following assumptions are made:
  * - bbts start at a page boundary, if autolocated on a block boundary
  * - bbts start at a page boundary, if autolocated on a block boundary
  * - the space neccecary for a bbt in FLASH does not exceed a block boundary
  * - the space neccecary for a bbt in FLASH does not exceed a block boundary
- * 
+ *
  */
  */
 
 
 #include <common.h>
 #include <common.h>
@@ -63,7 +63,7 @@
 
 
 #include <asm/errno.h>
 #include <asm/errno.h>
 
 
-/** 
+/**
  * check_pattern - [GENERIC] check if a pattern is in the buffer
  * check_pattern - [GENERIC] check if a pattern is in the buffer
  * @buf:	the buffer to search
  * @buf:	the buffer to search
  * @len:	the length of buffer to search
  * @len:	the length of buffer to search
@@ -87,9 +87,9 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des
 			if (p[i] != 0xff)
 			if (p[i] != 0xff)
 				return -1;
 				return -1;
 		}
 		}
-	}	
+	}
 	p += end;
 	p += end;
-	
+
 	/* Compare the pattern */
 	/* Compare the pattern */
 	for (i = 0; i < td->len; i++) {
 	for (i = 0; i < td->len; i++) {
 		if (p[i] != td->pattern[i])
 		if (p[i] != td->pattern[i])
@@ -120,7 +120,7 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des
  * Read the bad block table starting from page.
  * Read the bad block table starting from page.
  *
  *
  */
  */
-static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, 
+static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
 	int bits, int offs, int reserved_block_code)
 	int bits, int offs, int reserved_block_code)
 {
 {
 	int res, i, j, act = 0;
 	int res, i, j, act = 0;
@@ -131,7 +131,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
 
 
 	totlen = (num * bits) >> 3;
 	totlen = (num * bits) >> 3;
 	from = ((loff_t)page) << this->page_shift;
 	from = ((loff_t)page) << this->page_shift;
-	
+
 	while (totlen) {
 	while (totlen) {
 		len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
 		len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
 		res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
 		res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
@@ -141,7 +141,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				return res;
 				return res;
 			}
 			}
 			printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
 			printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
-		}	
+		}
 
 
 		/* Analyse data */
 		/* Analyse data */
 		for (i = 0; i < len; i++) {
 		for (i = 0; i < len; i++) {
@@ -161,12 +161,12 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				 * message to MTD_DEBUG_LEVEL0 */
 				 * message to MTD_DEBUG_LEVEL0 */
 				printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
 				printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
 					((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 					((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
-				/* Factory marked bad or worn out ? */	
+				/* Factory marked bad or worn out ? */
 				if (tmp == 0)
 				if (tmp == 0)
 					this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
 					this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
 				else
 				else
 					this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
 					this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
-			}	
+			}
 		}
 		}
 		totlen -= len;
 		totlen -= len;
 		from += len;
 		from += len;
@@ -178,7 +178,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
  * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page
  * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
  * @buf:	temporary buffer
  * @buf:	temporary buffer
- * @td:		descriptor for the bad block table 
+ * @td:		descriptor for the bad block table
  * @chip:	read the table for a specific chip, -1 read all chips.
  * @chip:	read the table for a specific chip, -1 read all chips.
  *		Applies only if NAND_BBT_PERCHIP option is set
  *		Applies only if NAND_BBT_PERCHIP option is set
  *
  *
@@ -213,7 +213,7 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
  * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
  * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
  * @buf:	temporary buffer
  * @buf:	temporary buffer
- * @td:		descriptor for the bad block table 
+ * @td:		descriptor for the bad block table
  * @md:		descriptor for the bad block table mirror
  * @md:		descriptor for the bad block table mirror
  *
  *
  * Read the bad block table(s) for all chips starting at a given page
  * Read the bad block table(s) for all chips starting at a given page
@@ -225,16 +225,16 @@ static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_de
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 
 
-	/* Read the primary version, if available */	
+	/* Read the primary version, if available */
 	if (td->options & NAND_BBT_VERSION) {
 	if (td->options & NAND_BBT_VERSION) {
-		nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); 
+		nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
 		td->version[0] = buf[mtd->oobblock + td->veroffs];
 		td->version[0] = buf[mtd->oobblock + td->veroffs];
 		printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
 		printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
 	}
 	}
 
 
-	/* Read the mirror version, if available */	
+	/* Read the mirror version, if available */
 	if (md && (md->options & NAND_BBT_VERSION)) {
 	if (md && (md->options & NAND_BBT_VERSION)) {
-		nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); 
+		nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
 		md->version[0] = buf[mtd->oobblock + md->veroffs];
 		md->version[0] = buf[mtd->oobblock + md->veroffs];
 		printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
 		printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
 	}
 	}
@@ -268,7 +268,7 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 	else {
 	else {
 		if (bd->options & NAND_BBT_SCAN2NDPAGE)
 		if (bd->options & NAND_BBT_SCAN2NDPAGE)
 			len = 2;
 			len = 2;
-		else	
+		else
 			len = 1;
 			len = 1;
 	}
 	}
 	scanlen	= mtd->oobblock + mtd->oobsize;
 	scanlen	= mtd->oobblock + mtd->oobsize;
@@ -285,20 +285,20 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 		if (chip >= this->numchips) {
 		if (chip >= this->numchips) {
 			printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
 			printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
 				chip + 1, this->numchips);
 				chip + 1, this->numchips);
-			return;	
+			return;
 		}
 		}
 		numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
 		numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
 		startblock = chip * numblocks;
 		startblock = chip * numblocks;
 		numblocks += startblock;
 		numblocks += startblock;
 		from = startblock << (this->bbt_erase_shift - 1);
 		from = startblock << (this->bbt_erase_shift - 1);
 	}
 	}
-	
+
 	for (i = startblock; i < numblocks;) {
 	for (i = startblock; i < numblocks;) {
 		nand_read_raw (mtd, buf, from, readlen, ooblen);
 		nand_read_raw (mtd, buf, from, readlen, ooblen);
 		for (j = 0; j < len; j++) {
 		for (j = 0; j < len; j++) {
 			if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
 			if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
 				this->bbt[i >> 3] |= 0x03 << (i & 0x6);
 				this->bbt[i >> 3] |= 0x03 << (i & 0x6);
-				printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 
+				printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
 					i >> 1, (unsigned int) from);
 					i >> 1, (unsigned int) from);
 				break;
 				break;
 			}
 			}
@@ -315,15 +315,15 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
  * @td:		descriptor for the bad block table
  * @td:		descriptor for the bad block table
  *
  *
  * Read the bad block table by searching for a given ident pattern.
  * Read the bad block table by searching for a given ident pattern.
- * Search is preformed either from the beginning up or from the end of 
+ * Search is preformed either from the beginning up or from the end of
  * the device downwards. The search starts always at the start of a
  * the device downwards. The search starts always at the start of a
  * block.
  * block.
- * If the option NAND_BBT_PERCHIP is given, each chip is searched 
+ * If the option NAND_BBT_PERCHIP is given, each chip is searched
  * for a bbt, which contains the bad block information of this chip.
  * for a bbt, which contains the bad block information of this chip.
  * This is neccecary to provide support for certain DOC devices.
  * This is neccecary to provide support for certain DOC devices.
  *
  *
- * The bbt ident pattern resides in the oob area of the first page 
- * in a block. 
+ * The bbt ident pattern resides in the oob area of the first page
+ * in a block.
  */
  */
 static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
 static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
 {
 {
@@ -338,10 +338,10 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 		startblock = (mtd->size >> this->bbt_erase_shift) -1;
 		startblock = (mtd->size >> this->bbt_erase_shift) -1;
 		dir = -1;
 		dir = -1;
 	} else {
 	} else {
-		startblock = 0;	
+		startblock = 0;
 		dir = 1;
 		dir = 1;
-	}	
-	
+	}
+
 	/* Do we have a bbt per chip ? */
 	/* Do we have a bbt per chip ? */
 	if (td->options & NAND_BBT_PERCHIP) {
 	if (td->options & NAND_BBT_PERCHIP) {
 		chips = this->numchips;
 		chips = this->numchips;
@@ -351,19 +351,19 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 		chips = 1;
 		chips = 1;
 		bbtblocks = mtd->size >> this->bbt_erase_shift;
 		bbtblocks = mtd->size >> this->bbt_erase_shift;
 	}
 	}
-	
+
 	/* Number of bits for each erase block in the bbt */
 	/* Number of bits for each erase block in the bbt */
 	bits = td->options & NAND_BBT_NRBITS_MSK;
 	bits = td->options & NAND_BBT_NRBITS_MSK;
-	
+
 	for (i = 0; i < chips; i++) {
 	for (i = 0; i < chips; i++) {
 		/* Reset version information */
 		/* Reset version information */
-		td->version[i] = 0;	
+		td->version[i] = 0;
 		td->pages[i] = -1;
 		td->pages[i] = -1;
 		/* Scan the maximum number of blocks */
 		/* Scan the maximum number of blocks */
 		for (block = 0; block < td->maxblocks; block++) {
 		for (block = 0; block < td->maxblocks; block++) {
 			int actblock = startblock + dir * block;
 			int actblock = startblock + dir * block;
 			/* Read first page */
 			/* Read first page */
-			nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize); 
+			nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
 			if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
 			if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
 				td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
 				td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
 				if (td->options & NAND_BBT_VERSION) {
 				if (td->options & NAND_BBT_VERSION) {
@@ -381,46 +381,46 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 		else
 		else
 			printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]);
 			printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]);
 	}
 	}
-	return 0;	
+	return 0;
 }
 }
 
 
 /**
 /**
  * search_read_bbts - [GENERIC] scan the device for bad block table(s)
  * search_read_bbts - [GENERIC] scan the device for bad block table(s)
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
  * @buf:	temporary buffer
  * @buf:	temporary buffer
- * @td:		descriptor for the bad block table 
+ * @td:		descriptor for the bad block table
  * @md:		descriptor for the bad block table mirror
  * @md:		descriptor for the bad block table mirror
  *
  *
  * Search and read the bad block table(s)
  * Search and read the bad block table(s)
 */
 */
-static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, 
+static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
 	struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 	struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
 {
 	/* Search the primary table */
 	/* Search the primary table */
 	search_bbt (mtd, buf, td);
 	search_bbt (mtd, buf, td);
-		
+
 	/* Search the mirror table */
 	/* Search the mirror table */
 	if (md)
 	if (md)
 		search_bbt (mtd, buf, md);
 		search_bbt (mtd, buf, md);
-	
+
 	/* Force result check */
 	/* Force result check */
-	return 1;	
+	return 1;
 }
 }
-	
 
 
-/** 
+
+/**
  * write_bbt - [GENERIC] (Re)write the bad block table
  * write_bbt - [GENERIC] (Re)write the bad block table
  *
  *
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
  * @buf:	temporary buffer
  * @buf:	temporary buffer
- * @td:		descriptor for the bad block table 
+ * @td:		descriptor for the bad block table
  * @md:		descriptor for the bad block table mirror
  * @md:		descriptor for the bad block table mirror
  * @chipsel:	selector for a specific chip, -1 for all
  * @chipsel:	selector for a specific chip, -1 for all
  *
  *
  * (Re)write the bad block table
  * (Re)write the bad block table
  *
  *
 */
 */
-static int write_bbt (struct mtd_info *mtd, uint8_t *buf, 
+static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
 	struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
 	struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
@@ -439,7 +439,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
 	/* Write bad block table per chip rather than per device ? */
 	/* Write bad block table per chip rather than per device ? */
 	if (td->options & NAND_BBT_PERCHIP) {
 	if (td->options & NAND_BBT_PERCHIP) {
 		numblocks = (int) (this->chipsize >> this->bbt_erase_shift);
 		numblocks = (int) (this->chipsize >> this->bbt_erase_shift);
-		/* Full device write or specific chip ? */	
+		/* Full device write or specific chip ? */
 		if (chipsel == -1) {
 		if (chipsel == -1) {
 			nrchips = this->numchips;
 			nrchips = this->numchips;
 		} else {
 		} else {
@@ -449,19 +449,19 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
 	} else {
 	} else {
 		numblocks = (int) (mtd->size >> this->bbt_erase_shift);
 		numblocks = (int) (mtd->size >> this->bbt_erase_shift);
 		nrchips = 1;
 		nrchips = 1;
-	}	
-	
+	}
+
 	/* Loop through the chips */
 	/* Loop through the chips */
 	for (; chip < nrchips; chip++) {
 	for (; chip < nrchips; chip++) {
-		
-		/* There was already a version of the table, reuse the page 
-		 * This applies for absolute placement too, as we have the 
+
+		/* There was already a version of the table, reuse the page
+		 * This applies for absolute placement too, as we have the
 		 * page nr. in td->pages.
 		 * page nr. in td->pages.
 		 */
 		 */
 		if (td->pages[chip] != -1) {
 		if (td->pages[chip] != -1) {
 			page = td->pages[chip];
 			page = td->pages[chip];
 			goto write;
 			goto write;
-		}	
+		}
 
 
 		/* Automatic placement of the bad block table */
 		/* Automatic placement of the bad block table */
 		/* Search direction top -> down ? */
 		/* Search direction top -> down ? */
@@ -471,7 +471,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
 		} else {
 		} else {
 			startblock = chip * numblocks;
 			startblock = chip * numblocks;
 			dir = 1;
 			dir = 1;
-		}	
+		}
 
 
 		for (i = 0; i < td->maxblocks; i++) {
 		for (i = 0; i < td->maxblocks; i++) {
 			int block = startblock + dir * i;
 			int block = startblock + dir * i;
@@ -488,7 +488,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
 		}
 		}
 		printk (KERN_ERR "No space left to write bad block table\n");
 		printk (KERN_ERR "No space left to write bad block table\n");
 		return -ENOSPC;
 		return -ENOSPC;
-write:	
+write:
 
 
 		/* Set up shift count and masks for the flash table */
 		/* Set up shift count and masks for the flash table */
 		bits = td->options & NAND_BBT_NRBITS_MSK;
 		bits = td->options & NAND_BBT_NRBITS_MSK;
@@ -499,14 +499,14 @@ write:
 		case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break;
 		case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break;
 		default: return -EINVAL;
 		default: return -EINVAL;
 		}
 		}
-		
+
 		bbtoffs = chip * (numblocks >> 2);
 		bbtoffs = chip * (numblocks >> 2);
-		
+
 		to = ((loff_t) page) << this->page_shift;
 		to = ((loff_t) page) << this->page_shift;
 
 
 		memcpy (&oobinfo, this->autooob, sizeof(oobinfo));
 		memcpy (&oobinfo, this->autooob, sizeof(oobinfo));
 		oobinfo.useecc = MTD_NANDECC_PLACEONLY;
 		oobinfo.useecc = MTD_NANDECC_PLACEONLY;
-		
+
 		/* Must we save the block contents ? */
 		/* Must we save the block contents ? */
 		if (td->options & NAND_BBT_SAVECONTENT) {
 		if (td->options & NAND_BBT_SAVECONTENT) {
 			/* Make it block aligned */
 			/* Make it block aligned */
@@ -545,7 +545,7 @@ write:
 				buf[len + td->veroffs] = td->version[chip];
 				buf[len + td->veroffs] = td->version[chip];
 			}
 			}
 		}
 		}
-	
+
 		/* walk through the memory table */
 		/* walk through the memory table */
 		for (i = 0; i < numblocks; ) {
 		for (i = 0; i < numblocks; ) {
 			uint8_t dat;
 			uint8_t dat;
@@ -557,7 +557,7 @@ write:
 				dat >>= 2;
 				dat >>= 2;
 			}
 			}
 		}
 		}
-		
+
 		memset (&einfo, 0, sizeof (einfo));
 		memset (&einfo, 0, sizeof (einfo));
 		einfo.mtd = mtd;
 		einfo.mtd = mtd;
 		einfo.addr = (unsigned long) to;
 		einfo.addr = (unsigned long) to;
@@ -567,18 +567,18 @@ write:
 			printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
 			printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
 			return res;
 			return res;
 		}
 		}
-	
+
 		res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
 		res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
 		if (res < 0) {
 		if (res < 0) {
 			printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
 			printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
 			return res;
 			return res;
 		}
 		}
-		printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", 
+		printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n",
 			(unsigned int) to, td->version[chip]);
 			(unsigned int) to, td->version[chip]);
-	
+
 		/* Mark it as used */
 		/* Mark it as used */
 		td->pages[chip] = page;
 		td->pages[chip] = page;
-	}	
+	}
 	return 0;
 	return 0;
 }
 }
 
 
@@ -587,7 +587,7 @@ write:
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
  * @bd:		descriptor for the good/bad block search pattern
  * @bd:		descriptor for the good/bad block search pattern
  *
  *
- * The function creates a memory based bbt by scanning the device 
+ * The function creates a memory based bbt by scanning the device
  * for manufacturer / software marked good / bad blocks
  * for manufacturer / software marked good / bad blocks
 */
 */
 static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
 static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
@@ -621,11 +621,11 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
 	struct nand_bbt_descr *rd, *rd2;
 	struct nand_bbt_descr *rd, *rd2;
 
 
 	/* Do we have a bbt per chip ? */
 	/* Do we have a bbt per chip ? */
-	if (td->options & NAND_BBT_PERCHIP) 
+	if (td->options & NAND_BBT_PERCHIP)
 		chips = this->numchips;
 		chips = this->numchips;
-	else 
+	else
 		chips = 1;
 		chips = 1;
-	
+
 	for (i = 0; i < chips; i++) {
 	for (i = 0; i < chips; i++) {
 		writeops = 0;
 		writeops = 0;
 		rd = NULL;
 		rd = NULL;
@@ -640,7 +640,7 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
 			}
 			}
 
 
 			if (td->pages[i] == -1) {
 			if (td->pages[i] == -1) {
-				rd = md;				
+				rd = md;
 				td->version[i] = md->version[i];
 				td->version[i] = md->version[i];
 				writeops = 1;
 				writeops = 1;
 				goto writecheck;
 				goto writecheck;
@@ -658,7 +658,7 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
 				if (!(td->options & NAND_BBT_VERSION))
 				if (!(td->options & NAND_BBT_VERSION))
 					rd2 = md;
 					rd2 = md;
 				goto writecheck;
 				goto writecheck;
-			}	
+			}
 
 
 			if (((int8_t) (td->version[i] - md->version[i])) > 0) {
 			if (((int8_t) (td->version[i] - md->version[i])) > 0) {
 				rd = td;
 				rd = td;
@@ -683,15 +683,15 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
 create:
 create:
 		/* Create the bad block table by scanning the device ? */
 		/* Create the bad block table by scanning the device ? */
 		if (!(td->options & NAND_BBT_CREATE))
 		if (!(td->options & NAND_BBT_CREATE))
-			continue;	
-		
+			continue;
+
 		/* Create the table in memory by scanning the chip(s) */
 		/* Create the table in memory by scanning the chip(s) */
 		create_bbt (mtd, buf, bd, chipsel);
 		create_bbt (mtd, buf, bd, chipsel);
-		
+
 		td->version[i] = 1;
 		td->version[i] = 1;
 		if (md)
 		if (md)
-			md->version[i] = 1;	
-writecheck:	
+			md->version[i] = 1;
+writecheck:
 		/* read back first ? */
 		/* read back first ? */
 		if (rd)
 		if (rd)
 			read_abs_bbt (mtd, buf, rd, chipsel);
 			read_abs_bbt (mtd, buf, rd, chipsel);
@@ -705,7 +705,7 @@ writecheck:
 			if (res < 0)
 			if (res < 0)
 				return res;
 				return res;
 		}
 		}
-		
+
 		/* Write the mirror bad block table to the device ? */
 		/* Write the mirror bad block table to the device ? */
 		if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
 		if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
 			res = write_bbt (mtd, buf, md, td, chipsel);
 			res = write_bbt (mtd, buf, md, td, chipsel);
@@ -713,11 +713,11 @@ writecheck:
 				return res;
 				return res;
 		}
 		}
 	}
 	}
-	return 0;	
+	return 0;
 }
 }
 
 
 /**
 /**
- * mark_bbt_regions - [GENERIC] mark the bad block table regions 
+ * mark_bbt_regions - [GENERIC] mark the bad block table regions
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
  * @td:		bad block table descriptor
  * @td:		bad block table descriptor
  *
  *
@@ -738,14 +738,14 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
 	} else {
 	} else {
 		chips = 1;
 		chips = 1;
 		nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
 		nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
-	}	
-	
+	}
+
 	for (i = 0; i < chips; i++) {
 	for (i = 0; i < chips; i++) {
 		if ((td->options & NAND_BBT_ABSPAGE) ||
 		if ((td->options & NAND_BBT_ABSPAGE) ||
 		    !(td->options & NAND_BBT_WRITE)) {
 		    !(td->options & NAND_BBT_WRITE)) {
 		    	if (td->pages[i] == -1) continue;
 		    	if (td->pages[i] == -1) continue;
 			block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
 			block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
-			block <<= 1;		
+			block <<= 1;
 			oldval = this->bbt[(block >> 3)];
 			oldval = this->bbt[(block >> 3)];
 			newval = oldval | (0x2 << (block & 0x06));
 			newval = oldval | (0x2 << (block & 0x06));
 			this->bbt[(block >> 3)] = newval;
 			this->bbt[(block >> 3)] = newval;
@@ -756,16 +756,16 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
 		update = 0;
 		update = 0;
 		if (td->options & NAND_BBT_LASTBLOCK)
 		if (td->options & NAND_BBT_LASTBLOCK)
 			block = ((i + 1) * nrblocks) - td->maxblocks;
 			block = ((i + 1) * nrblocks) - td->maxblocks;
-		else	
+		else
 			block = i * nrblocks;
 			block = i * nrblocks;
-		block <<= 1;	
+		block <<= 1;
 		for (j = 0; j < td->maxblocks; j++) {
 		for (j = 0; j < td->maxblocks; j++) {
 			oldval = this->bbt[(block >> 3)];
 			oldval = this->bbt[(block >> 3)];
 			newval = oldval | (0x2 << (block & 0x06));
 			newval = oldval | (0x2 << (block & 0x06));
 			this->bbt[(block >> 3)] = newval;
 			this->bbt[(block >> 3)] = newval;
 			if (oldval != newval) update = 1;
 			if (oldval != newval) update = 1;
 			block += 2;
 			block += 2;
-		}	
+		}
 		/* If we want reserved blocks to be recorded to flash, and some
 		/* If we want reserved blocks to be recorded to flash, and some
 		   new ones have been marked, then we need to update the stored
 		   new ones have been marked, then we need to update the stored
 		   bbts.  This should only happen once. */
 		   bbts.  This should only happen once. */
@@ -779,7 +779,7 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
  * @bd:		descriptor for the good/bad block search pattern
  * @bd:		descriptor for the good/bad block search pattern
  *
  *
- * The function checks, if a bad block table(s) is/are already 
+ * The function checks, if a bad block table(s) is/are already
  * available. If not it scans the device for manufacturer
  * available. If not it scans the device for manufacturer
  * marked good / bad blocks and writes the bad block table(s) to
  * marked good / bad blocks and writes the bad block table(s) to
  * the selected place.
  * the selected place.
@@ -822,30 +822,30 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
 		this->bbt = NULL;
 		this->bbt = NULL;
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
-	
+
 	/* Is the bbt at a given page ? */
 	/* Is the bbt at a given page ? */
 	if (td->options & NAND_BBT_ABSPAGE) {
 	if (td->options & NAND_BBT_ABSPAGE) {
 		res = read_abs_bbts (mtd, buf, td, md);
 		res = read_abs_bbts (mtd, buf, td, md);
-	} else {	
+	} else {
 		/* Search the bad block table using a pattern in oob */
 		/* Search the bad block table using a pattern in oob */
 		res = search_read_bbts (mtd, buf, td, md);
 		res = search_read_bbts (mtd, buf, td, md);
-	}	
+	}
 
 
-	if (res) 
+	if (res)
 		res = check_create (mtd, buf, bd);
 		res = check_create (mtd, buf, bd);
-	
+
 	/* Prevent the bbt regions from erasing / writing */
 	/* Prevent the bbt regions from erasing / writing */
 	mark_bbt_region (mtd, td);
 	mark_bbt_region (mtd, td);
 	if (md)
 	if (md)
 		mark_bbt_region (mtd, md);
 		mark_bbt_region (mtd, md);
-	
+
 	kfree (buf);
 	kfree (buf);
 	return res;
 	return res;
 }
 }
 
 
 
 
 /**
 /**
- * nand_update_bbt - [NAND Interface] update bad block table(s) 
+ * nand_update_bbt - [NAND Interface] update bad block table(s)
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
  * @offs:	the offset of the newly marked block
  * @offs:	the offset of the newly marked block
  *
  *
@@ -872,7 +872,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
 		printk (KERN_ERR "nand_update_bbt: Out of memory\n");
 		printk (KERN_ERR "nand_update_bbt: Out of memory\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
-	
+
 	writeops = md != NULL ? 0x03 : 0x01;
 	writeops = md != NULL ? 0x03 : 0x01;
 
 
 	/* Do we have a bbt per chip ? */
 	/* Do we have a bbt per chip ? */
@@ -886,7 +886,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
 
 
 	td->version[chip]++;
 	td->version[chip]++;
 	if (md)
 	if (md)
-		md->version[chip]++;	
+		md->version[chip]++;
 
 
 	/* Write the bad block table to the device ? */
 	/* Write the bad block table to the device ? */
 	if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
 	if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
@@ -899,15 +899,15 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
 		res = write_bbt (mtd, buf, md, td, chipsel);
 		res = write_bbt (mtd, buf, md, td, chipsel);
 	}
 	}
 
 
-out:	
+out:
 	kfree (buf);
 	kfree (buf);
 	return res;
 	return res;
 }
 }
 
 
-/* Define some generic bad / good block scan pattern which are used 
+/* Define some generic bad / good block scan pattern which are used
  * while scanning a device for factory marked good / bad blocks
  * while scanning a device for factory marked good / bad blocks
- * 
- * The memory based patterns just 
+ *
+ * The memory based patterns just
  */
  */
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
 
@@ -954,7 +954,7 @@ static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
 static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
 static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
 
 
 static struct nand_bbt_descr bbt_main_descr = {
 static struct nand_bbt_descr bbt_main_descr = {
-	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE 
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
 	.offs =	8,
 	.offs =	8,
 	.len = 4,
 	.len = 4,
@@ -964,7 +964,7 @@ static struct nand_bbt_descr bbt_main_descr = {
 };
 };
 
 
 static struct nand_bbt_descr bbt_mirror_descr = {
 static struct nand_bbt_descr bbt_mirror_descr = {
-	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE 
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
 	.offs =	8,
 	.offs =	8,
 	.len = 4,
 	.len = 4,
@@ -974,7 +974,7 @@ static struct nand_bbt_descr bbt_mirror_descr = {
 };
 };
 
 
 /**
 /**
- * nand_default_bbt - [NAND Interface] Select a default bad block table for the device 
+ * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
  *
  *
  * This function selects the default bad block table
  * This function selects the default bad block table
@@ -984,29 +984,29 @@ static struct nand_bbt_descr bbt_mirror_descr = {
 int nand_default_bbt (struct mtd_info *mtd)
 int nand_default_bbt (struct mtd_info *mtd)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
-	
-	/* Default for AG-AND. We must use a flash based 
+
+	/* Default for AG-AND. We must use a flash based
 	 * bad block table as the devices have factory marked
 	 * bad block table as the devices have factory marked
 	 * _good_ blocks. Erasing those blocks leads to loss
 	 * _good_ blocks. Erasing those blocks leads to loss
 	 * of the good / bad information, so we _must_ store
 	 * of the good / bad information, so we _must_ store
-	 * this information in a good / bad table during 
+	 * this information in a good / bad table during
 	 * startup
 	 * startup
 	*/
 	*/
 	if (this->options & NAND_IS_AND) {
 	if (this->options & NAND_IS_AND) {
 		/* Use the default pattern descriptors */
 		/* Use the default pattern descriptors */
-		if (!this->bbt_td) {	
+		if (!this->bbt_td) {
 			this->bbt_td = &bbt_main_descr;
 			this->bbt_td = &bbt_main_descr;
 			this->bbt_md = &bbt_mirror_descr;
 			this->bbt_md = &bbt_mirror_descr;
-		}	
+		}
 		this->options |= NAND_USE_FLASH_BBT;
 		this->options |= NAND_USE_FLASH_BBT;
 		return nand_scan_bbt (mtd, &agand_flashbased);
 		return nand_scan_bbt (mtd, &agand_flashbased);
 	}
 	}
-	
-	
+
+
 	/* Is a flash based bad block table requested ? */
 	/* Is a flash based bad block table requested ? */
 	if (this->options & NAND_USE_FLASH_BBT) {
 	if (this->options & NAND_USE_FLASH_BBT) {
-		/* Use the default pattern descriptors */	
-		if (!this->bbt_td) {	
+		/* Use the default pattern descriptors */
+		if (!this->bbt_td) {
 			this->bbt_td = &bbt_main_descr;
 			this->bbt_td = &bbt_main_descr;
 			this->bbt_md = &bbt_mirror_descr;
 			this->bbt_md = &bbt_mirror_descr;
 		}
 		}
@@ -1026,23 +1026,23 @@ int nand_default_bbt (struct mtd_info *mtd)
 }
 }
 
 
 /**
 /**
- * nand_isbad_bbt - [NAND Interface] Check if a block is bad 
+ * nand_isbad_bbt - [NAND Interface] Check if a block is bad
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
  * @offs:	offset in the device
  * @offs:	offset in the device
  * @allowbbt:	allow access to bad block table region
  * @allowbbt:	allow access to bad block table region
  *
  *
-*/
+ */
 int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
 int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
 {
 {
 	struct nand_chip *this = mtd->priv;
 	struct nand_chip *this = mtd->priv;
 	int block;
 	int block;
 	uint8_t	res;
 	uint8_t	res;
-	
+
 	/* Get block number * 2 */
 	/* Get block number * 2 */
 	block = (int) (offs >> (this->bbt_erase_shift - 1));
 	block = (int) (offs >> (this->bbt_erase_shift - 1));
 	res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 	res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
 
-	DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", 
+	DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
 		(unsigned int)offs, res, block >> 1);
 		(unsigned int)offs, res, block >> 1);
 
 
 	switch ((int)res) {
 	switch ((int)res) {

+ 22 - 23
drivers/nand/nand_ecc.c

@@ -13,16 +13,16 @@
  * under the terms of the GNU General Public License as published by the
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 or (at your option) any
  * Free Software Foundation; either version 2 or (at your option) any
  * later version.
  * later version.
- * 
+ *
  * This file is distributed in the hope that it will be useful, but WITHOUT
  * This file is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  * for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License along
  * You should have received a copy of the GNU General Public License along
  * with this file; if not, write to the Free Software Foundation, Inc.,
  * with this file; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- * 
+ *
  * As a special exception, if other files instantiate templates or use
  * As a special exception, if other files instantiate templates or use
  * macros or inline functions from these files, or you compile these
  * macros or inline functions from these files, or you compile these
  * files and link them with other works to produce a work based on these
  * files and link them with other works to produce a work based on these
@@ -30,7 +30,7 @@
  * covered by the GNU General Public License. However the source code for
  * covered by the GNU General Public License. However the source code for
  * these files must still be made available in accordance with section (3)
  * these files must still be made available in accordance with section (3)
  * of the GNU General Public License.
  * of the GNU General Public License.
- * 
+ *
  * This exception does not invalidate any other reasons why a work based on
  * This exception does not invalidate any other reasons why a work based on
  * this file might be covered by the GNU General Public License.
  * this file might be covered by the GNU General Public License.
  */
  */
@@ -66,7 +66,7 @@ static const u_char nand_ecc_precalc_table[] = {
  * nand_trans_result - [GENERIC] create non-inverted ECC
  * nand_trans_result - [GENERIC] create non-inverted ECC
  * @reg2:	line parity reg 2
  * @reg2:	line parity reg 2
  * @reg3:	line parity reg 3
  * @reg3:	line parity reg 3
- * @ecc_code:	ecc 
+ * @ecc_code:	ecc
  *
  *
  * Creates non-inverted ECC code from line parity
  * Creates non-inverted ECC code from line parity
  */
  */
@@ -74,11 +74,11 @@ static void nand_trans_result(u_char reg2, u_char reg3,
 	u_char *ecc_code)
 	u_char *ecc_code)
 {
 {
 	u_char a, b, i, tmp1, tmp2;
 	u_char a, b, i, tmp1, tmp2;
-	
+
 	/* Initialize variables */
 	/* Initialize variables */
 	a = b = 0x80;
 	a = b = 0x80;
 	tmp1 = tmp2 = 0;
 	tmp1 = tmp2 = 0;
-	
+
 	/* Calculate first ECC byte */
 	/* Calculate first ECC byte */
 	for (i = 0; i < 4; i++) {
 	for (i = 0; i < 4; i++) {
 		if (reg3 & a)		/* LP15,13,11,9 --> ecc_code[0] */
 		if (reg3 & a)		/* LP15,13,11,9 --> ecc_code[0] */
@@ -89,7 +89,7 @@ static void nand_trans_result(u_char reg2, u_char reg3,
 		b >>= 1;
 		b >>= 1;
 		a >>= 1;
 		a >>= 1;
 	}
 	}
-	
+
 	/* Calculate second ECC byte */
 	/* Calculate second ECC byte */
 	b = 0x80;
 	b = 0x80;
 	for (i = 0; i < 4; i++) {
 	for (i = 0; i < 4; i++) {
@@ -101,7 +101,7 @@ static void nand_trans_result(u_char reg2, u_char reg3,
 		b >>= 1;
 		b >>= 1;
 		a >>= 1;
 		a >>= 1;
 	}
 	}
-	
+
 	/* Store two of the ECC bytes */
 	/* Store two of the ECC bytes */
 	ecc_code[0] = tmp1;
 	ecc_code[0] = tmp1;
 	ecc_code[1] = tmp2;
 	ecc_code[1] = tmp2;
@@ -117,28 +117,28 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code
 {
 {
 	u_char idx, reg1, reg2, reg3;
 	u_char idx, reg1, reg2, reg3;
 	int j;
 	int j;
-	
+
 	/* Initialize variables */
 	/* Initialize variables */
 	reg1 = reg2 = reg3 = 0;
 	reg1 = reg2 = reg3 = 0;
 	ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
 	ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
-	
-	/* Build up column parity */ 
+
+	/* Build up column parity */
 	for(j = 0; j < 256; j++) {
 	for(j = 0; j < 256; j++) {
-		
+
 		/* Get CP0 - CP5 from table */
 		/* Get CP0 - CP5 from table */
 		idx = nand_ecc_precalc_table[dat[j]];
 		idx = nand_ecc_precalc_table[dat[j]];
 		reg1 ^= (idx & 0x3f);
 		reg1 ^= (idx & 0x3f);
-		
+
 		/* All bit XOR = 1 ? */
 		/* All bit XOR = 1 ? */
 		if (idx & 0x40) {
 		if (idx & 0x40) {
 			reg3 ^= (u_char) j;
 			reg3 ^= (u_char) j;
 			reg2 ^= ~((u_char) j);
 			reg2 ^= ~((u_char) j);
 		}
 		}
 	}
 	}
-	
+
 	/* Create non-inverted ECC code from line parity */
 	/* Create non-inverted ECC code from line parity */
 	nand_trans_result(reg2, reg3, ecc_code);
 	nand_trans_result(reg2, reg3, ecc_code);
-	
+
 	/* Calculate final ECC code */
 	/* Calculate final ECC code */
 	ecc_code[0] = ~ecc_code[0];
 	ecc_code[0] = ~ecc_code[0];
 	ecc_code[1] = ~ecc_code[1];
 	ecc_code[1] = ~ecc_code[1];
@@ -158,12 +158,12 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code
 int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
 int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
 {
 {
 	u_char a, b, c, d1, d2, d3, add, bit, i;
 	u_char a, b, c, d1, d2, d3, add, bit, i;
-	
-	/* Do error detection */ 
+
+	/* Do error detection */
 	d1 = calc_ecc[0] ^ read_ecc[0];
 	d1 = calc_ecc[0] ^ read_ecc[0];
 	d2 = calc_ecc[1] ^ read_ecc[1];
 	d2 = calc_ecc[1] ^ read_ecc[1];
 	d3 = calc_ecc[2] ^ read_ecc[2];
 	d3 = calc_ecc[2] ^ read_ecc[2];
-	
+
 	if ((d1 | d2 | d3) == 0) {
 	if ((d1 | d2 | d3) == 0) {
 		/* No errors */
 		/* No errors */
 		return 0;
 		return 0;
@@ -172,7 +172,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha
 		a = (d1 ^ (d1 >> 1)) & 0x55;
 		a = (d1 ^ (d1 >> 1)) & 0x55;
 		b = (d2 ^ (d2 >> 1)) & 0x55;
 		b = (d2 ^ (d2 >> 1)) & 0x55;
 		c = (d3 ^ (d3 >> 1)) & 0x54;
 		c = (d3 ^ (d3 >> 1)) & 0x54;
-		
+
 		/* Found and will correct single bit error in the data */
 		/* Found and will correct single bit error in the data */
 		if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
 		if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
 			c = 0x80;
 			c = 0x80;
@@ -205,8 +205,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha
 			a ^= (b << bit);
 			a ^= (b << bit);
 			dat[add] = a;
 			dat[add] = a;
 			return 1;
 			return 1;
-		}
-		else {
+		} else {
 			i = 0;
 			i = 0;
 			while (d1) {
 			while (d1) {
 				if (d1 & 0x01)
 				if (d1 & 0x01)
@@ -236,7 +235,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha
 			}
 			}
 		}
 		}
 	}
 	}
-	
+
 	/* Should never happen */
 	/* Should never happen */
 	return -1;
 	return -1;
 }
 }

+ 14 - 14
drivers/nand/nand_ids.c

@@ -18,14 +18,14 @@
 
 
 /*
 /*
 *	Chip ID list
 *	Chip ID list
-*	
+*
 *	Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
 *	Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
 *	options
 *	options
-* 
+*
 * 	Pagesize; 0, 256, 512
 * 	Pagesize; 0, 256, 512
 *	0 	get this information from the extended chip ID
 *	0 	get this information from the extended chip ID
 +	256	256 Byte page size
 +	256	256 Byte page size
-*	512	512 Byte page size	
+*	512	512 Byte page size
 */
 */
 struct nand_flash_dev nand_flash_ids[] = {
 struct nand_flash_dev nand_flash_ids[] = {
 	{"NAND 1MiB 5V 8-bit", 		0x6e, 256, 1, 0x1000, 0},
 	{"NAND 1MiB 5V 8-bit", 		0x6e, 256, 1, 0x1000, 0},
@@ -38,36 +38,36 @@ struct nand_flash_dev nand_flash_ids[] = {
 	{"NAND 4MiB 3,3V 8-bit", 	0xe3, 512, 4, 0x2000, 0},
 	{"NAND 4MiB 3,3V 8-bit", 	0xe3, 512, 4, 0x2000, 0},
 	{"NAND 4MiB 3,3V 8-bit", 	0xe5, 512, 4, 0x2000, 0},
 	{"NAND 4MiB 3,3V 8-bit", 	0xe5, 512, 4, 0x2000, 0},
 	{"NAND 8MiB 3,3V 8-bit", 	0xd6, 512, 8, 0x2000, 0},
 	{"NAND 8MiB 3,3V 8-bit", 	0xd6, 512, 8, 0x2000, 0},
-	
+
 	{"NAND 8MiB 1,8V 8-bit", 	0x39, 512, 8, 0x2000, 0},
 	{"NAND 8MiB 1,8V 8-bit", 	0x39, 512, 8, 0x2000, 0},
 	{"NAND 8MiB 3,3V 8-bit", 	0xe6, 512, 8, 0x2000, 0},
 	{"NAND 8MiB 3,3V 8-bit", 	0xe6, 512, 8, 0x2000, 0},
 	{"NAND 8MiB 1,8V 16-bit", 	0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
 	{"NAND 8MiB 1,8V 16-bit", 	0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
 	{"NAND 8MiB 3,3V 16-bit", 	0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
 	{"NAND 8MiB 3,3V 16-bit", 	0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
-	
+
 	{"NAND 16MiB 1,8V 8-bit", 	0x33, 512, 16, 0x4000, 0},
 	{"NAND 16MiB 1,8V 8-bit", 	0x33, 512, 16, 0x4000, 0},
 	{"NAND 16MiB 3,3V 8-bit", 	0x73, 512, 16, 0x4000, 0},
 	{"NAND 16MiB 3,3V 8-bit", 	0x73, 512, 16, 0x4000, 0},
 	{"NAND 16MiB 1,8V 16-bit", 	0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 16MiB 1,8V 16-bit", 	0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 16MiB 3,3V 16-bit", 	0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 16MiB 3,3V 16-bit", 	0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
-	
+
 	{"NAND 32MiB 1,8V 8-bit", 	0x35, 512, 32, 0x4000, 0},
 	{"NAND 32MiB 1,8V 8-bit", 	0x35, 512, 32, 0x4000, 0},
 	{"NAND 32MiB 3,3V 8-bit", 	0x75, 512, 32, 0x4000, 0},
 	{"NAND 32MiB 3,3V 8-bit", 	0x75, 512, 32, 0x4000, 0},
 	{"NAND 32MiB 1,8V 16-bit", 	0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 32MiB 1,8V 16-bit", 	0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 32MiB 3,3V 16-bit", 	0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 32MiB 3,3V 16-bit", 	0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
-	
+
 	{"NAND 64MiB 1,8V 8-bit", 	0x36, 512, 64, 0x4000, 0},
 	{"NAND 64MiB 1,8V 8-bit", 	0x36, 512, 64, 0x4000, 0},
 	{"NAND 64MiB 3,3V 8-bit", 	0x76, 512, 64, 0x4000, 0},
 	{"NAND 64MiB 3,3V 8-bit", 	0x76, 512, 64, 0x4000, 0},
 	{"NAND 64MiB 1,8V 16-bit", 	0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 64MiB 1,8V 16-bit", 	0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 64MiB 3,3V 16-bit", 	0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 64MiB 3,3V 16-bit", 	0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
-	
+
 	{"NAND 128MiB 1,8V 8-bit", 	0x78, 512, 128, 0x4000, 0},
 	{"NAND 128MiB 1,8V 8-bit", 	0x78, 512, 128, 0x4000, 0},
 	{"NAND 128MiB 3,3V 8-bit", 	0x79, 512, 128, 0x4000, 0},
 	{"NAND 128MiB 3,3V 8-bit", 	0x79, 512, 128, 0x4000, 0},
 	{"NAND 128MiB 1,8V 16-bit", 	0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 128MiB 1,8V 16-bit", 	0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 128MiB 3,3V 16-bit", 	0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
 	{"NAND 128MiB 3,3V 16-bit", 	0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-	
+
 	{"NAND 256MiB 3,3V 8-bit", 	0x71, 512, 256, 0x4000, 0},
 	{"NAND 256MiB 3,3V 8-bit", 	0x71, 512, 256, 0x4000, 0},
 
 
 	{"NAND 512MiB 3,3V 8-bit", 	0xDC, 512, 512, 0x4000, 0},
 	{"NAND 512MiB 3,3V 8-bit", 	0xDC, 512, 512, 0x4000, 0},
-	
+
 	/* These are the new chips with large page size. The pagesize
 	/* These are the new chips with large page size. The pagesize
 	* and the erasesize is determined from the extended id bytes
 	* and the erasesize is determined from the extended id bytes
 	*/
 	*/
@@ -82,13 +82,13 @@ struct nand_flash_dev nand_flash_ids[] = {
 	{"NAND 256MiB 3,3V 8-bit", 	0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 	{"NAND 256MiB 3,3V 8-bit", 	0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 	{"NAND 256MiB 1,8V 16-bit", 	0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 	{"NAND 256MiB 1,8V 16-bit", 	0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 	{"NAND 256MiB 3,3V 16-bit", 	0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 	{"NAND 256MiB 3,3V 16-bit", 	0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-	
+
 	/* 4 Gigabit */
 	/* 4 Gigabit */
 	{"NAND 512MiB 1,8V 8-bit", 	0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 	{"NAND 512MiB 1,8V 8-bit", 	0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 	{"NAND 512MiB 3,3V 8-bit", 	0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 	{"NAND 512MiB 3,3V 8-bit", 	0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 	{"NAND 512MiB 1,8V 16-bit", 	0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 	{"NAND 512MiB 1,8V 16-bit", 	0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 	{"NAND 512MiB 3,3V 16-bit", 	0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 	{"NAND 512MiB 3,3V 16-bit", 	0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-	
+
 	/* 8 Gigabit */
 	/* 8 Gigabit */
 	{"NAND 1GiB 1,8V 8-bit", 	0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 	{"NAND 1GiB 1,8V 8-bit", 	0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 	{"NAND 1GiB 3,3V 8-bit", 	0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 	{"NAND 1GiB 3,3V 8-bit", 	0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
@@ -101,11 +101,11 @@ struct nand_flash_dev nand_flash_ids[] = {
 	{"NAND 2GiB 1,8V 16-bit", 	0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 	{"NAND 2GiB 1,8V 16-bit", 	0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 	{"NAND 2GiB 3,3V 16-bit", 	0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 	{"NAND 2GiB 3,3V 16-bit", 	0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 
 
-	/* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout ! 
+	/* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout !
 	 * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes
 	 * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes
 	 * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7
 	 * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7
 	 * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
 	 * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
-	 * There are more speed improvements for reads and writes possible, but not implemented now 
+	 * There are more speed improvements for reads and writes possible, but not implemented now
 	 */
 	 */
 	{"AND 128MiB 3,3V 8-bit",	0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},
 	{"AND 128MiB 3,3V 8-bit",	0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},
 
 

+ 4 - 4
fs/jffs2/jffs2_1pass.c

@@ -143,7 +143,7 @@
 /* keeps pointer to currentlu processed partition */
 /* keeps pointer to currentlu processed partition */
 static struct part_info *current_part;
 static struct part_info *current_part;
 
 
-#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
+#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CONFIG_NEW_NAND_CODE)
 /*
 /*
  * Support for jffs2 on top of NAND-flash
  * Support for jffs2 on top of NAND-flash
  *
  *
@@ -290,7 +290,7 @@ static inline void *get_fl_mem(u32 off, u32 size, void *ext_buf)
 		return get_fl_mem_nor(off);
 		return get_fl_mem_nor(off);
 #endif
 #endif
 
 
-#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
+#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CONFIG_NEW_NAND_CODE)
 	if (id->type == MTD_DEV_TYPE_NAND)
 	if (id->type == MTD_DEV_TYPE_NAND)
 		return get_fl_mem_nand(off, size, ext_buf);
 		return get_fl_mem_nand(off, size, ext_buf);
 #endif
 #endif
@@ -308,7 +308,7 @@ static inline void *get_node_mem(u32 off)
 		return get_node_mem_nor(off);
 		return get_node_mem_nor(off);
 #endif
 #endif
 
 
-#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
+#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CONFIG_NEW_NAND_CODE)
 	if (id->type == MTD_DEV_TYPE_NAND)
 	if (id->type == MTD_DEV_TYPE_NAND)
 		return get_node_mem_nand(off);
 		return get_node_mem_nand(off);
 #endif
 #endif
@@ -319,7 +319,7 @@ static inline void *get_node_mem(u32 off)
 
 
 static inline void put_fl_mem(void *buf)
 static inline void put_fl_mem(void *buf)
 {
 {
-#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
+#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CONFIG_NEW_NAND_CODE)
 	struct mtdids *id = current_part->dev->id;
 	struct mtdids *id = current_part->dev->id;
 
 
 	if (id->type == MTD_DEV_TYPE_NAND)
 	if (id->type == MTD_DEV_TYPE_NAND)

+ 15 - 24
fs/jffs2/jffs2_nand_1pass.c

@@ -1,6 +1,6 @@
 #include <common.h>
 #include <common.h>
 
 
-#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
+#if defined(CONFIG_NEW_NAND_CODE) && (CONFIG_COMMANDS & CFG_CMD_JFFS2)
 
 
 #include <malloc.h>
 #include <malloc.h>
 #include <linux/stat.h>
 #include <linux/stat.h>
@@ -12,12 +12,12 @@
 
 
 #include "jffs2_nand_private.h"
 #include "jffs2_nand_private.h"
 
 
-#define	NODE_CHUNK  	1024	/* size of memory allocation chunk in b_nodes */
+#define	NODE_CHUNK	1024	/* size of memory allocation chunk in b_nodes */
 
 
 /* Debugging switches */
 /* Debugging switches */
 #undef	DEBUG_DIRENTS		/* print directory entry list after scan */
 #undef	DEBUG_DIRENTS		/* print directory entry list after scan */
 #undef	DEBUG_FRAGMENTS		/* print fragment list after scan */
 #undef	DEBUG_FRAGMENTS		/* print fragment list after scan */
-#undef	DEBUG  			/* enable debugging messages */
+#undef	DEBUG			/* enable debugging messages */
 
 
 #ifdef  DEBUG
 #ifdef  DEBUG
 # define DEBUGF(fmt,args...)	printf(fmt ,##args)
 # define DEBUGF(fmt,args...)	printf(fmt ,##args)
@@ -25,7 +25,6 @@
 # define DEBUGF(fmt,args...)
 # define DEBUGF(fmt,args...)
 #endif
 #endif
 
 
-static int nanddev = -1; /* nand device of current partition */
 static nand_info_t *nand;
 static nand_info_t *nand;
 
 
 /* Compression names */
 /* Compression names */
@@ -385,10 +384,10 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)
 				continue;
 				continue;
 
 
 			if (jDir->version == version && inode != 0) {
 			if (jDir->version == version && inode != 0) {
-			    	/* I'm pretty sure this isn't legal */
+				/* I'm pretty sure this isn't legal */
 				putstr(" ** ERROR ** ");
 				putstr(" ** ERROR ** ");
-//				putnstr(jDir->name, jDir->nsize);
-//				putLabeledWord(" has dup version =", version);
+/*				putnstr(jDir->name, jDir->nsize); */
+/*				putLabeledWord(" has dup version =", version); */
 			}
 			}
 			inode = jDir->ino;
 			inode = jDir->ino;
 			version = jDir->version;
 			version = jDir->version;
@@ -574,15 +573,15 @@ jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino)
 	/* we need to search all and return the inode with the highest version */
 	/* we need to search all and return the inode with the highest version */
 	for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) {
 	for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) {
 		if (ino == jDir->ino) {
 		if (ino == jDir->ino) {
-		    	if (jDir->version < version)
+			if (jDir->version < version)
 				continue;
 				continue;
 
 
 			if (jDir->version == version && jDirFoundType) {
 			if (jDir->version == version && jDirFoundType) {
-			    	/* I'm pretty sure this isn't legal */
+				/* I'm pretty sure this isn't legal */
 				putstr(" ** ERROR ** ");
 				putstr(" ** ERROR ** ");
-//				putnstr(jDir->name, jDir->nsize);
-//				putLabeledWord(" has dup version (resolve) = ",
-//					version);
+/*				putnstr(jDir->name, jDir->nsize); */
+/*				putLabeledWord(" has dup version (resolve) = ", */
+/*					version); */
 			}
 			}
 
 
 			jDirFoundType = jDir->type;
 			jDirFoundType = jDir->type;
@@ -686,12 +685,6 @@ jffs2_1pass_rescan_needed(struct part_info *part)
 		return 1;
 		return 1;
 	}
 	}
 
 
-#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
-	if (nanddev != (int)part->usr_priv - 1) {
-		DEBUGF ("rescan: nand device changed\n");
-		return -1;
-	}
-#endif /* defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) */
 	/* FIXME */
 	/* FIXME */
 #if 0
 #if 0
 	/* but suppose someone reflashed a partition at the same offset... */
 	/* but suppose someone reflashed a partition at the same offset... */
@@ -806,10 +799,8 @@ jffs2_1pass_build_lists(struct part_info * part)
 	u32 counterF = 0;
 	u32 counterF = 0;
 	u32 counterN = 0;
 	u32 counterN = 0;
 
 
-#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
-	nanddev = (int)part->usr_priv - 1;
-	nand = &nand_info[nanddev];
-#endif /* defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) */
+	struct mtdids *id = part->dev->id;
+	nand = nand_info + id->num;
 
 
 	/* if we are building a list we need to refresh the cache. */
 	/* if we are building a list we need to refresh the cache. */
 	jffs_init_1pass_list(part);
 	jffs_init_1pass_list(part);
@@ -993,7 +984,7 @@ jffs2_1pass_load(char *dest, struct part_info * part, const char *fname)
 	long ret = 0;
 	long ret = 0;
 	u32 inode;
 	u32 inode;
 
 
-	if (! (pl  = jffs2_get_list(part, "load")))
+	if (! (pl = jffs2_get_list(part, "load")))
 		return 0;
 		return 0;
 
 
 	if (! (inode = jffs2_1pass_search_inode(pl, fname, 1))) {
 	if (! (inode = jffs2_1pass_search_inode(pl, fname, 1))) {
@@ -1025,7 +1016,7 @@ jffs2_1pass_info(struct part_info * part)
 	struct b_lists *pl;
 	struct b_lists *pl;
 	int i;
 	int i;
 
 
-	if (! (pl  = jffs2_get_list(part, "info")))
+	if (! (pl = jffs2_get_list(part, "info")))
 		return 0;
 		return 0;
 
 
 	jffs2_1pass_fill_info(pl, &info);
 	jffs2_1pass_fill_info(pl, &info);

+ 8 - 0
include/asm-arm/io.h

@@ -58,6 +58,14 @@ extern void __raw_readsl(unsigned int addr, void *data, int longlen);
 #define __raw_readw(a)			__arch_getw(a)
 #define __raw_readw(a)			__arch_getw(a)
 #define __raw_readl(a)			__arch_getl(a)
 #define __raw_readl(a)			__arch_getl(a)
 
 
+#define writeb(v,a)			__arch_putb(v,a)
+#define writew(v,a)			__arch_putw(v,a)
+#define writel(v,a)			__arch_putl(v,a)
+
+#define readb(a)			__arch_getb(a)
+#define readw(a)			__arch_getw(a)
+#define readl(a)			__arch_getl(a)
+
 /*
 /*
  * The compiler seems to be incapable of optimising constants
  * The compiler seems to be incapable of optimising constants
  * properly.  Spell it out to the compiler in some cases.
  * properly.  Spell it out to the compiler in some cases.

+ 265 - 0
include/configs/netstar.h

@@ -0,0 +1,265 @@
+/*
+ * (C) Copyright 2005 2N TELEKOMUNIKACE, Ladislav Michl
+ *
+ * Configuation settings for the TI OMAP NetStar board.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/omap1510.h>
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_ARM925T	1		/* This is an arm925t CPU */
+#define CONFIG_OMAP	1		/* in a TI OMAP core */
+#define CONFIG_OMAP1510 1		/* which is in a 5910 */
+
+/* Input clock of PLL */
+#define CONFIG_SYS_CLK_FREQ	150000000	/* 150MHz input clock */
+#define CONFIG_XTAL_FREQ	12000000
+
+#undef CONFIG_USE_IRQ			/* we don't need IRQ/FIQ stuff */
+
+#define CONFIG_MISC_INIT_R		/* There is nothing to really init */
+#define BOARD_LATE_INIT			/* but we flash the LEDs here */
+
+#define CONFIG_CMDLINE_TAG		1	/* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS	1
+#define CONFIG_INITRD_TAG		1
+
+#define CFG_DEVICE_NULLDEV		1	/* enable null device */
+#define CONFIG_SILENT_CONSOLE		1	/* enable silent startup */
+
+/*
+ * Physical Memory Map
+ */
+#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */
+#define PHYS_SDRAM_1		0x10000000	/* SDRAM Bank #1 */
+#define PHYS_FLASH_1		0x00000000	/* Flash Bank #1 */
+
+/*
+ * FLASH organization
+ */
+#define CFG_FLASH_BASE		PHYS_FLASH_1
+#define CFG_MAX_FLASH_BANKS	1
+#if (PHYS_SDRAM_1_SIZE == SZ_32M)
+/*#if 1*/
+#define CFG_FLASH_CFI			/* Flash is CFI conformant */
+#define CFG_FLASH_CFI_DRIVER		/* Use the common driver */
+#define CFG_FLASH_EMPTY_INFO
+#define CFG_MAX_FLASH_SECT	128
+#else
+#define PHYS_FLASH_1_SIZE	SZ_1M
+#define CFG_MAX_FLASH_SECT	19
+#define CFG_FLASH_ERASE_TOUT	(5*CFG_HZ) /* in ticks */
+#define CFG_FLASH_WRITE_TOUT	(5*CFG_HZ)
+#endif
+
+#define CFG_MONITOR_BASE	PHYS_FLASH_1
+#define CFG_MONITOR_LEN		SZ_256K
+
+/*
+ * Environment settings
+ */
+#define CFG_ENV_IS_IN_FLASH
+#define ENV_IS_SOLITARY
+#define CFG_ENV_ADDR		0x4000
+#define CFG_ENV_SIZE		SZ_8K
+#define CFG_ENV_SECT_SIZE	SZ_8K
+#define CFG_ENV_ADDR_REDUND	0x6000
+#define CFG_ENV_SIZE_REDUND	CFG_ENV_SIZE
+#define CONFIG_ENV_OVERWRITE
+
+/*
+ * Size of malloc() pool
+ */
+#define CFG_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */
+/* XXX #define CFG_MALLOC_LEN		(SZ_64K - CFG_GBL_DATA_SIZE)*/
+#define CFG_MALLOC_LEN		SZ_4M
+
+/*
+ * The stack size is set up in start.S using the settings below
+ */
+/* XXX #define CONFIG_STACKSIZE	SZ_8K	/XXX* regular stack */
+#define CONFIG_STACKSIZE	SZ_1M	/* regular stack */
+
+/*
+ * Hardware drivers
+ */
+#define CONFIG_DRIVER_SMC91111
+#define CONFIG_SMC91111_BASE	0x04000300
+
+/*
+ * NS16550 Configuration
+ */
+#define CFG_NS16550
+#define CFG_NS16550_SERIAL
+#define CFG_NS16550_REG_SIZE	(-4)
+#define CFG_NS16550_CLK		(CONFIG_XTAL_FREQ)	/* can be 12M/32Khz or 48Mhz  */
+#define CFG_NS16550_COM1	OMAP1510_UART1_BASE	/* uart1 */
+
+#define CONFIG_CONS_INDEX	1
+#define CONFIG_BAUDRATE		115200
+#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*#define CONFIG_SKIP_RELOCATE_UBOOT*/
+/*#define CONFIG_SKIP_LOWLEVEL_INIT */
+
+/*
+ * NAND flash
+ */
+#define CFG_MAX_NAND_DEVICE	1
+#define CFG_NAND_BASE	0x04000000 + (2 << 23)
+#define CONFIG_NEW_NAND_CODE
+
+/*
+ * JFFS2 partitions (mtdparts command line support)
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT		"nor0=omapflash.0,nand0=omapnand.0"
+#define MTDPARTS_DEFAULT	"mtdparts=omapflash.0:8k@16k(env),8k(r_env),448k@576k(u-boot);omapnand.0:48M(rootfs0),48M(rootfs1),-(data)"
+
+#if 0
+#define CONFIG_COMMANDS		(CFG_CMD_BDI    | \
+				 CFG_CMD_BOOTD  | \
+				 CFG_CMD_DHCP   | \
+				 CFG_CMD_ENV	| \
+				 CFG_CMD_FLASH  | \
+				 CFG_CMD_IMI    | \
+				 CFG_CMD_LOADB  | \
+				 CFG_CMD_NET    | \
+				 CFG_CMD_MEMORY | \
+				 CFG_CMD_PING   | \
+				 CFG_CMD_RUN)
+
+#else
+#define CONFIG_COMMANDS		(CFG_CMD_BDI    | \
+				 CFG_CMD_BOOTD  | \
+				 CFG_CMD_DHCP   | \
+				 CFG_CMD_ENV	| \
+				 CFG_CMD_FLASH  | \
+				 CFG_CMD_NAND	| \
+				 CFG_CMD_IMI    | \
+				 CFG_CMD_JFFS2	| \
+				 CFG_CMD_LOADB  | \
+				 CFG_CMD_NET    | \
+				 CFG_CMD_MEMORY | \
+				 CFG_CMD_PING   | \
+				 CFG_CMD_RUN)
+
+#define CONFIG_JFFS2_NAND	1	/* jffs2 on nand support */
+#endif
+
+#define CONFIG_BOOTP_MASK	CONFIG_BOOTP_DEFAULT
+#define CONFIG_LOOPW
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#define CONFIG_BOOTDELAY	3
+#define CONFIG_ZERO_BOOTDELAY_CHECK	/* allow to break in always */
+#undef  CONFIG_BOOTARGS		/* the boot command will set bootargs*/
+#define CFG_AUTOLOAD		"n"		/* No autoload */
+#define CONFIG_BOOTCOMMAND	"run nboot"
+#define CONFIG_PREBOOT		"run setup"
+#define	CONFIG_EXTRA_ENV_SETTINGS				\
+	"setup=setenv bootargs console=ttyS0,$baudrate "	\
+		"$mtdparts\0"					\
+	"ospart=0\0"						\
+	"setpart="						\
+	"if test -n $swapos; then "				\
+		"if test $ospart -eq 0; then chpart nand0,1; else chpart nand0,0; fi; "\
+		"setenv swapos; saveenv; "			\
+	"else "							\
+		"chpart nand0,$ospart; "			\
+	"fi\0"							\
+	"nfsargs=setenv bootargs $bootargs "			\
+		"ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname::off " \
+		"nfsroot=$rootpath root=/dev/nfs\0"		\
+	"flashargs=run setpart;setenv bootargs $bootargs "	\
+		"root=/dev/mtdblock$partition ro "		\
+		"rootfstype=jffs2\0"				\
+	"initrdargs=setenv bootargs $bootargs "			\
+		"ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname::off\0" \
+	"iboot=bootp;run initrdargs;tftp;bootm\0"		\
+	"fboot=run flashargs;fsload /boot/uImage;bootm\0"	\
+	"nboot=bootp;run nfsargs;tftp;bootm\0"
+
+#if 0	/* feel free to disable for development */
+#define	CONFIG_AUTOBOOT_KEYED		/* Enable password protection	*/
+#define CONFIG_AUTOBOOT_PROMPT	"\nNetStar PBX - boot in %d sec...\n"
+#define CONFIG_AUTOBOOT_DELAY_STR	"R"	/* 1st "password"	*/
+#define CONFIG_BOOT_RETRY_TIME	30
+#endif
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP				/* undef to save memory		*/
+#define CFG_PROMPT		"# "		/* Monitor Command Prompt	*/
+#define CFG_CBSIZE		256		/* Console I/O Buffer Size	*/
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS		16		/* max number of command args	*/
+#define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size	*/
+
+#define CFG_HUSH_PARSER
+#define CFG_PROMPT_HUSH_PS2	"> "
+#define CONFIG_AUTO_COMPLETE
+
+#define CFG_MEMTEST_START	PHYS_SDRAM_1
+#define CFG_MEMTEST_END		PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE
+
+#undef	CFG_CLKS_IN_HZ		/* everything, incl board info, in Hz */
+
+#define CFG_LOAD_ADDR		PHYS_SDRAM_1 + 0x400000	/* default load address */
+
+/* The 1510 has 3 timers, they can be driven by the RefClk (12Mhz) or by DPLL1.
+ * This time is further subdivided by a local divisor.
+ */
+#define CFG_TIMERBASE		OMAP1510_TIMER1_BASE
+#define CFG_PVT			7		/* 2^(pvt+1), divide by 256 */
+#define CFG_HZ			((CONFIG_SYS_CLK_FREQ)/(2 << CFG_PVT))
+
+#define OMAP5910_DPLL_DIV	1
+#define OMAP5910_DPLL_MUL	((CONFIG_SYS_CLK_FREQ * \
+				 (1 << OMAP5910_DPLL_DIV)) / CONFIG_XTAL_FREQ)
+
+#define OMAP5910_ARM_PER_DIV	2	/* CKL/4 */
+#define OMAP5910_LCD_DIV	2	/* CKL/4 */
+#define OMAP5910_ARM_DIV	0	/* CKL/1 */
+#define OMAP5910_DSP_DIV	0	/* CKL/1 */
+#define OMAP5910_TC_DIV		1	/* CKL/2 */
+#define OMAP5910_DSP_MMU_DIV	1	/* CKL/2 */
+#define OMAP5910_ARM_TIM_SEL	1	/* CKL used for MPU timers */
+
+#define OMAP5910_ARM_EN_CLK	0x03d6	/* 0000 0011 1101 0110b  Clock Enable */
+#define OMAP5910_ARM_CKCTL	((OMAP5910_ARM_PER_DIV)  |	\
+				 (OMAP5910_LCD_DIV << 2) |	\
+				 (OMAP5910_ARM_DIV << 4) |	\
+				 (OMAP5910_DSP_DIV << 6) |	\
+				 (OMAP5910_TC_DIV << 8) |	\
+				 (OMAP5910_DSP_MMU_DIV << 10) |	\
+				 (OMAP5910_ARM_TIM_SEL << 12))
+
+#endif	/* __CONFIG_H */

+ 24 - 24
include/linux/mtd/mtd-abi.h

@@ -1,7 +1,7 @@
 /*
 /*
  * $Id: mtd-abi.h,v 1.7 2004/11/23 15:37:32 gleixner Exp $
  * $Id: mtd-abi.h,v 1.7 2004/11/23 15:37:32 gleixner Exp $
  *
  *
- * Portions of MTD ABI definition which are shared by kernel and user space 
+ * Portions of MTD ABI definition which are shared by kernel and user space
  */
  */
 
 
 #ifndef __MTD_ABI_H__
 #ifndef __MTD_ABI_H__
@@ -27,17 +27,17 @@ struct mtd_oob_buf {
 #define MTD_OTHER		14
 #define MTD_OTHER		14
 #define MTD_UNKNOWN		15
 #define MTD_UNKNOWN		15
 
 
-#define MTD_CLEAR_BITS		1       // Bits can be cleared (flash)
-#define MTD_SET_BITS		2       // Bits can be set
-#define MTD_ERASEABLE		4       // Has an erase function
-#define MTD_WRITEB_WRITEABLE	8       // Direct IO is possible
-#define MTD_VOLATILE		16      // Set for RAMs
-#define MTD_XIP			32	// eXecute-In-Place possible
-#define MTD_OOB			64	// Out-of-band data (NAND flash)
-#define MTD_ECC			128	// Device capable of automatic ECC
-#define MTD_NO_VIRTBLOCKS	256	// Virtual blocks not allowed
+#define MTD_CLEAR_BITS		1       /* Bits can be cleared (flash) */
+#define MTD_SET_BITS		2       /* Bits can be set */
+#define MTD_ERASEABLE		4       /* Has an erase function */
+#define MTD_WRITEB_WRITEABLE	8       /* Direct IO is possible */
+#define MTD_VOLATILE		16      /* Set for RAMs */
+#define MTD_XIP			32	/* eXecute-In-Place possible */
+#define MTD_OOB			64	/* Out-of-band data (NAND flash) */
+#define MTD_ECC			128	/* Device capable of automatic ECC */
+#define MTD_NO_VIRTBLOCKS	256	/* Virtual blocks not allowed */
 
 
-// Some common devices / combinations of capabilities
+/* Some common devices / combinations of capabilities */
 #define MTD_CAP_ROM		0
 #define MTD_CAP_ROM		0
 #define MTD_CAP_RAM		(MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
 #define MTD_CAP_RAM		(MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
 #define MTD_CAP_NORFLASH        (MTD_CLEAR_BITS|MTD_ERASEABLE)
 #define MTD_CAP_NORFLASH        (MTD_CLEAR_BITS|MTD_ERASEABLE)
@@ -45,31 +45,31 @@ struct mtd_oob_buf {
 #define MTD_WRITEABLE		(MTD_CLEAR_BITS|MTD_SET_BITS)
 #define MTD_WRITEABLE		(MTD_CLEAR_BITS|MTD_SET_BITS)
 
 
 
 
-// Types of automatic ECC/Checksum available
-#define MTD_ECC_NONE		0 	// No automatic ECC available
-#define MTD_ECC_RS_DiskOnChip	1	// Automatic ECC on DiskOnChip
-#define MTD_ECC_SW		2	// SW ECC for Toshiba & Samsung devices
+/* Types of automatic ECC/Checksum available */
+#define MTD_ECC_NONE		0 	/* No automatic ECC available */
+#define MTD_ECC_RS_DiskOnChip	1	/* Automatic ECC on DiskOnChip */
+#define MTD_ECC_SW		2	/* SW ECC for Toshiba & Samsung devices */
 
 
 /* ECC byte placement */
 /* ECC byte placement */
-#define MTD_NANDECC_OFF		0	// Switch off ECC (Not recommended)
-#define MTD_NANDECC_PLACE	1	// Use the given placement in the structure (YAFFS1 legacy mode)
-#define MTD_NANDECC_AUTOPLACE	2	// Use the default placement scheme
-#define MTD_NANDECC_PLACEONLY	3	// Use the given placement in the structure (Do not store ecc result on read)
-#define MTD_NANDECC_AUTOPL_USR 	4	// Use the given autoplacement scheme rather than using the default
+#define MTD_NANDECC_OFF		0	/* Switch off ECC (Not recommended) */
+#define MTD_NANDECC_PLACE	1	/* Use the given placement in the structure (YAFFS1 legacy mode) */
+#define MTD_NANDECC_AUTOPLACE	2	/* Use the default placement scheme */
+#define MTD_NANDECC_PLACEONLY	3	/* Use the given placement in the structure (Do not store ecc result on read) */
+#define MTD_NANDECC_AUTOPL_USR 	4	/* Use the given autoplacement scheme rather than using the default */
 
 
 struct mtd_info_user {
 struct mtd_info_user {
 	uint8_t type;
 	uint8_t type;
 	uint32_t flags;
 	uint32_t flags;
-	uint32_t size;	 // Total size of the MTD
+	uint32_t size;	 /* Total size of the MTD */
 	uint32_t erasesize;
 	uint32_t erasesize;
-	uint32_t oobblock;  // Size of OOB blocks (e.g. 512)
-	uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
+	uint32_t oobblock;  /* Size of OOB blocks (e.g. 512) */
+	uint32_t oobsize;   /* Amount of OOB data per block (e.g. 16) */
 	uint32_t ecctype;
 	uint32_t ecctype;
 	uint32_t eccsize;
 	uint32_t eccsize;
 };
 };
 
 
 struct region_info_user {
 struct region_info_user {
-	uint32_t offset;		/* At which this region starts, 
+	uint32_t offset;		/* At which this region starts,
 					 * from the beginning of the MTD */
 					 * from the beginning of the MTD */
 	uint32_t erasesize;		/* For this region */
 	uint32_t erasesize;		/* For this region */
 	uint32_t numblocks;		/* Number of blocks in this region */
 	uint32_t numblocks;		/* Number of blocks in this region */

+ 17 - 17
include/linux/mtd/mtd.h

@@ -1,4 +1,4 @@
-/* 
+/*
  * $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $
  * $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $
  *
  *
  * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
  * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
@@ -46,7 +46,7 @@ struct mtd_erase_region_info {
 struct mtd_info {
 struct mtd_info {
 	u_char type;
 	u_char type;
 	u_int32_t flags;
 	u_int32_t flags;
-	u_int32_t size;	 // Total size of the MTD
+	u_int32_t size;	 /* Total size of the MTD */
 
 
 	/* "Major" erase size for the device. Naïve users may take this
 	/* "Major" erase size for the device. Naïve users may take this
 	 * to be the only erase size available, or may use the more detailed
 	 * to be the only erase size available, or may use the more detailed
@@ -54,25 +54,25 @@ struct mtd_info {
 	 */
 	 */
 	u_int32_t erasesize;
 	u_int32_t erasesize;
 
 
-	u_int32_t oobblock;  // Size of OOB blocks (e.g. 512)
-	u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
-	u_int32_t oobavail;  // Number of bytes in OOB area available for fs 
+	u_int32_t oobblock;  /* Size of OOB blocks (e.g. 512) */
+	u_int32_t oobsize;   /* Amount of OOB data per block (e.g. 16) */
+	u_int32_t oobavail;  /* Number of bytes in OOB area available for fs  */
 	u_int32_t ecctype;
 	u_int32_t ecctype;
 	u_int32_t eccsize;
 	u_int32_t eccsize;
-	
 
 
-	// Kernel-only stuff starts here.
+
+	/* Kernel-only stuff starts here. */
 	char *name;
 	char *name;
 	int index;
 	int index;
 
 
-	// oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO)
+	/* oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) */
 	struct nand_oobinfo oobinfo;
 	struct nand_oobinfo oobinfo;
 
 
 	/* Data for variable erase regions. If numeraseregions is zero,
 	/* Data for variable erase regions. If numeraseregions is zero,
-	 * it means that the whole device has erasesize as given above. 
+	 * it means that the whole device has erasesize as given above.
 	 */
 	 */
 	int numeraseregions;
 	int numeraseregions;
-	struct mtd_erase_region_info *eraseregions; 
+	struct mtd_erase_region_info *eraseregions;
 
 
 	/* This really shouldn't be here. It can go away in 2.5 */
 	/* This really shouldn't be here. It can go away in 2.5 */
 	u_int32_t bank_size;
 	u_int32_t bank_size;
@@ -95,10 +95,10 @@ struct mtd_info {
 	int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 	int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 	int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
 	int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
 
 
-	/* 
-	 * Methods to access the protection register area, present in some 
+	/*
+	 * Methods to access the protection register area, present in some
 	 * flash devices. The user data is one time programmable but the
 	 * flash devices. The user data is one time programmable but the
-	 * factory data is read only. 
+	 * factory data is read only.
 	 */
 	 */
 	int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 	int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 
 
@@ -109,14 +109,14 @@ struct mtd_info {
 #if 0
 #if 0
 	/* kvec-based read/write methods. We need these especially for NAND flash,
 	/* kvec-based read/write methods. We need these especially for NAND flash,
 	   with its limited number of write cycles per erase.
 	   with its limited number of write cycles per erase.
-	   NB: The 'count' parameter is the number of _vectors_, each of 
+	   NB: The 'count' parameter is the number of _vectors_, each of
 	   which contains an (ofs, len) tuple.
 	   which contains an (ofs, len) tuple.
 	*/
 	*/
 	int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen);
 	int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen);
-	int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, 
+	int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from,
 		size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
 		size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
 	int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
 	int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
-	int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, 
+	int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to,
 		size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
 		size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
 #endif
 #endif
 	/* Sync */
 	/* Sync */
@@ -179,7 +179,7 @@ int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
 #define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
 #define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
 #define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
 #define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
 #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
 #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
-#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd);  } while (0) 
+#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd);  } while (0)
 
 
 
 
 #ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_PARTITIONS

+ 22 - 22
include/linux/mtd/nand.h

@@ -24,7 +24,7 @@
  *			bat later if I did something naughty.
  *			bat later if I did something naughty.
  *   10-11-2000 SJH     Added private NAND flash structure for driver
  *   10-11-2000 SJH     Added private NAND flash structure for driver
  *   10-24-2000 SJH     Added prototype for 'nand_scan' function
  *   10-24-2000 SJH     Added prototype for 'nand_scan' function
- *   10-29-2001 TG	changed nand_chip structure to support 
+ *   10-29-2001 TG	changed nand_chip structure to support
  *			hardwarespecific function for accessing control lines
  *			hardwarespecific function for accessing control lines
  *   02-21-2002 TG	added support for different read/write adress and
  *   02-21-2002 TG	added support for different read/write adress and
  *			ready/busy line access function
  *			ready/busy line access function
@@ -36,14 +36,14 @@
  *			CONFIG_MTD_NAND_ECC_JFFS2 is not set
  *			CONFIG_MTD_NAND_ECC_JFFS2 is not set
  *   08-10-2002 TG	extensions to nand_chip structure to support HW-ECC
  *   08-10-2002 TG	extensions to nand_chip structure to support HW-ECC
  *
  *
- *   08-29-2002 tglx 	nand_chip structure: data_poi for selecting 
+ *   08-29-2002 tglx 	nand_chip structure: data_poi for selecting
  *			internal / fs-driver buffer
  *			internal / fs-driver buffer
  *			support for 6byte/512byte hardware ECC
  *			support for 6byte/512byte hardware ECC
  *			read_ecc, write_ecc extended for different oob-layout
  *			read_ecc, write_ecc extended for different oob-layout
  *			oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,
  *			oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,
  *			NAND_YAFFS_OOB
  *			NAND_YAFFS_OOB
  *  11-25-2002 tglx	Added Manufacturer code FUJITSU, NATIONAL
  *  11-25-2002 tglx	Added Manufacturer code FUJITSU, NATIONAL
- *			Split manufacturer and device ID structures 
+ *			Split manufacturer and device ID structures
  *
  *
  *  02-08-2004 tglx 	added option field to nand structure for chip anomalities
  *  02-08-2004 tglx 	added option field to nand structure for chip anomalities
  *  05-25-2004 tglx 	added bad block table support, ST-MICRO manufacturer id
  *  05-25-2004 tglx 	added bad block table support, ST-MICRO manufacturer id
@@ -120,7 +120,7 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
 #define NAND_STATUS_READY	0x40
 #define NAND_STATUS_READY	0x40
 #define NAND_STATUS_WP		0x80
 #define NAND_STATUS_WP		0x80
 
 
-/* 
+/*
  * Constants for ECC_MODES
  * Constants for ECC_MODES
  */
  */
 
 
@@ -162,12 +162,12 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
 #define NAND_CACHEPRG		0x00000008
 #define NAND_CACHEPRG		0x00000008
 /* Chip has copy back function */
 /* Chip has copy back function */
 #define NAND_COPYBACK		0x00000010
 #define NAND_COPYBACK		0x00000010
-/* AND Chip which has 4 banks and a confusing page / block 
+/* AND Chip which has 4 banks and a confusing page / block
  * assignment. See Renesas datasheet for further information */
  * assignment. See Renesas datasheet for further information */
 #define NAND_IS_AND		0x00000020
 #define NAND_IS_AND		0x00000020
 /* Chip has a array of 4 pages which can be read without
 /* Chip has a array of 4 pages which can be read without
  * additional ready /busy waits */
  * additional ready /busy waits */
-#define NAND_4PAGE_ARRAY	0x00000040 
+#define NAND_4PAGE_ARRAY	0x00000040
 
 
 /* Options valid for Samsung large page devices */
 /* Options valid for Samsung large page devices */
 #define NAND_SAMSUNG_LP_OPTIONS \
 #define NAND_SAMSUNG_LP_OPTIONS \
@@ -186,8 +186,8 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
 /* Use a flash based bad block table. This option is passed to the
 /* Use a flash based bad block table. This option is passed to the
  * default bad block table function. */
  * default bad block table function. */
 #define NAND_USE_FLASH_BBT	0x00010000
 #define NAND_USE_FLASH_BBT	0x00010000
-/* The hw ecc generator provides a syndrome instead a ecc value on read 
- * This can only work if we have the ecc bytes directly behind the 
+/* The hw ecc generator provides a syndrome instead a ecc value on read
+ * This can only work if we have the ecc bytes directly behind the
  * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
  * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
 #define NAND_HWECC_SYNDROME	0x00020000
 #define NAND_HWECC_SYNDROME	0x00020000
 
 
@@ -218,7 +218,7 @@ struct nand_chip;
 #if 0
 #if 0
 /**
 /**
  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices
  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices
- * @lock:               protection lock  
+ * @lock:               protection lock
  * @active:		the mtd device which holds the controller currently
  * @active:		the mtd device which holds the controller currently
  */
  */
 struct nand_hw_control {
 struct nand_hw_control {
@@ -229,8 +229,8 @@ struct nand_hw_control {
 
 
 /**
 /**
  * struct nand_chip - NAND Private Flash Chip Data
  * struct nand_chip - NAND Private Flash Chip Data
- * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the flash device 
- * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the flash device 
+ * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
+ * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
  * @read_byte:		[REPLACEABLE] read one byte from the chip
  * @read_byte:		[REPLACEABLE] read one byte from the chip
  * @write_byte:		[REPLACEABLE] write one byte to the chip
  * @write_byte:		[REPLACEABLE] write one byte to the chip
  * @read_word:		[REPLACEABLE] read one word from the chip
  * @read_word:		[REPLACEABLE] read one word from the chip
@@ -253,7 +253,7 @@ struct nand_hw_control {
  *			be provided if a hardware ECC is available
  *			be provided if a hardware ECC is available
  * @erase_cmd:		[INTERN] erase command write function, selectable due to AND support
  * @erase_cmd:		[INTERN] erase command write function, selectable due to AND support
  * @scan_bbt:		[REPLACEABLE] function to scan bad block table
  * @scan_bbt:		[REPLACEABLE] function to scan bad block table
- * @eccmode:		[BOARDSPECIFIC] mode of ecc, see defines 
+ * @eccmode:		[BOARDSPECIFIC] mode of ecc, see defines
  * @eccsize: 		[INTERN] databytes used per ecc-calculation
  * @eccsize: 		[INTERN] databytes used per ecc-calculation
  * @eccbytes: 		[INTERN] number of ecc bytes per ecc-calculation step
  * @eccbytes: 		[INTERN] number of ecc bytes per ecc-calculation step
  * @eccsteps:		[INTERN] number of ecc calculation steps per page
  * @eccsteps:		[INTERN] number of ecc calculation steps per page
@@ -265,7 +265,7 @@ struct nand_hw_control {
  * @phys_erase_shift:	[INTERN] number of address bits in a physical eraseblock
  * @phys_erase_shift:	[INTERN] number of address bits in a physical eraseblock
  * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
  * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
  * @chip_shift:		[INTERN] number of address bits in one chip
  * @chip_shift:		[INTERN] number of address bits in one chip
- * @data_buf:		[INTERN] internal buffer for one page + oob 
+ * @data_buf:		[INTERN] internal buffer for one page + oob
  * @oob_buf:		[INTERN] oob buffer for one eraseblock
  * @oob_buf:		[INTERN] oob buffer for one eraseblock
  * @oobdirty:		[INTERN] indicates that oob_buf must be reinitialized
  * @oobdirty:		[INTERN] indicates that oob_buf must be reinitialized
  * @data_poi:		[INTERN] pointer to a data buffer
  * @data_poi:		[INTERN] pointer to a data buffer
@@ -280,20 +280,20 @@ struct nand_hw_control {
  * @bbt:		[INTERN] bad block table pointer
  * @bbt:		[INTERN] bad block table pointer
  * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash lookup
  * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash lookup
  * @bbt_md:		[REPLACEABLE] bad block table mirror descriptor
  * @bbt_md:		[REPLACEABLE] bad block table mirror descriptor
- * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial bad block scan 
+ * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial bad block scan
  * @controller:		[OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
  * @controller:		[OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
  * @priv:		[OPTIONAL] pointer to private chip date
  * @priv:		[OPTIONAL] pointer to private chip date
  */
  */
- 
+
 struct nand_chip {
 struct nand_chip {
 	void  __iomem	*IO_ADDR_R;
 	void  __iomem	*IO_ADDR_R;
 	void  __iomem 	*IO_ADDR_W;
 	void  __iomem 	*IO_ADDR_W;
-	
+
 	u_char		(*read_byte)(struct mtd_info *mtd);
 	u_char		(*read_byte)(struct mtd_info *mtd);
 	void		(*write_byte)(struct mtd_info *mtd, u_char byte);
 	void		(*write_byte)(struct mtd_info *mtd, u_char byte);
 	u16		(*read_word)(struct mtd_info *mtd);
 	u16		(*read_word)(struct mtd_info *mtd);
 	void		(*write_word)(struct mtd_info *mtd, u16 word);
 	void		(*write_word)(struct mtd_info *mtd, u16 word);
-	
+
 	void		(*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
 	void		(*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
 	void		(*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
 	void		(*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
 	int		(*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
 	int		(*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
@@ -358,7 +358,7 @@ struct nand_chip {
  * @name:  	Identify the device type
  * @name:  	Identify the device type
  * @id:   	device ID code
  * @id:   	device ID code
  * @pagesize:  	Pagesize in bytes. Either 256 or 512 or 0
  * @pagesize:  	Pagesize in bytes. Either 256 or 512 or 0
- *		If the pagesize is 0, then the real pagesize 
+ *		If the pagesize is 0, then the real pagesize
  *		and the eraseize are determined from the
  *		and the eraseize are determined from the
  *		extended id bytes in the chip
  *		extended id bytes in the chip
  * @erasesize: 	Size of an erase block in the flash device.
  * @erasesize: 	Size of an erase block in the flash device.
@@ -387,7 +387,7 @@ struct nand_manufacturers {
 extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 
 
-/** 
+/**
  * struct nand_bbt_descr - bad block table descriptor
  * struct nand_bbt_descr - bad block table descriptor
  * @options:	options for this descriptor
  * @options:	options for this descriptor
  * @pages:	the page(s) where we find the bbt, used with option BBT_ABSPAGE
  * @pages:	the page(s) where we find the bbt, used with option BBT_ABSPAGE
@@ -398,14 +398,14 @@ extern struct nand_manufacturers nand_manuf_ids[];
  * @version:	version read from the bbt page during scan
  * @version:	version read from the bbt page during scan
  * @len:	length of the pattern, if 0 no pattern check is performed
  * @len:	length of the pattern, if 0 no pattern check is performed
  * @maxblocks:	maximum number of blocks to search for a bbt. This number of
  * @maxblocks:	maximum number of blocks to search for a bbt. This number of
- *		blocks is reserved at the end of the device where the tables are 
+ *		blocks is reserved at the end of the device where the tables are
  *		written.
  *		written.
  * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
  * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
  *              bad) block in the stored bbt
  *              bad) block in the stored bbt
- * @pattern:	pattern to identify bad block table or factory marked good / 
+ * @pattern:	pattern to identify bad block table or factory marked good /
  *		bad blocks, can be NULL, if len = 0
  *		bad blocks, can be NULL, if len = 0
  *
  *
- * Descriptor for the bad block table marker and the descriptor for the 
+ * Descriptor for the bad block table marker and the descriptor for the
  * pattern which identifies good and bad blocks. The assumption is made
  * pattern which identifies good and bad blocks. The assumption is made
  * that the pattern and the version count are always located in the oob area
  * that the pattern and the version count are always located in the oob area
  * of the first block.
  * of the first block.

+ 1 - 1
include/nand.h

@@ -24,7 +24,7 @@
 #ifndef _NAND_H_
 #ifndef _NAND_H_
 #define _NAND_H_
 #define _NAND_H_
 
 
-#include <linux_compat.h>
+#include <linux/mtd/compat.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand.h>
 
 

Some files were not shown because too many files changed in this diff